diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/AccountService.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/AccountService.java index ec596586e..f02a5e94e 100644 --- a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/AccountService.java +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/AccountService.java @@ -59,6 +59,10 @@ public class AccountService extends QueueConsumer implements InitializingBean { log.debug("successfully processed, grouping id={}, processed number={}", req.getGroupingSdf01Id(), accountToStatement.size()); } + private void accountUpdateWithBrake(BaseRequest userRequest) { + + } + private AccountSdfToStatementRequestPart responsePart(Long sdf01Id) { AccountSdfToStatementRequestPart responsePart = new AccountSdfToStatementRequestPart(); responsePart.setSdfId(sdf01Id); diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/company/DeleteCompanyController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/company/DeleteCompanyController.java index 35dcd9432..d6555064d 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/company/DeleteCompanyController.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/company/DeleteCompanyController.java @@ -30,7 +30,8 @@ public class DeleteCompanyController extends AbstractQueueController { private final IStateLoader stateLoader; @Autowired - public DeleteCompanyController(IOperator operator, IStateLoader stateLoader) { + public DeleteCompanyController(IOperator operator, + IStateLoader stateLoader) { super(operator); this.stateLoader = stateLoader; } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/securities/CudMoneyMarketSecurityController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/securities/CudMoneyMarketSecurityController.java index 7feceaedb..197c0fe52 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/securities/CudMoneyMarketSecurityController.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/securities/CudMoneyMarketSecurityController.java @@ -20,6 +20,7 @@ import ru.spcex.clearing.backendapi.service.IOperator; import ru.spcex.clearing.backendapi.service.IStateLoader; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.Consts; +import ru.spcex.platform.enumeration.Status; import java.util.Collection; import java.util.Map; @@ -75,7 +76,9 @@ public class CudMoneyMarketSecurityController extends AbstractQueueController { @RequestMapping(method = RequestMethod.GET) @ResponseBody public CommonGetAllResponse getAll() { - Collection> all = stateLoader.getAllMetaTransform(IMDGDistributedNames.Map_MoneyMarketSecurity, MoneyMarketSecurity.class); + Collection> all = stateLoader.getAllMetaTransform(IMDGDistributedNames.Map_MoneyMarketSecurity, + MoneyMarketSecurity.class, + Map.of("workflowStatus", Status.Active.getKey())); CommonGetAllResponse response = new CommonGetAllResponse(); response.fromEntity(all); return response; diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/dictionary/DictionaryBackendGetAll.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/dictionary/DictionaryBackendGetAll.java index 3d6c11aeb..c6c9b71f3 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/dictionary/DictionaryBackendGetAll.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/dictionary/DictionaryBackendGetAll.java @@ -9,25 +9,34 @@ import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Map; @ApiModel(description = "Ответ при получении объектов словаря.") public class DictionaryBackendGetAll extends BasicSpcexResponse { @JsonProperty @ApiModelProperty(value = "Полезная нагрузка") - private DictionaryBackendPayload payload = new DictionaryBackendPayload(); + private IDictionaryPayload payload; public void fromEntity(Collection dictionaryValues) { - var payload = this.getPayload(); + this.payload = new GeneralDictionaryBackendPayload(); + GeneralDictionaryBackendPayload castedPayload = (GeneralDictionaryBackendPayload) payload; for (AbstractDictionary dictionaryValue : dictionaryValues) { var singleItem = new DictionaryBackendGetFields(); singleItem.fromEntity(dictionaryValue); - payload.getItems().add(singleItem); + castedPayload.getItems().add(singleItem); } } + public void addMap(Map m) { + if (this.payload == null) { + this.payload = new SpecificDictionaryBackendPayload(); + } + SpecificDictionaryBackendPayload payloadCasted = (SpecificDictionaryBackendPayload) this.payload; + payloadCasted.getItems().add(m); + } - private static class DictionaryBackendPayload { + public static class GeneralDictionaryBackendPayload implements IDictionaryPayload { private List items = new ArrayList<>(); public List getItems() { @@ -39,11 +48,24 @@ public class DictionaryBackendGetAll extends BasicSpcexResponse { } } - public DictionaryBackendPayload getPayload() { + public static class SpecificDictionaryBackendPayload implements IDictionaryPayload { + @JsonProperty + private List> items = new ArrayList<>(); + + public List> getItems() { + return items; + } + + public void setItems(List> items) { + this.items = items; + } + } + + public IDictionaryPayload getPayload() { return payload; } - public void setPayload(DictionaryBackendPayload payload) { + public void setPayload(IDictionaryPayload payload) { this.payload = payload; } } \ No newline at end of file diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/dictionary/DictionaryBackendGetFields.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/dictionary/DictionaryBackendGetFields.java index fa27898c9..eb91fba9a 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/dictionary/DictionaryBackendGetFields.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/dictionary/DictionaryBackendGetFields.java @@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.annotations.ApiModelProperty; import ru.clearing.platform.dictionary.AbstractDictionary; -public class DictionaryBackendGetFields { +public class DictionaryBackendGetFields implements IDictionaryPayload { @JsonProperty @ApiModelProperty(value = "Идентификатор", example = "1234") private Long id; diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/dictionary/DictionaryBackendGetSingleValueV2.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/dictionary/DictionaryBackendGetSingleValueV2.java new file mode 100644 index 000000000..4db4ef922 --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/dictionary/DictionaryBackendGetSingleValueV2.java @@ -0,0 +1,25 @@ +package ru.spcex.clearing.backendapi.controller.response.entity.dictionary; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse; + +import java.util.HashMap; +import java.util.Map; + +@ApiModel(description = "Ответ при получении объекта словаря.") +public class DictionaryBackendGetSingleValueV2 extends BasicSpcexResponse { + + @JsonProperty + @ApiModelProperty(value = "Поля объекта") + private Map payload = new HashMap<>(); + + public Map getPayload() { + return payload; + } + + public void setPayload(Map payload) { + this.payload = payload; + } +} \ No newline at end of file diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/dictionary/IDictionaryPayload.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/dictionary/IDictionaryPayload.java new file mode 100644 index 000000000..2cba7bac3 --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/response/entity/dictionary/IDictionaryPayload.java @@ -0,0 +1,4 @@ +package ru.spcex.clearing.backendapi.controller.response.entity.dictionary; + +public interface IDictionaryPayload { +} diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/system/DictionaryController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/system/DictionaryController.java index 425bd1876..138735915 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/system/DictionaryController.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/system/DictionaryController.java @@ -13,10 +13,11 @@ import org.springframework.web.bind.annotation.*; import ru.clearing.platform.dictionary.AbstractDictionary; import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse; import ru.spcex.clearing.backendapi.controller.response.entity.dictionary.DictionaryBackendGetAll; -import ru.spcex.clearing.backendapi.controller.response.entity.dictionary.DictionaryBackendGetSingleValue; +import ru.spcex.clearing.backendapi.controller.response.entity.dictionary.DictionaryBackendGetSingleValueV2; import ru.spcex.clearing.backendapi.errors.ActionValidationException; import ru.spcex.clearing.backendapi.errors.BackEndError; import ru.spcex.clearing.backendapi.errors.NotFound404Exception; +import ru.spcex.clearing.backendapi.meta.GetResponseFactory; import ru.spcex.platform.classes.base.SpcexObjectBase; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; @@ -33,10 +34,12 @@ public class DictionaryController { private final Logger log = LoggerFactory.getLogger(getClass()); private final Map> allDictionaryMaps; private final ImdgProvider imdgProvider; + private final GetResponseFactory responseFactory; @Autowired - public DictionaryController(ImdgProvider imdgProvider) { + public DictionaryController(ImdgProvider imdgProvider, GetResponseFactory responseFactory) { this.imdgProvider = imdgProvider; + this.responseFactory = responseFactory; this.allDictionaryMaps = new ConcurrentHashMap<>(); } @@ -49,39 +52,42 @@ public class DictionaryController { Imdg dictionary = extractDictionaryImdgFromUrlParameter(dictionaryName, AbstractDictionary.class); Collection allValues = dictionary.getAllValues(); DictionaryBackendGetAll response = new DictionaryBackendGetAll(); - response.fromEntity(allValues); + for (AbstractDictionary val : allValues) { + Map fromMeta = responseFactory.responseFromDictionary(dictionaryName, val); + response.addMap(fromMeta); + } return response; } @ApiOperation(value = "get dictionary value by id.") - @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = DictionaryBackendGetSingleValue.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)}) + @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = DictionaryBackendGetSingleValueV2.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)}) @RequestMapping(value = "/{dictionary-name}/{id}", method = RequestMethod.GET) @ResponseBody - public DictionaryBackendGetSingleValue getById(@ApiParam(value = "Название словаря", required = true, example = "moneyFlowSide") + public DictionaryBackendGetSingleValueV2 getById(@ApiParam(value = "Название словаря", required = true, example = "moneyFlowSide") @PathVariable("dictionary-name") String dictionaryName, @ApiParam(value = "Идентификатор объекта", required = true, example = "1234") @PathVariable("id") Long id) { Imdg dictionary = extractDictionaryImdgFromUrlParameter(dictionaryName, AbstractDictionary.class); AbstractDictionary value = dictionary.getSingleObjectByID(id); if (value == null) throw new NotFound404Exception(dictionaryName + " id='" + id + "'"); - DictionaryBackendGetSingleValue response = new DictionaryBackendGetSingleValue(); - response.fromEntity(value); + DictionaryBackendGetSingleValueV2 response = new DictionaryBackendGetSingleValueV2(); + response.setPayload(responseFactory.responseFromDictionary(dictionaryName, value)); return response; } @ApiOperation(value = "get dictionary value by code.") - @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = DictionaryBackendGetSingleValue.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)}) + @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = DictionaryBackendGetSingleValueV2.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)}) @RequestMapping(value = "/{dictionary-name}/code/{code}", method = RequestMethod.GET) @ResponseBody - public DictionaryBackendGetSingleValue getByCode(@ApiParam(value = "Название словаря", required = true, example = "moneyFlowSide") + public DictionaryBackendGetSingleValueV2 getByCode(@ApiParam(value = "Название словаря", required = true, example = "moneyFlowSide") @PathVariable("dictionary-name") String dictionaryName, @ApiParam(value = "Код словаря", required = true, example = "1234") @PathVariable("code") String code) { Imdg dictionary = extractDictionaryImdgFromUrlParameter(dictionaryName, AbstractDictionary.class); AbstractDictionary value = dictionary.getSingleObjectByFieldValues(Map.of("code", code)); if (value == null) throw new NotFound404Exception(dictionaryName + " code='" + code + "'"); - DictionaryBackendGetSingleValue response = new DictionaryBackendGetSingleValue(); - response.fromEntity(value); + DictionaryBackendGetSingleValueV2 response = new DictionaryBackendGetSingleValueV2(); + response.setPayload(responseFactory.responseFromDictionary(dictionaryName, value)); return response; } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/meta/ClearingDictionaryExtracted.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/meta/ClearingDictionaryExtracted.java new file mode 100644 index 000000000..dabb4f653 --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/meta/ClearingDictionaryExtracted.java @@ -0,0 +1,22 @@ +package ru.spcex.clearing.backendapi.meta; + +import java.util.List; + +public class ClearingDictionaryExtracted extends ObjectExtracted { + + public ClearingDictionaryExtracted(String clazz, List actionFields) { + for (ActionField field : actionFields) { + if (field.getVirtual() != null && field.isVirtual()){ + continue; + } + FieldExtracted fe = getImplFieldExtracted(field); + fields.add(fe); + fieldByCode.put(field.getCode(), fe); + } + } + + @Override + public FieldExtracted getImplFieldExtracted(ActionField field) { + return new ClearingFieldExtracted(field); + } +} diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/meta/GetResponseFactory.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/meta/GetResponseFactory.java index 86f3cb2c1..e6e23ff8d 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/meta/GetResponseFactory.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/meta/GetResponseFactory.java @@ -31,11 +31,26 @@ public class GetResponseFactory { .collect(Collectors.toList()); } + /** + * dictionaryName - это имя тэга внутри + */ + public Map responseFromDictionary(String dictionaryName, Object o) { + ObjectExtracted objectExtracted = meta.getEnumsExtractedByTagName().get(dictionaryName); + if (objectExtracted == null) { + throw new RuntimeException("cannot find dictionary in meta for " + dictionaryName); + } + return responseFromObjectExtracted(o, objectExtracted); + } + public Map responseFromObject(Object o) { ObjectExtracted objExtr = meta.getObjectsExtractedByClazz().get(o.getClass().getCanonicalName()); if (objExtr == null) { throw new RuntimeException("cannot find object in meta for " + o.getClass().getCanonicalName()); } + return responseFromObjectExtracted(o, objExtr); + } + + private Map responseFromObjectExtracted(Object o, ObjectExtracted objExtr) { Map r = new LinkedHashMap<>(); FieldExtracted currentField = null; try { diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/meta/MetaServer.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/meta/MetaServer.java index be7392a9b..452a5e9af 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/meta/MetaServer.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/meta/MetaServer.java @@ -2,6 +2,7 @@ package ru.spcex.clearing.backendapi.meta; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import ru.spcex.platform.utils.log.ExceptionUtils; import java.lang.reflect.Constructor; import java.lang.reflect.Method; @@ -17,6 +18,8 @@ public class MetaServer extends MetaBase { private Map objectsExtractedByDestination; private Map actionObjectsExtracted; private Map objectElementByDestination; + private Map enumsExtractedByTagName; + private final static Set dictionaryDefaultFields = Set.of("id", "code", "name"); protected ObjectExtracted getImplInstanceObjectExtracted(String clazz, List actionFields) { return new ClearingObjectExtracted(clazz, actionFields); @@ -31,6 +34,7 @@ public class MetaServer extends MetaBase { objectsExtractedByClazz = new ConcurrentHashMap<>(); objectsExtractedByDestination = new ConcurrentHashMap<>(); objectElementByDestination = new ConcurrentHashMap<>(); + enumsExtractedByTagName = new ConcurrentHashMap<>(); try { Map objects = getObjects(); log.info("Meta objects:\n{}", @@ -84,6 +88,37 @@ public class MetaServer extends MetaBase { } catch (Throwable e) { throw new ClearingMetaServerValidationException(e.getLocalizedMessage()); } + try { + Map enums = getEnums(); + for (String key : enums.keySet()) { + ObjectExtracted oe; + ObjectEnumElement objectElement = enums.get(key); + try { + oe = new ClearingDictionaryExtracted(objectElement.getClazz(), objectElement.getFields()); + } catch (Throwable e) { + log.warn("{} {}", key, ExceptionUtils.getStackTrace(e)); + continue; + } + /** + * можно было бы хранить только для нестандартных словарей (где не только id, name, code) + */ +// List dictFields = oe.getFields(); +// boolean add = false; +// for (FieldExtracted dictField : dictFields) { +// if (!dictionaryDefaultFields.contains(dictField.getMemberName())) { +// add = true; +// break; +// } +// } +// if (add) { +// enumsExtractedByTagName.put(key, oe); +// } + enumsExtractedByTagName.put(key, oe); + } + + } catch (Throwable e) { + throw new ClearingMetaServerValidationException(e.getLocalizedMessage()); + } } for (ObjectExtracted o : this.objectsExtracted) { try { @@ -196,4 +231,8 @@ public class MetaServer extends MetaBase { } return partSize; } + + public Map getEnumsExtractedByTagName() { + return enumsExtractedByTagName; + } } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/meta/ObjectExtracted.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/meta/ObjectExtracted.java index 5f75b9de5..8e4fc3cda 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/meta/ObjectExtracted.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/meta/ObjectExtracted.java @@ -5,12 +5,14 @@ import java.util.*; import java.util.concurrent.ConcurrentHashMap; public abstract class ObjectExtracted { - private String className; - private Class clazz; - private List fields = new LinkedList<>(); - private Map fieldByCode = new ConcurrentHashMap<>(); - private boolean isArray = false; + protected String className; + protected Class clazz; + protected List fields = new LinkedList<>(); + protected Map fieldByCode = new ConcurrentHashMap<>(); + protected boolean isArray = false; + public ObjectExtracted() { + } public ObjectExtracted(String clazz, List actionFields) { this.className = clazz; diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/IStateLoader.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/IStateLoader.java index c8caa0caa..b5fd01105 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/IStateLoader.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/IStateLoader.java @@ -13,4 +13,5 @@ public interface IStateLoader { Optional getById(Long id, String mapName, Class clazz); Collection getAll(String mapName, Class clazz); Collection> getAllMetaTransform(String mapName, Class clazz); + Collection> getAllMetaTransform(String mapName, Class clazz, Map> conditions); } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/impl/StateLoaderImpl.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/impl/StateLoaderImpl.java index 8d21ba817..afd00a665 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/impl/StateLoaderImpl.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/impl/StateLoaderImpl.java @@ -44,6 +44,15 @@ public class StateLoaderImpl implements IStateLoader { return responseFactory.responseFromObjectCollection(all); } + @Override + public Collection> getAllMetaTransform(String mapName, + Class clazz, + Map> conditions) { + Imdg imdg = getImdg(mapName, clazz); + Collection all = imdg.getCollectionObjectsByFieldValues(conditions); + return responseFactory.responseFromObjectCollection(all); + } + @SuppressWarnings("unchecked") private Imdg getImdg(String mapName, Class clazz) { return (Imdg) allImdgMaps.computeIfAbsent(mapName, (mapName1) -> imdgProvider.getImdg(mapName, clazz)); diff --git a/clearing-parent/backend-api/src/main/resources/meta/data.xml b/clearing-parent/backend-api/src/main/resources/meta/data.xml index fb7903874..dd892e3c3 100644 --- a/clearing-parent/backend-api/src/main/resources/meta/data.xml +++ b/clearing-parent/backend-api/src/main/resources/meta/data.xml @@ -12,15 +12,13 @@ - - + - - + diff --git a/clearing-parent/backend-api/src/main/resources/meta/meta.xml b/clearing-parent/backend-api/src/main/resources/meta/meta.xml index ce5377bf7..693d0161e 100644 --- a/clearing-parent/backend-api/src/main/resources/meta/meta.xml +++ b/clearing-parent/backend-api/src/main/resources/meta/meta.xml @@ -1,25 +1,25 @@ - + - + - + - + - + @@ -39,7 +39,7 @@ - + @@ -49,200 +49,200 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -254,14 +254,14 @@ - + - + @@ -274,7 +274,7 @@ - + @@ -293,7 +293,7 @@ - + @@ -303,7 +303,7 @@ - + @@ -311,7 +311,7 @@ - + @@ -349,7 +349,7 @@ - + @@ -361,7 +361,7 @@ - + @@ -371,7 +371,7 @@ - + @@ -385,48 +385,69 @@ - + - + - + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + + + - - @@ -436,7 +457,7 @@ - + @@ -470,7 +491,7 @@ - + @@ -488,7 +509,7 @@ - + @@ -501,7 +522,7 @@ - + @@ -532,7 +553,7 @@ - + @@ -545,7 +566,7 @@ - + @@ -575,12 +596,12 @@ - + - + @@ -606,12 +627,12 @@ - + - + @@ -622,7 +643,7 @@ - + @@ -640,7 +661,7 @@ - + @@ -685,19 +706,19 @@ - + - + - + @@ -710,12 +731,12 @@ - + - + @@ -740,7 +761,7 @@ - + @@ -750,11 +771,11 @@ - + - + @@ -766,7 +787,7 @@ - + @@ -777,7 +798,7 @@ - + @@ -820,7 +841,7 @@ - + @@ -834,7 +855,7 @@ - + @@ -851,7 +872,7 @@ - + @@ -887,9 +908,9 @@ - - - + + + @@ -912,9 +933,9 @@ - - - + + + @@ -984,7 +1005,7 @@ - + @@ -996,7 +1017,7 @@ - + @@ -1015,7 +1036,7 @@ - + @@ -1059,7 +1080,7 @@ - + @@ -1098,7 +1119,7 @@ - + @@ -1112,7 +1133,7 @@ - + @@ -1122,24 +1143,24 @@ - + - + - + - + - - + + - + @@ -1151,9 +1172,9 @@ - + - + @@ -1169,7 +1190,7 @@ - + @@ -1181,7 +1202,7 @@ - + @@ -1194,7 +1215,7 @@ - + @@ -1218,7 +1239,7 @@ - + @@ -1236,7 +1257,7 @@ - + @@ -1255,7 +1276,7 @@ - + @@ -1307,7 +1328,7 @@ - + @@ -1359,7 +1380,7 @@ - +
@@ -1368,14 +1389,14 @@ - + - + @@ -1387,7 +1408,7 @@ - + @@ -1400,7 +1421,7 @@ - + @@ -1451,7 +1472,7 @@ - + @@ -1460,7 +1481,7 @@ - + @@ -1510,7 +1531,7 @@ - + @@ -1524,7 +1545,7 @@ - + @@ -1539,7 +1560,7 @@ - + @@ -1549,7 +1570,7 @@ - + @@ -1571,7 +1592,7 @@ - + @@ -1588,7 +1609,7 @@ - + @@ -1602,20 +1623,20 @@ - + - + - - - + + + diff --git a/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/config/KafkaSenderConfig.java b/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/config/KafkaSenderConfig.java new file mode 100644 index 000000000..16e63b03d --- /dev/null +++ b/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/config/KafkaSenderConfig.java @@ -0,0 +1,32 @@ +package ru.spcex.clearing.company.config; + +import org.apache.kafka.clients.producer.Producer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.service.RequestInfo; +import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgId; +import ru.spcex.platform.imdg.api.ImdgProvider; + +@Configuration +public class KafkaSenderConfig { + + @Autowired + @Bean + public KafkaSender kafkaSender(Producer kafkaProducer, + ImdgProvider imdgProvider) { + ImdgId imdgIdGenerator = imdgProvider.getImdgIdGenerator(); + return KafkaSender + .setup() + .producer(kafkaProducer) + .idGenerator(imdgIdGenerator::nextId) + .imdgProvider(s -> { + Imdg imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_RequestInfo, RequestInfo.class); + return imdg::insert; + }) + .build(); + } +} diff --git a/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/service/ProfileDocumentService.java b/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/service/ProfileDocumentService.java new file mode 100644 index 000000000..28990c9f5 --- /dev/null +++ b/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/service/ProfileDocumentService.java @@ -0,0 +1,77 @@ +package ru.spcex.clearing.company.service; + +import org.apache.kafka.clients.consumer.Consumer; +import org.apache.kafka.clients.producer.Producer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.lang.NonNull; +import ru.clearing.classes.statics.data.company.Company; +import ru.clearing.classes.statics.data.profile.ProfileDocument; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.BaseRequest; +import ru.spcex.clearing.platform.messaging.domain.Consts; +import ru.spcex.clearing.platform.messaging.domain.cud.company.ProfileDocumentNewRequest; +import ru.spcex.clearing.platform.messaging.service.QueueConsumer; +import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; + +public class ProfileDocumentService extends QueueConsumer implements InitializingBean { + private final Logger log = LoggerFactory.getLogger(getClass()); + private Imdg profileDocumentMap; + private Imdg companyMap; + private ImdgProvider imdgProvider; + private KafkaSender kafkaReqProducer; + + @Autowired + public ProfileDocumentService(Consumer kafkaQueue, + Producer kafkaProducer, + KafkaSender kafkaReqProducer, + ImdgProvider imdgProvider) { + super(kafkaQueue, kafkaProducer); + this.imdgProvider = imdgProvider; + this.kafkaReqProducer = kafkaReqProducer; + } + + @Override + public void afterPropertiesSet() { + this.profileDocumentMap = imdgProvider.getImdg(IMDGDistributedNames.Map_ProfileDocument, ProfileDocument.class); + this.companyMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class); + + callback(ProfileDocumentNewRequest.class) + .setConsumer(this::newProfileDocument) + .forDestination(Consts.DESTINATION_PROFILE_DOCUMENT_NEW, callbacks::put); + init(); + } + + @NonNull + private void newProfileDocument(BaseRequest profileDocumentNewRequestBaseRequest) { + log.trace("Start processing ProfileDocumentNewRequest!"); + ProfileDocumentNewRequest profileDocumentNewRequest = profileDocumentNewRequestBaseRequest.getRequestPayload(); + Long companyId = profileDocumentNewRequest.getCompanyId(); + Company company = companyMap.getSingleObjectByID(companyId); + if (company != null && !company.getWorkflowStatus().equalsIgnoreCase("ACTV")) { + throw new IllegalStateException("Wrong company with ID " + companyId + " and workflow status " + company.getWorkflowStatus()); + } + ProfileDocument profileDocument = new ProfileDocument(); + profileDocument.setCompanyId(profileDocumentNewRequest.getCompanyId()); + profileDocument.setDocumentType(profileDocumentNewRequest.getDocumentType()); + profileDocument.setIssueDate(profileDocumentNewRequest.getIssueDate()); + profileDocument.setIssuePlace(profileDocumentNewRequest.getIssuePlace()); + profileDocument.setIssuer(profileDocumentNewRequest.getIssuer()); + profileDocument.setIssuerCode(profileDocumentNewRequest.getIssuerCode()); + profileDocument.setName(profileDocumentNewRequest.getName()); + profileDocument.setNumber(profileDocumentNewRequest.getNumber()); + profileDocument.setPlace(profileDocumentNewRequest.getPlace()); + profileDocument.setValidFromDate(profileDocumentNewRequest.getValidFromDate()); + profileDocument.setValidToDate(profileDocumentNewRequest.getValidToDate()); + profileDocument.setLink(profileDocumentNewRequest.getLink()); + profileDocumentMap.insert(profileDocument); + if (profileDocument.getDocumentType().equalsIgnoreCase("XCNT")) { + + //kafkaReqProducer.sendRequestToQueue(Consts.EXPORT_PROCESS, exportRequest); + } + } +} diff --git a/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/ClearingCalendarService.java b/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/ClearingCalendarService.java index 70bd24147..3a86684b7 100644 --- a/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/ClearingCalendarService.java +++ b/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/ClearingCalendarService.java @@ -18,6 +18,8 @@ import ru.spcex.clearing.platform.messaging.service.QueueConsumer; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; +import java.time.Instant; + @Service public class ClearingCalendarService extends QueueConsumer implements InitializingBean { private final Logger log = LoggerFactory.getLogger(getClass()); @@ -33,21 +35,23 @@ public class ClearingCalendarService extends QueueConsumer implements Initializi @Override public void afterPropertiesSet() { callback(ClearingCalendarNewRequest.class) - .setConsumer(this::newTradingCalendar) + .setConsumer(this::newClearingCalendar) .forDestination(Consts.DESTINATION_CLEARING_CALENDAR_NEW, callbacks::put); callback(ClearingCalendarUpdateRequest.class) - .setConsumer(this::updateTradingCalendar) + .setConsumer(this::updateClearingCalendar) .forDestination(Consts.DESTINATION_CLEARING_CALENDAR_UPDATE, callbacks::put); callback(CommonDeleteRequest.class) - .setConsumer(this::deleteTradingCalendar) + .setConsumer(this::deleteClearingCalendar) .forDestination(Consts.DESTINATION_CLEARING_CALENDAR_DELETE, callbacks::put); init(); } - private void newTradingCalendar(BaseRequest userRequest) { + private void newClearingCalendar(BaseRequest userRequest) { ClearingCalendarNewRequest req = userRequest.getRequestPayload(); log.debug("ClearingCalendarNewRequest received"); ClearingCalendar clearingCalendar = new ClearingCalendar(); + Instant created = Instant.now(); + clearingCalendar.setCreated(created); clearingCalendar.setClearingDate(req.getClearingDate()); clearingCalendar.setCompanyId(req.getCompanyId()); clearingCalendar.setDayStatus(req.getDayStatus()); @@ -55,18 +59,20 @@ public class ClearingCalendarService extends QueueConsumer implements Initializi log.debug("successfully processed, new id {}", clearingCalendar.getId()); } - private void updateTradingCalendar(BaseRequest userRequest) { + private void updateClearingCalendar(BaseRequest userRequest) { ClearingCalendarUpdateRequest req = userRequest.getRequestPayload(); log.debug("ClearingCalendarUpdateRequest received"); + Instant updated = Instant.now(); ClearingCalendar clearingCalendar = clearingCalendarMap.getSingleObjectByID(req.getId()); clearingCalendar.setClearingDate(req.getClearingDate()); clearingCalendar.setCompanyId(req.getCompanyId()); clearingCalendar.setDayStatus(req.getDayStatus()); + clearingCalendar.setUpdated(updated); clearingCalendarMap.update(clearingCalendar); log.debug("successfully processed, new id {}", clearingCalendar.getId()); } - private void deleteTradingCalendar(BaseRequest userRequest) { + private void deleteClearingCalendar(BaseRequest userRequest) { CommonDeleteRequest req = userRequest.getRequestPayload(); log.debug("CommonDeleteRequest received id = {}", req.getId()); ClearingCalendar clearingCalendar = clearingCalendarMap.getSingleObjectByID(req.getId()); diff --git a/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/PlannerTemplateService.java b/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/PlannerTemplateService.java index 491e884dc..77a1466a0 100644 --- a/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/PlannerTemplateService.java +++ b/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/PlannerTemplateService.java @@ -50,7 +50,8 @@ public class PlannerTemplateService extends QueueConsumer implements Initializin PlannerTemplateNewRequest req = userRequest.getRequestPayload(); log.debug("PlannerTemplateNewRequest received"); PlannerTemplate plannerTemplate = new PlannerTemplate(); - plannerTemplate.setCreated(Instant.now()); + Instant created = Instant.now(); + plannerTemplate.setCreated(created); plannerTemplate.setTask(req.getTask()); plannerTemplate.setTaskTime(req.getTaskTime()); plannerTemplate.setTaskStatus(req.getTaskStatus()); @@ -64,7 +65,8 @@ public class PlannerTemplateService extends QueueConsumer implements Initializin PlannerTemplateUpdateRequest req = userRequest.getRequestPayload(); log.debug("PlannerTemplateUpdateRequest received"); PlannerTemplate plannerTemplate = plannerTemplateMap.getSingleObjectByID(req.getId()); - plannerTemplate.setUpdated(Instant.now()); + Instant updated = Instant.now(); + plannerTemplate.setUpdated(updated); plannerTemplate.setTask(req.getTask()); plannerTemplate.setTaskTime(req.getTaskTime()); plannerTemplate.setTaskStatus(req.getTaskStatus()); diff --git a/clearing-parent/scheduler-service/src/test/java/ru/specx/clearing/scheduler/config/HazelcastServiceTestConfiguration.java b/clearing-parent/scheduler-service/src/test/java/ru/specx/clearing/scheduler/config/HazelcastServiceTestConfiguration.java new file mode 100644 index 000000000..af55150d0 --- /dev/null +++ b/clearing-parent/scheduler-service/src/test/java/ru/specx/clearing/scheduler/config/HazelcastServiceTestConfiguration.java @@ -0,0 +1,68 @@ +package ru.specx.clearing.scheduler.config; + +import com.hazelcast.config.*; +import com.hazelcast.core.Hazelcast; +import com.hazelcast.core.HazelcastInstance; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import ru.spcex.platform.imdg.iml.hazelcast.config.HazelcastClientParams; +import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService; +import ru.spcex.platform.imdg.iml.hazelcast.util.HazelcastHelper; + +import java.util.List; +import java.util.Random; + +@Configuration +public class HazelcastServiceTestConfiguration { + private HazelcastInstance hazelcastInstance; + + private static ThreadPoolTaskExecutor createThreadPoolTaskExecutor(int maxPoolSz, boolean waitForCompletion) { + ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor(); + if (maxPoolSz > 2) { + pool.setKeepAliveSeconds(60); + pool.setAllowCoreThreadTimeOut(true); + } + pool.setCorePoolSize(maxPoolSz); + pool.setWaitForTasksToCompleteOnShutdown(waitForCompletion); + return pool; + } + + @Bean(name = "hazelcastServiceTest") + public HazelcastService hazelcastService(@Qualifier("taskExecutorHazelcastClientInitializer") ThreadPoolTaskExecutor taskExecutorHazelcastClientInitializer, @Qualifier("taskExecutorIdGeneratorAwaiter") ThreadPoolTaskExecutor taskExecutorIdGeneratorAwaiter, HazelcastClientParams params) { + Config cfg = new Config(); + cfg.setInstanceName("localhost"); + + NetworkConfig networkConfig = new NetworkConfig(); + JoinConfig joinConfig = new JoinConfig(); + joinConfig.setMulticastConfig(new MulticastConfig().setEnabled(false)); + joinConfig.setTcpIpConfig(new TcpIpConfig().setEnabled(true).setMembers(List.of("127.0.0.1"))); + networkConfig.setJoin(joinConfig); + cfg.setNetworkConfig(networkConfig); + hazelcastInstance = Hazelcast.newHazelcastInstance(cfg); + HazelcastHelper.otcSystem_setStorageState(true, hazelcastInstance); + return new HazelcastService(taskExecutorHazelcastClientInitializer, taskExecutorIdGeneratorAwaiter, params); + } + + @Bean(name = "taskExecutorHazelcastClientInitializer") + public ThreadPoolTaskExecutor taskExecutorHazelcastClientInitializer() { + return createThreadPoolTaskExecutor(1, true); + } + + @Bean(name = "taskExecutorIdGeneratorAwaiter") + public ThreadPoolTaskExecutor taskExecutorIdGeneratorAwaiter() { + return createThreadPoolTaskExecutor(1, false); + } + + @Bean(name = "hazelcastClientParams") + public HazelcastClientParams getHazelcastClientParams() { + HazelcastClientParams params = new HazelcastClientParams(); + params.setLogin("dev"); + params.setPassword("dev-pass"); + params.setClusterMembers("127.0.0.1"); + params.setInstanceName("hzTestClient" + new Random().nextInt()); + params.setNearCacheConfig(new NearCacheConfig()); + return params; + } +} diff --git a/clearing-parent/scheduler-service/src/test/java/ru/specx/clearing/scheduler/service/ClearingCalendarServiceTest.java b/clearing-parent/scheduler-service/src/test/java/ru/specx/clearing/scheduler/service/ClearingCalendarServiceTest.java new file mode 100644 index 000000000..7307966f9 --- /dev/null +++ b/clearing-parent/scheduler-service/src/test/java/ru/specx/clearing/scheduler/service/ClearingCalendarServiceTest.java @@ -0,0 +1,138 @@ +package ru.specx.clearing.scheduler.service; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.hazelcast.core.IMap; +import com.hazelcast.map.listener.EntryRemovedListener; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.MockConsumer; +import org.apache.kafka.clients.consumer.OffsetResetStrategy; +import org.apache.kafka.clients.producer.MockProducer; +import org.apache.kafka.common.TopicPartition; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import ru.clearing.classes.statics.data.profile.Contact; +import ru.clearing.classes.statics.data.scheduler.ClearingCalendar; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.ActionType; +import ru.spcex.clearing.platform.messaging.domain.BaseRequest; +import ru.spcex.clearing.platform.messaging.domain.Consts; +import ru.spcex.clearing.platform.messaging.domain.cud.schedule.ClearingCalendarNewRequest; +import ru.spcex.clearing.scheduler.service.ClearingCalendarService; +import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService; +import ru.specx.clearing.scheduler.config.HazelcastServiceTestConfiguration; + +import java.time.Instant; +import java.time.LocalDate; +import java.util.Collections; +import java.util.HashMap; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = { + HazelcastServiceTestConfiguration.class}) +class ClearingCalendarServiceTest { + + private static final int PARTITION = 0; + private static final String TOPIC_CLEARING_CALENDAR_NEW = Consts.DESTINATION_CLEARING_CALENDAR_NEW; + private static final Long ID = 0L; + + @Autowired + @Qualifier("hazelcastServiceTest") + private HazelcastService hazelcastServiceTest; + private MockConsumer mockConsumer; + private MockProducer mockProducer; + + @BeforeEach + void setUp() { + mockConsumer = new MockConsumer<>(OffsetResetStrategy.EARLIEST); + mockProducer = new MockProducer<>(); + } + + /** + * {@link ClearingCalendarService#newTradingCalendar(BaseRequest)}(BaseRequest)}
+ * Тест проверяет создание сущности {@link ClearingCalendar} в Hazelcast при передаче из Apache Kafka.
+ * Входной запрос {@link ClearingCalendarNewRequest}:
+ */ + @Test + public void newClearingCalendarInQueue() throws InterruptedException { + //ARRANGE + + ClearingCalendar clearingCalendar = new ClearingCalendar(); + Instant created = Instant.now(); + clearingCalendar.setCreated(created); + clearingCalendar.setClearingDate(LocalDate.now()); + clearingCalendar.setCompanyId(0L); + clearingCalendar.setDayStatus("STATUS"); + + ClearingCalendarNewRequest clearingCalendarNewRequest = new ClearingCalendarNewRequest(); + clearingCalendarNewRequest.setClearingDate(clearingCalendar.getClearingDate()); + clearingCalendarNewRequest.setCompanyId(clearingCalendar.getCompanyId()); + clearingCalendarNewRequest.setDayStatus(clearingCalendar.getDayStatus()); + + BaseRequest baseNewRequest = new BaseRequest<>(); + baseNewRequest.setRequestPayload(clearingCalendarNewRequest); + baseNewRequest.setId(ID); + baseNewRequest.setActionType(ActionType.NEW); + String jsonBaseForRequest; + ObjectMapper objectMapper = new ObjectMapper(); + try { + jsonBaseForRequest = objectMapper.writeValueAsString(baseNewRequest); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + + //ACT + //service set up + ClearingCalendarService clearingCalendarService = new ClearingCalendarService(mockConsumer, mockProducer, hazelcastServiceTest); + + //callbacks set up + clearingCalendarService.afterPropertiesSet(); + IMap iMap = hazelcastServiceTest.getHazelcast().getMap(IMDGDistributedNames.Map_ClearingCalendar); + //KAFKA + HashMap startOffsetsUpdating = new HashMap<>(); + TopicPartition topic = new TopicPartition(TOPIC_CLEARING_CALENDAR_NEW, PARTITION); + startOffsetsUpdating.put(topic, 0L); + mockConsumer.updateBeginningOffsets(startOffsetsUpdating); + + mockConsumer.schedulePollTask(() -> { + mockConsumer.rebalance(Collections.singletonList(new TopicPartition(TOPIC_CLEARING_CALENDAR_NEW, PARTITION))); + mockConsumer.addRecord(new ConsumerRecord<>(TOPIC_CLEARING_CALENDAR_NEW, PARTITION, 0, "key", jsonBaseForRequest)); + }); + + //waiting for hazelcast map item removes + Object waiter = new Object(); + String listenerID = iMap.addEntryListener((EntryRemovedListener) entryEvent -> { + System.out.println("Checking If pushed.."); + + try { + waiter.wait(100); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + synchronized (waiter) { + waiter.notify(); + } + }, false); + + synchronized (waiter) { + waiter.wait(100); + } + ClearingCalendar clearingCalendarRes = iMap.get(iMap.keySet().stream().findFirst().get()); + //ASSERT + Assertions.assertEquals(1, iMap.size()); + + Assertions.assertNotNull(clearingCalendarRes.getCreated()); + Assertions.assertEquals(clearingCalendar.getClearingDate(), clearingCalendarRes.getClearingDate()); + Assertions.assertEquals(clearingCalendar.getCompanyId(), clearingCalendarRes.getCompanyId()); + Assertions.assertEquals(clearingCalendar.getDayStatus(), clearingCalendarRes.getDayStatus()); + + //preparing hazelcastImdgProvider for next test + iMap.removeEntryListener(listenerID); + } +} \ No newline at end of file diff --git a/clearing-parent/scheduler-service/src/test/java/ru/specx/clearing/scheduler/service/PlannerTemplateServiceTest.java b/clearing-parent/scheduler-service/src/test/java/ru/specx/clearing/scheduler/service/PlannerTemplateServiceTest.java new file mode 100644 index 000000000..ff5ac8109 --- /dev/null +++ b/clearing-parent/scheduler-service/src/test/java/ru/specx/clearing/scheduler/service/PlannerTemplateServiceTest.java @@ -0,0 +1,141 @@ +package ru.specx.clearing.scheduler.service; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.hazelcast.core.IMap; +import com.hazelcast.map.listener.EntryRemovedListener; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.MockConsumer; +import org.apache.kafka.clients.consumer.OffsetResetStrategy; +import org.apache.kafka.clients.producer.MockProducer; +import org.apache.kafka.common.TopicPartition; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import ru.clearing.classes.statics.data.profile.Contact; +import ru.clearing.classes.statics.data.scheduler.PlannerTemplate; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.ActionType; +import ru.spcex.clearing.platform.messaging.domain.BaseRequest; +import ru.spcex.clearing.platform.messaging.domain.Consts; +import ru.spcex.clearing.platform.messaging.domain.cud.schedule.PlannerTemplateNewRequest; +import ru.spcex.clearing.scheduler.service.PlannerTemplateService; +import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService; +import ru.specx.clearing.scheduler.config.HazelcastServiceTestConfiguration; + +import java.time.Instant; +import java.time.LocalTime; +import java.util.Collections; +import java.util.HashMap; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = { + HazelcastServiceTestConfiguration.class}) +class PlannerTemplateServiceTest { + + private static final int PARTITION = 0; + private static final String TOPIC_PLANNER_TEMPLATE_NEW = Consts.DESTINATION_PLANNER_TEMPLATE_NEW; + private static final Long ID = 0L; + + @Autowired + @Qualifier("hazelcastServiceTest") + private HazelcastService hazelcastServiceTest; + private MockConsumer mockConsumer; + private MockProducer mockProducer; + + @BeforeEach + void setUp() { + mockConsumer = new MockConsumer<>(OffsetResetStrategy.EARLIEST); + mockProducer = new MockProducer<>(); + } + + /** + * {@link PlannerTemplateService#newTimetable(BaseRequest)}(BaseRequest)}
+ * Тест проверяет создание сущности {@link ru.clearing.classes.statics.data.scheduler.PlannerTemplate} в Hazelcast при передаче из Apache Kafka.
+ * Входной запрос {@link PlannerTemplateNewRequest}:
+ */ + @Test + public void newPlannerTemplateInQueue() throws InterruptedException { + //ARRANGE + Instant created = Instant.now(); + PlannerTemplate plannerTemplate = new PlannerTemplate(); + plannerTemplate.setTask("TASK"); + plannerTemplate.setTaskTime(LocalTime.MIDNIGHT); + plannerTemplate.setTaskStatus("TASK_STATUS"); + plannerTemplate.setCompanyId(0L); + plannerTemplate.setSecurityId(10L); + + PlannerTemplateNewRequest plannerTemplateNewRequest = new PlannerTemplateNewRequest(); + plannerTemplateNewRequest.setTask(plannerTemplate.getTask()); + plannerTemplateNewRequest.setTaskTime(plannerTemplate.getTaskTime()); + plannerTemplateNewRequest.setTaskStatus(plannerTemplate.getTaskStatus()); + plannerTemplateNewRequest.setCompanyId(plannerTemplate.getCompanyId()); + plannerTemplateNewRequest.setSecurityId(plannerTemplate.getSecurityId()); + + BaseRequest plannerTemplateRequest = new BaseRequest<>(); + plannerTemplateRequest.setRequestPayload(plannerTemplateNewRequest); + plannerTemplateRequest.setId(ID); + plannerTemplateRequest.setActionType(ActionType.NEW); + String jsonBaseForDeleteRequest; + ObjectMapper objectMapper = new ObjectMapper(); + try { + jsonBaseForDeleteRequest = objectMapper.writeValueAsString(plannerTemplateRequest); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + + //ACT + //service set up + PlannerTemplateService plannerTemplateService = new PlannerTemplateService(mockConsumer, mockProducer, hazelcastServiceTest); + + //callbacks set up + plannerTemplateService.afterPropertiesSet(); + IMap iMap = hazelcastServiceTest.getHazelcast().getMap(IMDGDistributedNames.Map_PlannerTemplate); + //KAFKA + HashMap startOffsetsUpdating = new HashMap<>(); + TopicPartition topic = new TopicPartition(TOPIC_PLANNER_TEMPLATE_NEW, PARTITION); + startOffsetsUpdating.put(topic, 0L); + mockConsumer.updateBeginningOffsets(startOffsetsUpdating); + + mockConsumer.schedulePollTask(() -> { + mockConsumer.rebalance(Collections.singletonList(new TopicPartition(TOPIC_PLANNER_TEMPLATE_NEW, PARTITION))); + mockConsumer.addRecord(new ConsumerRecord<>(TOPIC_PLANNER_TEMPLATE_NEW, PARTITION, 0, "key", jsonBaseForDeleteRequest)); + }); + + //waiting for hazelcast map item removes + Object waiter = new Object(); + String listenerID = iMap.addEntryListener((EntryRemovedListener) entryEvent -> { + System.out.println("Checking If pushed.."); + + try { + waiter.wait(100); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + synchronized (waiter) { + waiter.notify(); + } + }, false); + + synchronized (waiter) { + waiter.wait(100); + } + PlannerTemplate plannerTemplateRes = iMap.get(iMap.keySet().stream().findFirst().get()); + //ASSERT + Assertions.assertEquals(1, iMap.size()); + + Assertions.assertNotNull(plannerTemplateRes.getCreated()); + Assertions.assertEquals(plannerTemplate.getTask(), plannerTemplateRes.getTask()); + Assertions.assertEquals(plannerTemplate.getTaskTime(), plannerTemplateRes.getTaskTime()); + Assertions.assertEquals(plannerTemplate.getTaskStatus(), plannerTemplateRes.getTaskStatus()); + Assertions.assertEquals(plannerTemplate.getCompanyId(), plannerTemplateRes.getCompanyId()); + Assertions.assertEquals(plannerTemplate.getSecurityId(), plannerTemplateRes.getSecurityId()); + //preparing hazelcastImdgProvider for next test + iMap.removeEntryListener(listenerID); + } +} \ No newline at end of file diff --git a/clearing-parent/scheduler-service/src/test/java/ru/specx/clearing/scheduler/utils/MatcherFactory.java b/clearing-parent/scheduler-service/src/test/java/ru/specx/clearing/scheduler/utils/MatcherFactory.java new file mode 100644 index 000000000..c214393ea --- /dev/null +++ b/clearing-parent/scheduler-service/src/test/java/ru/specx/clearing/scheduler/utils/MatcherFactory.java @@ -0,0 +1,38 @@ +package ru.specx.clearing.scheduler.utils; + +import java.util.Arrays; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Factory for creating test matchers. + *

+ * Comparing actual and expected objects via AssertJ + */ +public class MatcherFactory { + + public static Matcher usingIgnoringFieldsComparator(String... fieldsToIgnore) { + return new Matcher<>(fieldsToIgnore); + } + + public static class Matcher { + private final String[] fieldsToIgnore; + + private Matcher(String... fieldsToIgnore) { + this.fieldsToIgnore = fieldsToIgnore; + } + + public void assertMatch(T actual, T expected) { + assertThat(actual).usingRecursiveComparison().ignoringFields(fieldsToIgnore).isEqualTo(expected); + } + + @SafeVarargs + public final void assertMatch(Iterable actual, T... expected) { + assertMatch(actual, Arrays.asList(expected)); + } + + public void assertMatch(Iterable actual, Iterable expected) { + assertThat(actual).usingRecursiveFieldByFieldElementComparatorIgnoringFields(fieldsToIgnore).isEqualTo(expected); + } + } +} diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/brake/document/AccountUpdateWithBrakeRequest.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/brake/document/AccountUpdateWithBrakeRequest.java new file mode 100644 index 000000000..8064c3ab5 --- /dev/null +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/brake/document/AccountUpdateWithBrakeRequest.java @@ -0,0 +1,4 @@ +package ru.spcex.clearing.platform.messaging.domain.cud.account.brake.document; + +public class AccountUpdateWithBrakeRequest { +}