diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/AccountValidationConfig.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/AccountValidationConfig.java index 9ee54a54b..f5d440c8c 100644 --- a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/AccountValidationConfig.java +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/AccountValidationConfig.java @@ -116,9 +116,9 @@ public class AccountValidationConfig { AccountError.RequiredFieldEmpty, AccountError.AccountNotFound, account -> { - String statusFromRequest = correspondentAccountUpdateRequest.getStatus(); - if (statusFromRequest != null && !statusFromRequest.equalsIgnoreCase(account.getStatus())) - return AccountError.WrongFieldValue; + // проверка на заблокированность счёта + if (!AccountStatus.ACTIVE.getKey().equalsIgnoreCase(account.getStatus())) + return AccountError.AccountNotActive; return null; }), IdPresentRule.instance("companyId", diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/ClientCodeService.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/ClientCodeService.java index c3ed92205..b46a83451 100644 --- a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/ClientCodeService.java +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/ClientCodeService.java @@ -229,11 +229,13 @@ public class ClientCodeService extends QueueConsumer implements InitializingBean ClientCode clientCode = clientCodeMap.getSingleObjectByID(req.getId()); if (clientCode.getMoneyAccountId() != null) { - log.debug("Delete clientCode.id = {}: send message to account-service", clientCode.getId()); + log.debug("Blocking clientCode.id = {}: send message to account-service", clientCode.getId()); sendBlockTCR(clientCode.getTradingClearingRegistryId(), clientCode.getMoneyAccountId()); } - log.debug("Delete clientCode.id={}", clientCode.getId()); - clientCodeMap.delete(clientCode); + log.debug("Blocking clientCode.id={}", clientCode.getId()); + clientCode.setUpdated(Instant.now()); + clientCode.setStatus(WorkflowStatus.Blocked.getKey()); + clientCodeMap.update(clientCode); return null; } diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/TradingClearingRegistryService.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/TradingClearingRegistryService.java index 3f0a443fe..152894df1 100644 --- a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/TradingClearingRegistryService.java +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/TradingClearingRegistryService.java @@ -153,6 +153,14 @@ public class TradingClearingRegistryService extends QueueConsumer implements Ini // Пока что она соответствует ТЗ, но возможно будет правиться, поэтому расписана без выноса кода в методы и // прочих методов сокращения кода. В дальнейшем, после тестирования и окончательного выяснения вида проверки, // её стоит вынести на этап валидации запроса. + if (req.getMoneyAccountId() == null && (req.getMoneyAccountId() == null || req.getDepoAccountId() == null)) { + TradingClearingRegistry registryByCompany = tradingClearingRegistryImdg.getSingleObjectByFieldValues(Map.of("companyId", req.getCompanyId())); + if (registryByCompany == null) { + return requestHelper.makeErrorResponse(userRequest, + AccountError.TradingClearingRegistryNotFound, + req.getCompanyId()); + } + } Relation relation = relationImdg.getSingleObjectByFieldValues(Map.of("consumerId", req.getCompanyId())); if (ru.spcex.platform.enumeration.Service.MKR.equalsByKey(relation.getService())) { TradingClearingRegistry registry = tradingClearingRegistryImdg.getSingleObjectByFieldValues(Map.of("companyId", req.getCompanyId())); @@ -281,6 +289,15 @@ public class TradingClearingRegistryService extends QueueConsumer implements Ini } TradingClearingRegistryNewRequest req = userRequest.getRequestPayload(); + // Дополнительная проверка + if (req.getMoneyAccountId() == null && (req.getMoneyAccountId() == null || req.getDepoAccountId() == null)) { + TradingClearingRegistry registryByCompany = tradingClearingRegistryImdg.getSingleObjectByFieldValues(Map.of("companyId", req.getCompanyId())); + if (registryByCompany == null) { + return requestHelper.makeErrorResponse(userRequest, + AccountError.TradingClearingRegistryNotFound, + "companyId=" + req.getCompanyId()); + } + } Long id = tradingClearingRegistryImdg.nextIDSequenceFor(); TradingClearingRegistry tradingClearingRegistry = new TradingClearingRegistry(); @@ -335,6 +352,15 @@ public class TradingClearingRegistryService extends QueueConsumer implements Ini TradingClearingRegistryUpdateRequest req = userRequest.getRequestPayload(); TradingClearingRegistry tradingClearingRegistry = tradingClearingRegistryImdg.getSingleObjectByID(req.getId()); + // Дополнительная проверка + if (req.getMoneyAccountId() == null && (req.getMoneyAccountId() == null || req.getDepoAccountId() == null)) { + TradingClearingRegistry registryByCompany = tradingClearingRegistryImdg.getSingleObjectByFieldValues(Map.of("companyId", req.getCompanyId())); + if (registryByCompany == null) { + return requestHelper.makeErrorResponse(userRequest, + AccountError.TradingClearingRegistryNotFound, + "companyId=" + req.getCompanyId()); + } + } if (req.getStatus() != null) tradingClearingRegistry.setStatus(req.getStatus()); diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/misc/ListingController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/misc/ListingController.java index 583801df2..45cf6dd43 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/misc/ListingController.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/misc/ListingController.java @@ -1,22 +1,29 @@ package ru.spcex.clearing.backendapi.controller.queue.misc; import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import ru.clearing.classes.statics.data.misc.Listing; import ru.spcex.clearing.backendapi.controller.queue.AbstractQueueController; +import ru.spcex.clearing.backendapi.controller.request.cud.common.CommonDeleteAction; +import ru.spcex.clearing.backendapi.controller.request.cud.company.ListingNewAction; +import ru.spcex.clearing.backendapi.controller.request.cud.company.ListingUpdateAction; +import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse; +import ru.spcex.clearing.backendapi.controller.response.cud.CudResponse; import ru.spcex.clearing.backendapi.controller.response.entity.CommonGetAllResponse; 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 java.util.Collection; import java.util.Map; +import java.util.concurrent.ExecutionException; @Controller @RequestMapping("/listings") @@ -39,4 +46,40 @@ public class ListingController extends AbstractQueueController { response.fromEntity(all); return response; } + + + + @ApiOperation(value = "create Listing.") + @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CudResponse.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)}) + @RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public CudResponse create( + @ApiParam(value = "Значения полей нового объекта.", required = true) + @RequestBody ListingNewAction listingNewAction) throws ExecutionException, InterruptedException { + return processRequest(Consts.LISTING_NEW, listingNewAction); + } + + @ApiOperation(value = "update Listing.") + @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CudResponse.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)}) + @RequestMapping(value = "/{id}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public CudResponse update( + @ApiParam(value = "Идентификатор изменяемого объекта.", required = true, example = "1234") + @PathVariable("id") Long id, + @ApiParam(value = "Новые значения полей объекта.", required = true) + @RequestBody ListingUpdateAction listingUpdateAction) throws ExecutionException, InterruptedException { + listingUpdateAction.setId(id); + return processRequest(Consts.LISTING_UPDATE, listingUpdateAction); + } + + @ApiOperation(value = "delete Listing.") + @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CudResponse.class)}) + @RequestMapping(value = "/{id}", method = RequestMethod.DELETE) + @ResponseBody + public CudResponse delete(@ApiParam(value = "Идентификатор удаляемого объекта", required = true, example = "1234") + @PathVariable("id") Long id) throws ExecutionException, InterruptedException { + CommonDeleteAction deleteAction = new CommonDeleteAction(); + deleteAction.setId(id); + return processRequest(Consts.LISTING_DELETE, deleteAction); + } } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/securities/EquitySecurityController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/securities/EquitySecurityController.java index 6a6542568..1a01f06a0 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/securities/EquitySecurityController.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/securities/EquitySecurityController.java @@ -77,8 +77,7 @@ public class EquitySecurityController extends AbstractQueueController { @ResponseBody public CommonGetAllResponse getAll() { Collection> all = stateLoader.getAllMetaTransform(IMDGDistributedNames.Map_EquitySecurity, - EquitySecurity.class, - Map.of("workflowStatus", Status.Active.getKey())); + EquitySecurity.class); CommonGetAllResponse response = new CommonGetAllResponse(); response.fromEntity(all); return response; diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/securities/FixedIncomeSecurityController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/securities/FixedIncomeSecurityController.java index 527554d73..58f7b474b 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/securities/FixedIncomeSecurityController.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/securities/FixedIncomeSecurityController.java @@ -77,8 +77,7 @@ public class FixedIncomeSecurityController extends AbstractQueueController { @ResponseBody public CommonGetAllResponse getAll() { Collection> all = stateLoader.getAllMetaTransform(IMDGDistributedNames.Map_FixedIncomeSecurity, - FixedIncomeSecurity.class, - Map.of("workflowStatus", Status.Active.getKey())); + FixedIncomeSecurity.class); CommonGetAllResponse response = new CommonGetAllResponse(); response.fromEntity(all); return response; diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/company/ListingNewAction.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/company/ListingNewAction.java new file mode 100644 index 000000000..ca4768af3 --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/company/ListingNewAction.java @@ -0,0 +1,86 @@ +package ru.spcex.clearing.backendapi.controller.request.cud.company; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModelProperty; +import ru.spcex.clearing.backendapi.domain.actions.IAction; +import ru.spcex.clearing.platform.messaging.domain.ActionType; +import ru.spcex.clearing.platform.messaging.domain.cud.company.CompanySymbolUpdateRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.ListingNewRequest; + +import java.math.BigDecimal; + +public class ListingNewAction implements IAction { + @ApiModelProperty(value = "Наименование инструмента", example = "1234") + @JsonProperty + private Long securityId; + @ApiModelProperty(value = "Наименование режима", example = "ABCD") + @JsonProperty + private String market; + @ApiModelProperty(value = "Размер лота", example = "1234.56") + @JsonProperty + private BigDecimal lotSize; + @ApiModelProperty(value = "Наименование валюты расчета", example = "RUB") + @JsonProperty + private String tradingCurrency; + @ApiModelProperty(value = "Наименование статуса листинга в системе", example = "ACTV") + @JsonProperty + private String workflowStatus; + + @Override + public ListingNewRequest toRequest() { + ListingNewRequest request = new ListingNewRequest(); + request.setSecurityId(this.securityId); + request.setMarket(this.market); + request.setLotSize(this.lotSize); + request.setTradingCurrency(this.tradingCurrency); + request.setWorkflowStatus(this.workflowStatus); + return request; + } + + @ApiModelProperty(hidden = true) + @Override + public ActionType getActionType() { + return ActionType.NEW; + } + + + public Long getSecurityId() { + return securityId; + } + + public void setSecurityId(Long securityId) { + this.securityId = securityId; + } + + public String getMarket() { + return market; + } + + public void setMarket(String market) { + this.market = market; + } + + public BigDecimal getLotSize() { + return lotSize; + } + + public void setLotSize(BigDecimal lotSize) { + this.lotSize = lotSize; + } + + public String getTradingCurrency() { + return tradingCurrency; + } + + public void setTradingCurrency(String tradingCurrency) { + this.tradingCurrency = tradingCurrency; + } + + public String getWorkflowStatus() { + return workflowStatus; + } + + public void setWorkflowStatus(String workflowStatus) { + this.workflowStatus = workflowStatus; + } +} diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/company/ListingUpdateAction.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/company/ListingUpdateAction.java new file mode 100644 index 000000000..afaf2591f --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/company/ListingUpdateAction.java @@ -0,0 +1,97 @@ +package ru.spcex.clearing.backendapi.controller.request.cud.company; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModelProperty; +import ru.spcex.clearing.backendapi.domain.actions.IAction; +import ru.spcex.clearing.platform.messaging.domain.ActionType; +import ru.spcex.clearing.platform.messaging.domain.cud.company.ContactUpdateRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.securitites.ListingUpdateRequest; + +import java.math.BigDecimal; + +public class ListingUpdateAction implements IAction { + @ApiModelProperty(hidden = true) + @JsonProperty + public Long id; + @ApiModelProperty(value = "Наименование инструмента", example = "1234") + @JsonProperty + private Long securityId; + @ApiModelProperty(value = "Наименование режима", example = "ABCD") + @JsonProperty + private String market; + @ApiModelProperty(value = "Размер лота", example = "1234.56") + @JsonProperty + private BigDecimal lotSize; + @ApiModelProperty(value = "Наименование валюты расчета", example = "RUB") + @JsonProperty + private String tradingCurrency; + @ApiModelProperty(value = "Наименование статуса листинга в системе", example = "ACTV") + @JsonProperty + private String workflowStatus; + + @Override + public ListingUpdateRequest toRequest() { + ListingUpdateRequest request = new ListingUpdateRequest(); + request.setId(this.id); + request.setSecurityId(this.securityId); + request.setMarket(this.market); + request.setLotSize(this.lotSize); + request.setTradingCurrency(this.tradingCurrency); + request.setWorkflowStatus(this.workflowStatus); + return request; + } + + @ApiModelProperty(hidden = true) + @Override + public ActionType getActionType() { + return ActionType.UPDATE; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getSecurityId() { + return securityId; + } + + public void setSecurityId(Long securityId) { + this.securityId = securityId; + } + + public String getMarket() { + return market; + } + + public void setMarket(String market) { + this.market = market; + } + + public BigDecimal getLotSize() { + return lotSize; + } + + public void setLotSize(BigDecimal lotSize) { + this.lotSize = lotSize; + } + + public String getTradingCurrency() { + return tradingCurrency; + } + + public void setTradingCurrency(String tradingCurrency) { + this.tradingCurrency = tradingCurrency; + } + + public String getWorkflowStatus() { + return workflowStatus; + } + + public void setWorkflowStatus(String workflowStatus) { + this.workflowStatus = workflowStatus; + } +} diff --git a/clearing-parent/backend-api/src/main/resources/meta/meta.json b/clearing-parent/backend-api/src/main/resources/meta/meta.json index 7b96718d8..84394d492 100644 --- a/clearing-parent/backend-api/src/main/resources/meta/meta.json +++ b/clearing-parent/backend-api/src/main/resources/meta/meta.json @@ -1,6 +1,6 @@ { - "version": "3.5.0.24", + "version": "3.5.0.25", "enums": { @@ -2502,6 +2502,10 @@ "confirmation": "securitySymbol,shortName,fullName,lotSize,nominalValue,nominalCurrency", "fields": [ + {"code": "instrumentType", + "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false + } + , {"code": "securitySymbol", "type": 2,"length": 255,"name": "Код инструмента","shortname": "Код","required": true } @@ -2539,7 +2543,7 @@ } , {"code": "termType", - "type": 12,"name": "Наименование вида инструмента","shortname": "Вид инструмента","link": "termType","visible": false + "type": 12,"name": "Наименование вида инструмента","shortname": "Вид инструмента","link": "termType" } , {"code": "description", @@ -2565,10 +2569,6 @@ {"code": "workflowStatus", "type": 12,"name": "Наименование статуса","shortname": "Статус","link": "workflowStatus" } - , - {"code": "instrumentType", - "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"visible": false - } ] } , @@ -2582,6 +2582,10 @@ {"code": "id", "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "moneyMarketSecurity","linkCode": "id","required": true } + , + {"code": "instrumentType", + "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false + } , {"code": "securitySymbol", "type": 2,"length": 255,"name": "Код инструмента","shortname": "Код","enabled": false @@ -2600,7 +2604,7 @@ } , {"code": "lotSize", - "field": "securityId","type": 11,"name": "Размер лота","shortname": "Лот","linkKeyCode": "securityId","linkCode": "lotSize","link": "listing" + "field": "securityId","type": 11,"name": "Размер лота","shortname": "Лот","linkKeyCode": "securityId","linkCode": "lotSize","link": "listing","required": true } , {"code": "nominalValue", @@ -2646,10 +2650,6 @@ {"code": "workflowStatus", "type": 12,"name": "Наименование статуса","shortname": "Статус","link": "workflowStatus" } - , - {"code": "instrumentType", - "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","visible": false - } ] } , @@ -2768,9 +2768,13 @@ "name": "Добавление акции", - "confirmation": "securitySymbol,shortName,fullName,isin,shareType,lotSize", + "confirmation": "securitySymbol,shortName,fullName,isin,shareType", "fields": [ + {"code": "instrumentType", + "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false + } + , {"code": "securitySymbol", "type": 2,"length": 255,"name": "Код инструмента","shortname": "Код","required": true } @@ -2792,7 +2796,7 @@ } , {"code": "lotSize", - "type": 11,"name": "Размер лота","shortname": "Лот","required": true + "type": 11,"name": "Размер лота","shortname": "Лот","visible": false } , {"code": "issuerId", @@ -2810,10 +2814,6 @@ {"code": "workflowStatus", "type": 12,"name": "Наименование статуса","shortname": "Статус","link": "workflowStatus" } - , - {"code": "instrumentType", - "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"visible": false - } ] } , @@ -2821,12 +2821,16 @@ "name": "Изменение акции", - "confirmation": "securitySymbol,shortName,fullName,isin,shareType,lotSize", + "confirmation": "securitySymbol,shortName,fullName,isin,shareType", "fields": [ {"code": "id", "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "equitySecurity","linkCode": "id","required": true } + , + {"code": "instrumentType", + "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false + } , {"code": "securitySymbol", "type": 2,"length": 255,"name": "Код инструмента","shortname": "Код","enabled": false @@ -2849,7 +2853,7 @@ } , {"code": "lotSize", - "field": "securityId","type": 11,"name": "Размер лота","shortname": "Лот","linkKeyCode": "securityId","linkCode": "lotSize","link": "listing" + "field": "securityId","type": 11,"name": "Размер лота","shortname": "Лот","linkKeyCode": "securityId","linkCode": "lotSize","link": "listing","visible": false } , {"code": "issuerId", @@ -2867,10 +2871,6 @@ {"code": "workflowStatus", "type": 12,"name": "Наименование статуса","shortname": "Статус","link": "workflowStatus" } - , - {"code": "instrumentType", - "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","visible": false - } ] } , @@ -2979,9 +2979,13 @@ "name": "Добавление облигации", - "confirmation": "securitySymbol,shortName,fullName,isin,bondType,lotSize,nominalValue,nominalCurrency", + "confirmation": "securitySymbol,shortName,fullName,isin,bondType,nominalValue,nominalCurrency", "fields": [ + {"code": "instrumentType", + "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false + } + , {"code": "securitySymbol", "type": 2,"length": 255,"name": "Код инструмента","shortname": "Код","required": true } @@ -3003,7 +3007,7 @@ } , {"code": "lotSize", - "type": 11,"name": "Размер лота","shortname": "Лот","required": true + "type": 11,"name": "Размер лота","shortname": "Лот","visible": false } , {"code": "nominalValue", @@ -3041,10 +3045,6 @@ {"code": "workflowStatus", "type": 12,"name": "Наименование статуса","shortname": "Статус","link": "workflowStatus" } - , - {"code": "instrumentType", - "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"visible": false - } ] } , @@ -3052,12 +3052,16 @@ "name": "Изменение облигации", - "confirmation": "securitySymbol,shortName,fullName,isin,bondType,lotSize,nominalValue,nominalCurrency", + "confirmation": "securitySymbol,shortName,fullName,isin,bondType,nominalValue,nominalCurrency", "fields": [ {"code": "id", "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "fixedIncomeSecurity","linkCode": "id","required": true } + , + {"code": "instrumentType", + "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false + } , {"code": "securitySymbol", "type": 2,"length": 255,"name": "Код инструмента","shortname": "Код","enabled": false @@ -3080,7 +3084,7 @@ } , {"code": "lotSize", - "field": "securityId","type": 11,"name": "Размер лота","shortname": "Лот","linkKeyCode": "securityId","linkCode": "lotSize","link": "listing" + "field": "securityId","type": 11,"name": "Размер лота","shortname": "Лот","linkKeyCode": "securityId","linkCode": "lotSize","link": "listing","visible": false } , {"code": "nominalValue", @@ -3118,10 +3122,6 @@ {"code": "workflowStatus", "type": 12,"name": "Наименование статуса","shortname": "Статус","link": "workflowStatus" } - , - {"code": "instrumentType", - "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","visible": false - } ] } , @@ -3222,7 +3222,7 @@ , "listing": { - "name": "Листинг инструментов", + "name": "Инструменты на режимах", "destination": "listings", @@ -3236,21 +3236,21 @@ {"code": "securityId", "type": 1,"dbname": "Идентификатор инструмента","name": "Наименование инструмента","shortname": "Инструмент","searchable": true,"sortable": true,"link": "security","linkCode": "shortName" } + , + {"code": "market", + "type": 12,"dbname": "Код торговой секции","name": "Наименование режима","shortname": "Режим","searchable": true,"sortable": true,"link": "market","linkCode": "description" + } , {"code": "lotSize", "type": 11,"name": "Размер лота","shortname": "Лот","searchable": true,"sortable": true } - , - {"code": "market", - "type": 12,"dbname": "Код торговой секции","name": "Наименование торговой секции","shortname": "Секция","searchable": true,"sortable": true,"link": "market","linkCode": "name" - } , {"code": "symbolCode", - "type": 2,"length": 255,"name": "Код инструмента на торговой площадке","shortname": "Код инструмента на торговой площадке","searchable": true,"sortable": true + "type": 2,"length": 255,"name": "Код инструмента на торговой площадке","shortname": "Код инструмента на режиме","searchable": true,"sortable": true } , {"code": "symbolName", - "type": 2,"length": 255,"name": "Наименование инструмента на торговой площадке","shortname": "Инструмент на торговой площадке","searchable": true,"sortable": true + "type": 2,"length": 255,"name": "Наименование инструмента на торговой площадке","shortname": "Наименование инструмента на режиме","searchable": true,"sortable": true } , {"code": "tradingCurrency", @@ -3273,7 +3273,82 @@ "field": "updated","type": 4,"webtype": "5","dbname": "Дата-время изменения записи","name": "Время изменения записи","shortname": "Изменено","searchable": true,"sortable": true,"ignore": true } ] - + ,"actions":[ + {"method":"post", + + "name": "Добавление инструмента на режимах", + + "confirmation": "securityId,market,lotSize,tradingCurrency,workflowStatus", + + "fields": [ + {"code": "securityId", + "type": 1,"name": "Наименование инструмента","shortname": "Инструмент","link": "security","linkCode": "shortName","required": true + } + , + {"code": "market", + "type": 12,"name": "Наименование режима","shortname": "Режим","link": "market","required": true,"linkCode": "code" + } + , + {"code": "lotSize", + "type": 11,"name": "Размер лота","shortname": "Лот","required": true + } + , + {"code": "tradingCurrency", + "type": 12,"name": "Наименование валюты расчета","shortname": "Валюта","link": "currencyCode","linkCode": "code","required": true + } + , + {"code": "workflowStatus", + "type": 12,"name": "Наименование статуса листинга в системе","shortname": "Статус","link": "workflowStatus","required": true + } + ] + } + , + {"method":"put", + + "name": "Изменение инструмента на режимах", + + "confirmation": "securityId,market,lotSize,tradingCurrency,workflowStatus", + + "fields": [ + {"code": "id", + "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "listing","linkCode": "id","required": true + } + , + {"code": "securityId", + "type": 1,"name": "Наименование инструмента","shortname": "Инструмент","link": "security","linkCode": "shortName","required": true,"enabled": false + } + , + {"code": "market", + "type": 12,"name": "Наименование режима","shortname": "Режим","link": "market","linkCode": "code","required": true,"enabled": false + } + , + {"code": "lotSize", + "type": 11,"name": "Размер лота","shortname": "Лот","required": true + } + , + {"code": "tradingCurrency", + "type": 12,"name": "Наименование валюты расчета","shortname": "Валюта","link": "currencyCode","linkCode": "code","required": true + } + , + {"code": "workflowStatus", + "type": 12,"name": "Наименование статуса листинга в системе","shortname": "Статус","link": "workflowStatus","required": true + } + ] + } + , + {"method":"delete", + + "name": "Блокировка инструмента на режимах", + + "confirmation": "securityId,market", + + "fields": [ + {"code": "id", + "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "listing","linkCode": "id","required": true + } + ] + } + ] } , "market": { @@ -5235,7 +5310,7 @@ , "session": { - "name": "Клиринговая сессия", + "name": "Клиринговые сессии", "destination": "sessions", 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 7735e5c00..d7d11b810 100644 --- a/clearing-parent/backend-api/src/main/resources/meta/meta.xml +++ b/clearing-parent/backend-api/src/main/resources/meta/meta.xml @@ -1,6 +1,6 @@ - + @@ -579,6 +579,7 @@ + @@ -588,22 +589,22 @@ - + - + - + @@ -615,7 +616,6 @@ - @@ -643,32 +643,32 @@ - + + - + - - + + - + - @@ -695,13 +695,14 @@ - + + - + @@ -711,16 +712,16 @@ - - + + - + @@ -730,7 +731,6 @@ - @@ -753,17 +753,37 @@ - + + - - - + + + + + + + + + + + + + + + + + + + + + + @@ -1218,7 +1238,7 @@ - + diff --git a/clearing-parent/backend-api/src/test/resources/meta.json b/clearing-parent/backend-api/src/test/resources/meta.json index 7b96718d8..84394d492 100644 --- a/clearing-parent/backend-api/src/test/resources/meta.json +++ b/clearing-parent/backend-api/src/test/resources/meta.json @@ -1,6 +1,6 @@ { - "version": "3.5.0.24", + "version": "3.5.0.25", "enums": { @@ -2502,6 +2502,10 @@ "confirmation": "securitySymbol,shortName,fullName,lotSize,nominalValue,nominalCurrency", "fields": [ + {"code": "instrumentType", + "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false + } + , {"code": "securitySymbol", "type": 2,"length": 255,"name": "Код инструмента","shortname": "Код","required": true } @@ -2539,7 +2543,7 @@ } , {"code": "termType", - "type": 12,"name": "Наименование вида инструмента","shortname": "Вид инструмента","link": "termType","visible": false + "type": 12,"name": "Наименование вида инструмента","shortname": "Вид инструмента","link": "termType" } , {"code": "description", @@ -2565,10 +2569,6 @@ {"code": "workflowStatus", "type": 12,"name": "Наименование статуса","shortname": "Статус","link": "workflowStatus" } - , - {"code": "instrumentType", - "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"visible": false - } ] } , @@ -2582,6 +2582,10 @@ {"code": "id", "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "moneyMarketSecurity","linkCode": "id","required": true } + , + {"code": "instrumentType", + "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false + } , {"code": "securitySymbol", "type": 2,"length": 255,"name": "Код инструмента","shortname": "Код","enabled": false @@ -2600,7 +2604,7 @@ } , {"code": "lotSize", - "field": "securityId","type": 11,"name": "Размер лота","shortname": "Лот","linkKeyCode": "securityId","linkCode": "lotSize","link": "listing" + "field": "securityId","type": 11,"name": "Размер лота","shortname": "Лот","linkKeyCode": "securityId","linkCode": "lotSize","link": "listing","required": true } , {"code": "nominalValue", @@ -2646,10 +2650,6 @@ {"code": "workflowStatus", "type": 12,"name": "Наименование статуса","shortname": "Статус","link": "workflowStatus" } - , - {"code": "instrumentType", - "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","visible": false - } ] } , @@ -2768,9 +2768,13 @@ "name": "Добавление акции", - "confirmation": "securitySymbol,shortName,fullName,isin,shareType,lotSize", + "confirmation": "securitySymbol,shortName,fullName,isin,shareType", "fields": [ + {"code": "instrumentType", + "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false + } + , {"code": "securitySymbol", "type": 2,"length": 255,"name": "Код инструмента","shortname": "Код","required": true } @@ -2792,7 +2796,7 @@ } , {"code": "lotSize", - "type": 11,"name": "Размер лота","shortname": "Лот","required": true + "type": 11,"name": "Размер лота","shortname": "Лот","visible": false } , {"code": "issuerId", @@ -2810,10 +2814,6 @@ {"code": "workflowStatus", "type": 12,"name": "Наименование статуса","shortname": "Статус","link": "workflowStatus" } - , - {"code": "instrumentType", - "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"visible": false - } ] } , @@ -2821,12 +2821,16 @@ "name": "Изменение акции", - "confirmation": "securitySymbol,shortName,fullName,isin,shareType,lotSize", + "confirmation": "securitySymbol,shortName,fullName,isin,shareType", "fields": [ {"code": "id", "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "equitySecurity","linkCode": "id","required": true } + , + {"code": "instrumentType", + "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false + } , {"code": "securitySymbol", "type": 2,"length": 255,"name": "Код инструмента","shortname": "Код","enabled": false @@ -2849,7 +2853,7 @@ } , {"code": "lotSize", - "field": "securityId","type": 11,"name": "Размер лота","shortname": "Лот","linkKeyCode": "securityId","linkCode": "lotSize","link": "listing" + "field": "securityId","type": 11,"name": "Размер лота","shortname": "Лот","linkKeyCode": "securityId","linkCode": "lotSize","link": "listing","visible": false } , {"code": "issuerId", @@ -2867,10 +2871,6 @@ {"code": "workflowStatus", "type": 12,"name": "Наименование статуса","shortname": "Статус","link": "workflowStatus" } - , - {"code": "instrumentType", - "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","visible": false - } ] } , @@ -2979,9 +2979,13 @@ "name": "Добавление облигации", - "confirmation": "securitySymbol,shortName,fullName,isin,bondType,lotSize,nominalValue,nominalCurrency", + "confirmation": "securitySymbol,shortName,fullName,isin,bondType,nominalValue,nominalCurrency", "fields": [ + {"code": "instrumentType", + "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false + } + , {"code": "securitySymbol", "type": 2,"length": 255,"name": "Код инструмента","shortname": "Код","required": true } @@ -3003,7 +3007,7 @@ } , {"code": "lotSize", - "type": 11,"name": "Размер лота","shortname": "Лот","required": true + "type": 11,"name": "Размер лота","shortname": "Лот","visible": false } , {"code": "nominalValue", @@ -3041,10 +3045,6 @@ {"code": "workflowStatus", "type": 12,"name": "Наименование статуса","shortname": "Статус","link": "workflowStatus" } - , - {"code": "instrumentType", - "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"visible": false - } ] } , @@ -3052,12 +3052,16 @@ "name": "Изменение облигации", - "confirmation": "securitySymbol,shortName,fullName,isin,bondType,lotSize,nominalValue,nominalCurrency", + "confirmation": "securitySymbol,shortName,fullName,isin,bondType,nominalValue,nominalCurrency", "fields": [ {"code": "id", "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "fixedIncomeSecurity","linkCode": "id","required": true } + , + {"code": "instrumentType", + "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","required": true,"enabled": false + } , {"code": "securitySymbol", "type": 2,"length": 255,"name": "Код инструмента","shortname": "Код","enabled": false @@ -3080,7 +3084,7 @@ } , {"code": "lotSize", - "field": "securityId","type": 11,"name": "Размер лота","shortname": "Лот","linkKeyCode": "securityId","linkCode": "lotSize","link": "listing" + "field": "securityId","type": 11,"name": "Размер лота","shortname": "Лот","linkKeyCode": "securityId","linkCode": "lotSize","link": "listing","visible": false } , {"code": "nominalValue", @@ -3118,10 +3122,6 @@ {"code": "workflowStatus", "type": 12,"name": "Наименование статуса","shortname": "Статус","link": "workflowStatus" } - , - {"code": "instrumentType", - "type": 12,"name": "Наименование типа инструмента","shortname": "Тип инструмента","link": "instrumentType","visible": false - } ] } , @@ -3222,7 +3222,7 @@ , "listing": { - "name": "Листинг инструментов", + "name": "Инструменты на режимах", "destination": "listings", @@ -3236,21 +3236,21 @@ {"code": "securityId", "type": 1,"dbname": "Идентификатор инструмента","name": "Наименование инструмента","shortname": "Инструмент","searchable": true,"sortable": true,"link": "security","linkCode": "shortName" } + , + {"code": "market", + "type": 12,"dbname": "Код торговой секции","name": "Наименование режима","shortname": "Режим","searchable": true,"sortable": true,"link": "market","linkCode": "description" + } , {"code": "lotSize", "type": 11,"name": "Размер лота","shortname": "Лот","searchable": true,"sortable": true } - , - {"code": "market", - "type": 12,"dbname": "Код торговой секции","name": "Наименование торговой секции","shortname": "Секция","searchable": true,"sortable": true,"link": "market","linkCode": "name" - } , {"code": "symbolCode", - "type": 2,"length": 255,"name": "Код инструмента на торговой площадке","shortname": "Код инструмента на торговой площадке","searchable": true,"sortable": true + "type": 2,"length": 255,"name": "Код инструмента на торговой площадке","shortname": "Код инструмента на режиме","searchable": true,"sortable": true } , {"code": "symbolName", - "type": 2,"length": 255,"name": "Наименование инструмента на торговой площадке","shortname": "Инструмент на торговой площадке","searchable": true,"sortable": true + "type": 2,"length": 255,"name": "Наименование инструмента на торговой площадке","shortname": "Наименование инструмента на режиме","searchable": true,"sortable": true } , {"code": "tradingCurrency", @@ -3273,7 +3273,82 @@ "field": "updated","type": 4,"webtype": "5","dbname": "Дата-время изменения записи","name": "Время изменения записи","shortname": "Изменено","searchable": true,"sortable": true,"ignore": true } ] - + ,"actions":[ + {"method":"post", + + "name": "Добавление инструмента на режимах", + + "confirmation": "securityId,market,lotSize,tradingCurrency,workflowStatus", + + "fields": [ + {"code": "securityId", + "type": 1,"name": "Наименование инструмента","shortname": "Инструмент","link": "security","linkCode": "shortName","required": true + } + , + {"code": "market", + "type": 12,"name": "Наименование режима","shortname": "Режим","link": "market","required": true,"linkCode": "code" + } + , + {"code": "lotSize", + "type": 11,"name": "Размер лота","shortname": "Лот","required": true + } + , + {"code": "tradingCurrency", + "type": 12,"name": "Наименование валюты расчета","shortname": "Валюта","link": "currencyCode","linkCode": "code","required": true + } + , + {"code": "workflowStatus", + "type": 12,"name": "Наименование статуса листинга в системе","shortname": "Статус","link": "workflowStatus","required": true + } + ] + } + , + {"method":"put", + + "name": "Изменение инструмента на режимах", + + "confirmation": "securityId,market,lotSize,tradingCurrency,workflowStatus", + + "fields": [ + {"code": "id", + "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "listing","linkCode": "id","required": true + } + , + {"code": "securityId", + "type": 1,"name": "Наименование инструмента","shortname": "Инструмент","link": "security","linkCode": "shortName","required": true,"enabled": false + } + , + {"code": "market", + "type": 12,"name": "Наименование режима","shortname": "Режим","link": "market","linkCode": "code","required": true,"enabled": false + } + , + {"code": "lotSize", + "type": 11,"name": "Размер лота","shortname": "Лот","required": true + } + , + {"code": "tradingCurrency", + "type": 12,"name": "Наименование валюты расчета","shortname": "Валюта","link": "currencyCode","linkCode": "code","required": true + } + , + {"code": "workflowStatus", + "type": 12,"name": "Наименование статуса листинга в системе","shortname": "Статус","link": "workflowStatus","required": true + } + ] + } + , + {"method":"delete", + + "name": "Блокировка инструмента на режимах", + + "confirmation": "securityId,market", + + "fields": [ + {"code": "id", + "type": 1,"name": "Идентификатор записи","shortname": "ID","link": "listing","linkCode": "id","required": true + } + ] + } + ] } , "market": { @@ -5235,7 +5310,7 @@ , "session": { - "name": "Клиринговая сессия", + "name": "Клиринговые сессии", "destination": "sessions", diff --git a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/config/SdfExecutorsConfig.java b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/config/SdfExecutorsConfig.java index 6bc274352..612692cad 100644 --- a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/config/SdfExecutorsConfig.java +++ b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/config/SdfExecutorsConfig.java @@ -3,9 +3,7 @@ package ru.spcex.clearing.balance.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import ru.spcex.clearing.balance.service.AbstractExecutor; -import ru.spcex.clearing.balance.service.Sdf01Executor; import ru.spcex.clearing.balance.service.Sdf16Executor; -import ru.spcex.clearing.balance.service.Sdf57Executor; import ru.spcex.platform.enumeration.SdfTable; import java.util.HashMap; @@ -15,15 +13,11 @@ import java.util.Map; public class SdfExecutorsConfig { @Bean("sdfExecutors") - public Map> executorsMap(Sdf01Executor sdf01Executor, - //Sdf09Executor sdf09Executor, - Sdf16Executor sdf16Executor, - Sdf57Executor sdf57Executor) { + public Map> executorsMap(//Sdf09Executor sdf09Executor, + Sdf16Executor sdf16Executor) { Map> executors = new HashMap<>(); - executors.put(SdfTable.SDF_01, sdf01Executor); // todo возможно удалят или переделают: executors.put(SdfTable.SDF_09, sdf09Executor); executors.put(SdfTable.SDF_16, sdf16Executor); - executors.put(SdfTable.SDF_57, sdf57Executor); return executors; } } diff --git a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/config/ValidationConfig.java b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/config/ValidationConfig.java index aa0745b0a..4434d8165 100644 --- a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/config/ValidationConfig.java +++ b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/config/ValidationConfig.java @@ -7,10 +7,8 @@ import ru.clearing.classes.statics.data.account.Account; import ru.clearing.classes.statics.data.account.AccountBalance; import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.company.CompanySymbols; -import ru.clearing.classes.statics.data.sdf.SDf01; import ru.clearing.classes.statics.data.sdf.SDf09; import ru.clearing.classes.statics.data.sdf.SDf16; -import ru.clearing.classes.statics.data.sdf.SDf57; import ru.spcex.clearing.balance.validation.*; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.platform.classes.base.SpcexObjectBase; @@ -46,41 +44,6 @@ public class ValidationConfig { return imdgs.get(key); } - @Bean("sdf01Validator") - public Function sdf01Validator() { - return sDf01 -> { - ImdgValidationContext context = new ImdgValidationContext<>(); - context.setValidatedObject(sDf01); - Consumer addImdg = (s) -> context.addImdg(s, getImdg(s)); - addImdg.accept(IMDGDistributedNames.Map_Account); - addImdg.accept(IMDGDistributedNames.Map_Company); - return new ValidatorImpl<>(context, - Sdf01ValidationRule.CompanyPresent, - Sdf01ValidationRule.AccountPresent, - Sdf01ValidationRule.CurrencyCode, - Sdf01ValidationRule.CurrentDateOnly, - MarketIsUValidationRule.instance, - Sdf01ValidationRule.accountType); - }; - } - - @Bean("sdf57Validator") - public Function sdf57Validator() { - return sDf57 -> { - ImdgValidationContext context = new ImdgValidationContext<>(); - context.setValidatedObject(sDf57); - Consumer addImdg = (s) -> context.addImdg(s, getImdg(s)); - addImdg.accept(IMDGDistributedNames.Map_Account); - addImdg.accept(IMDGDistributedNames.Map_Company); - return new ValidatorImpl<>(context, - Sdf57ValidationRule.CompanyDebPresent, - Sdf57ValidationRule.CompanyCredPresent, - Sdf57ValidationRule.AccountDebPresent, - Sdf57ValidationRule.CurrencyCode - ); - }; - } - @Bean("sdf16Validator") public Function sdf16Validator() { return sDf16 -> { diff --git a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/StatementService.java b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/StatementService.java index c1041b9e7..0de34e4b0 100644 --- a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/StatementService.java +++ b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/StatementService.java @@ -7,29 +7,16 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; -import ru.clearing.classes.statics.data.sdf.SDf01; -import ru.clearing.classes.statics.data.sdf.SDf16; -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.account.sdf01.AccountSdf01Request; -import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountSdfRequestPart; import ru.spcex.clearing.platform.messaging.domain.cud.balance.AccountBalanceClearingRequest; -import ru.spcex.clearing.platform.messaging.domain.cud.balance.ExportToFileRequest; -import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest; import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonIdRequest; import ru.spcex.clearing.platform.messaging.service.QueueConsumer; import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; -import ru.spcex.platform.classes.base.interfaces.WithAccount; import ru.spcex.platform.enumeration.SdfTable; -import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; -import java.util.Collection; -import java.util.EnumMap; -import java.util.List; import java.util.Map; -import java.util.stream.Collectors; @Service public class StatementService extends QueueConsumer implements InitializingBean { @@ -37,31 +24,25 @@ public class StatementService extends QueueConsumer implements InitializingBean private final ImdgProvider imdgProvider; private final KafkaSender kafkaReqProducer; - private final Map> sdfImdgs; - private final Map> executorsMap; private final AccountBalanceService accountBalanceService; @Autowired public StatementService(Consumer kafkaQueue, ImdgProvider imdgProvider, KafkaSender kafkaReqProducer, - @Qualifier("sdfExecutors") Map> executorsMap, AccountBalanceService accountBalanceService) { + @Qualifier("sdfExecutors") Map> executorsMap, + AccountBalanceService accountBalanceService) { super(kafkaQueue); this.imdgProvider = imdgProvider; this.accountBalanceService = accountBalanceService; - this.sdfImdgs = new EnumMap<>(SdfTable.class); this.kafkaReqProducer = kafkaReqProducer; - this.executorsMap = executorsMap; - this.sdfImdgs.put(SdfTable.SDF_01, imdgProvider.getImdg(IMDGDistributedNames.Map_SDf01, SDf01.class)); -// todo изменение классов. this.sdfImdgs.put(SdfTable.SDF_09, imdgProvider.getImdg(IMDGDistributedNames.Map_SDf09, SDf09.class)); - this.sdfImdgs.put(SdfTable.SDF_16, imdgProvider.getImdg(IMDGDistributedNames.Map_SDf16, SDf16.class)); } @Override public void afterPropertiesSet() throws Exception { - callback(StatementRequest.class) - .setConsumer(this::process) - .forDestination(Consts.STATEMENT_PROCESS, callbacks::put); +// callback(StatementRequest.class) +// .setConsumer(this::process) +// .forDestination(Consts.STATEMENT_PROCESS, callbacks::put); callback(AccountBalanceClearingRequest.class) .setConsumer(this::accountBalanceClearingUpdate) .forDestination(Consts.BALANCE_ACCOUNT_UPDATE, callbacks::put); @@ -77,42 +58,4 @@ public class StatementService extends QueueConsumer implements InitializingBean commonIdRequest.setId(updateAccBalanceReq.getId()); kafkaReqProducer.sendRequestToQueue(Consts.CONTINUE_CLEARING, commonIdRequest, updateAccBalanceReq.getCorrelationId()); } - - private void process(BaseRequest systemRequest) { - StatementRequest statementRequest = systemRequest.getRequestPayload(); - Collection sdfGroup; - SdfTable table = statementRequest.getTable(); - //map = getMapByTable(table) - Imdg sdfImdg = sdfImdgs.get(table); - if (statementRequest.getAccountCreationResults().size() == 0) { - sdfGroup = sdfImdg.getCollectionObjectsByFieldValues(Map.of("generationId", statementRequest.getGroupId())); - } else { - sdfGroup = statementRequest.getAccountCreationResults() - .stream() - .filter(part -> part.getErrorCode() == null) //fixme эти случае должны попадать в ошибочный sdf02 - .map(part -> sdfImdg.getSingleObjectByID(part.getSdfId())) - .collect(Collectors.toList()); - } -// sdf01Group = sdf01Group -// .stream() -// .sorted(Comparator.comparing(SpcexObjectBase::getId)) -// .collect(Collectors.toList()); - AbstractExecutor service = executorsMap.get(table); - Result res = service.execute(sdfGroup, statementRequest); - if (res.getAccountRequests().size() == 0) { - ExportToFileRequest exportRequest = new ExportToFileRequest(); - exportRequest.setSdfGroupId(res.getGenerationId()); - exportRequest.setNameOfTable(service.exportTableName()); - kafkaReqProducer.sendRequestToQueue(Consts.EXPORT_PROCESS, exportRequest); - } else { - kafkaReqProducer.sendRequestToQueue(Consts.ACCOUNT_NEW_SDF01, createAccountsRequest(statementRequest.getGroupId(), res.getAccountRequests())); - } - } - - private AccountSdf01Request createAccountsRequest(Long sdf01GroupingId, List accountRequests) { - AccountSdf01Request r = new AccountSdf01Request(); - r.setGroupingSdf01Id(sdf01GroupingId); - r.setAccounts(accountRequests); - return r; - } } diff --git a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/validation/Sdf57ValidationRule.java b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/validation/Sdf57ValidationRule.java deleted file mode 100644 index 10cb0cd85..000000000 --- a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/validation/Sdf57ValidationRule.java +++ /dev/null @@ -1,94 +0,0 @@ -package ru.spcex.clearing.balance.validation; - -import ru.clearing.classes.statics.data.account.Account; -import ru.clearing.classes.statics.data.company.Company; -import ru.clearing.classes.statics.data.sdf.SDf57; -import ru.spcex.clearing.balance.errors.BalanceError; -import ru.spcex.clearing.imdg.IMDGDistributedNames; -import ru.spcex.platform.imdg.api.Imdg; -import ru.spcex.platform.imdg.validation.ImdgValidationContext; -import ru.spcex.platform.utils.enumeration.EnumMessage; -import ru.spcex.platform.utils.text.TextUtil; -import ru.spcex.platform.utils.validation.IValidationRule; - -import java.util.Optional; - -public enum Sdf57ValidationRule implements IValidationRule> { - CompanyDebPresent() { - @Override - public Optional validate(ImdgValidationContext context) { - SDf57 sdf57 = context.getValidatedObject(); - if (TextUtil.isEmpty(sdf57.getDeal_deb())) { - return of(BalanceError.CompanyNotFound, sdf57.getDeal_deb()); - } - Imdg companyImdg = context.obtainMap(IMDGDistributedNames.Map_Company, Company.class); - Company found = companyImdg.getSingleObjectBySQL("tradingCode = '" + sdf57.getDeal_deb() + "'"); - if (found == null) { - return of(BalanceError.CompanyNotFound, sdf57.getDeal_deb()); - } - context.storeObject(ValidationStored.Sdf57CompanyDeb, found); - return empty(); - } - }, CompanyCredPresent() { - @Override - public Optional validate(ImdgValidationContext context) { - SDf57 sdf57 = context.getValidatedObject(); - if (TextUtil.isEmpty(sdf57.getDeal_cred())) { - return of(BalanceError.CompanyNotFound, sdf57.getDeal_deb()); - } - Imdg companyImdg = context.obtainMap(IMDGDistributedNames.Map_Company, Company.class); - Company found = companyImdg.getSingleObjectBySQL("tradingCode = '" + sdf57.getDeal_cred() + "'"); - if (found == null) { - return of(BalanceError.CompanyNotFound, sdf57.getDeal_deb()); - } - context.storeObject(ValidationStored.Sdf57CompanyCred, found); - return empty(); - } - }, AccountDebPresent() { - @Override - public Optional validate(ImdgValidationContext context) { - SDf57 sdf57 = context.getValidatedObject(); - if (TextUtil.isEmpty(sdf57.getC_acc_deb())) { - return of(BalanceError.AccountNotPresent, sdf57.getDeal_deb()); - } - Imdg accountImdg = context.obtainMap(IMDGDistributedNames.Map_Account, Account.class); - Account found = accountImdg.getSingleObjectBySQL("account = '" + sdf57.getC_acc_deb() + "'"); - if (found == null) { - return of(BalanceError.AccountNotPresent, sdf57.getDeal_deb()); - } - context.storeObject(ValidationStored.Sdf57AccountDeb, found); - return empty(); - } - - }, AccountCredPresent() { - @Override - public Optional validate(ImdgValidationContext context) { - SDf57 sdf57 = context.getValidatedObject(); - if (TextUtil.isEmpty(sdf57.getC_acc_cred())) { - return of(BalanceError.AccountNotPresent, sdf57.getDeal_deb()); - } - Imdg accountImdg = context.obtainMap(IMDGDistributedNames.Map_Account, Account.class); - Account found = accountImdg.getSingleObjectBySQL("account = '" + sdf57.getC_acc_cred() + "'"); - if (found == null) { - return of(BalanceError.AccountNotPresent, sdf57.getDeal_deb()); - } - context.storeObject(ValidationStored.Sdf57AccountCred, found); - return empty(); - } - - }, CurrencyCode() { - @Override - public Optional validate(ImdgValidationContext context) { - SDf57 sdf57 = context.getValidatedObject(); - if (!ru.spcex.platform.enumeration.CurrencyCode.RUR.equalsByKey(sdf57.getPay_val())) { - return of(BalanceError.CurrencyNotFound, sdf57.getPay_val()); - } - return empty(); - } - }; - - @Override - public String ruleName() { - return "Sdf57ValidationRule." + name(); - } -} diff --git a/clearing-parent/balance-service/src/test/java/ru/spcex/clearing/balance/service/AbstractServiceTest.java b/clearing-parent/balance-service/src/test/java/ru/spcex/clearing/balance/service/AbstractServiceTest.java index b77d31c7a..5e08f0f09 100644 --- a/clearing-parent/balance-service/src/test/java/ru/spcex/clearing/balance/service/AbstractServiceTest.java +++ b/clearing-parent/balance-service/src/test/java/ru/spcex/clearing/balance/service/AbstractServiceTest.java @@ -22,17 +22,13 @@ import ru.spcex.platform.imdg.iml.hazelcast.adapter.ImdgHazelcast; import java.math.BigDecimal; import java.math.RoundingMode; -import java.time.LocalDate; import java.util.concurrent.atomic.AtomicLong; -import static ru.spcex.clearing.balance.service.Sdf01ExecutorTest.acc; -import static ru.spcex.clearing.balance.service.Sdf01ExecutorTest.datFormatter; import static ru.spcex.clearing.balance.utils.MatcherFactory.usingIgnoringFieldsComparator; @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = { AccountBalanceService.class, - Sdf01Executor.class, Sdf08Service.class, // Sdf09Executor.class, Sdf16Executor.class, @@ -140,19 +136,19 @@ public abstract class AbstractServiceTest { accountBalance.setFullName(company.getFullName()); return accountBalance; } - - protected SDf01 getTestSdf01(long id, long generationId) { - LocalDate date = LocalDate.now(); - SDf01 sdf01 = new SDf01(); - sdf01.setId(id); - sdf01.setGenerationId(generationId); - sdf01.setMarket("U"); - sdf01.setDeal(deal); - sdf01.setAccount(acc); - sdf01.setCurr_code("RUR"); - sdf01.setDat(date.format(datFormatter)); - sdf01.setAcc_type("A"); - sdf01.setRemainder(amountNew.toString()); - return sdf01; - } +// +// protected SDf01 getTestSdf01(long id, long generationId) { +// LocalDate date = LocalDate.now(); +// SDf01 sdf01 = new SDf01(); +// sdf01.setId(id); +// sdf01.setGenerationId(generationId); +// sdf01.setMarket("U"); +// sdf01.setDeal(deal); +// sdf01.setAccount(acc); +// sdf01.setCurr_code("RUR"); +// sdf01.setDat(date.format(datFormatter)); +// sdf01.setAcc_type("A"); +// sdf01.setRemainder(amountNew.toString()); +// return sdf01; +// } } diff --git a/clearing-parent/balance-service/src/test/java/ru/spcex/clearing/balance/service/Sdf01ExecutorTest.java b/clearing-parent/balance-service/src/test/java/ru/spcex/clearing/balance/service/Sdf01ExecutorTest.java deleted file mode 100644 index b2633523a..000000000 --- a/clearing-parent/balance-service/src/test/java/ru/spcex/clearing/balance/service/Sdf01ExecutorTest.java +++ /dev/null @@ -1,263 +0,0 @@ -package ru.spcex.clearing.balance.service; - -import org.apache.kafka.clients.producer.MockProducer; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.SpyBean; -import ru.clearing.classes.statics.data.account.Account; -import ru.clearing.classes.statics.data.account.AccountBalance; -import ru.clearing.classes.statics.data.company.Company; -import ru.clearing.classes.statics.data.sdf.SDf01; -import ru.clearing.classes.statics.data.sdf.SDf02; -import ru.clearing.classes.statics.data.statement.Statement; -import ru.spcex.clearing.balance.errors.BalanceError; -import ru.spcex.clearing.balance.utils.MatcherFactory; -import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountSdfRequestPart; -import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest; -import ru.spcex.platform.enumeration.*; -import ru.spcex.platform.utils.enumeration.EnumMessage; -import ru.spcex.platform.utils.number.BigDecimalUtil; - -import javax.annotation.PostConstruct; -import java.time.Instant; -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; - -import static ru.spcex.clearing.balance.utils.MatcherFactory.usingIgnoringFieldsComparator; - -class Sdf01ExecutorTest extends AbstractServiceTest { - public final static DateTimeFormatter datFormatter = DateTimeFormatter.ofPattern("dd.MM.yy"); - public final static String acc = "123456789"; - private static final MatcherFactory.Matcher SDF_02_MATCHER = usingIgnoringFieldsComparator("created", "comment", "outSDfId", "generationTime", "generationId", "id"); - private final Long ID = 1L; - @Autowired - Sdf01Executor sdf01Executor; - private StatementRequest statementRequest; - @SpyBean - private MockProducer producer; - - @PostConstruct - void init() { - super.init(); - statementRequest = new StatementRequest(); - } - - /** - * {@link Sdf01Executor#execute(Collection collection, StatementRequest statementRequest)}
- * Тест проверяет генерацию сущностей {@link Result}, {@link Statement}, {@link SDf02}
- * Входные параметры:
- * accountId - {@link StatementRequest}: new StatementRequest()
- * addresseeId - {@link Collection}
- * addresseeId - {@link SDf01}
- * {@link SDf01#market} - "U"
- * {@link SDf01#deal} - "111111111"
- * {@link SDf01#account} - "123456789"
- * {@link SDf01#curr_code} - "RUR"
- * {@link SDf01#dat} - текущая дата
- * {@link SDf01#acc_type} - "A"
- * {@link SDf01#remainder} - "1000"
- */ - @Test - void execute() { - //check create statement, SDf02 and AccountBalance - SDf01 sdf01 = getTestSdf01(ID, 1L); - Company company = getTestCompany(); - companyMap.put(addresseeIdNew, company); - - Account account = getTestAccount(ID, acc); - accountMap.put(accountIdNew, account); - - Result predictableResult = new Result(); - predictableResult.setGenerationId(ID); - Statement predictableStatement = getTestStatement(currentId.getAndIncrement(), company, account, sdf01); - predictableStatement.setOperationStatus(OperationStatus.Executed.getKey()); - SDf02 predictableSdf02 = getTestSdf02(currentId.getAndIncrement(), sdf01, ID); - predictableStatement.setOutSDfId(predictableSdf02.getId()); - AccountResult predictableNewResult = getTestAccountResult(currentId.getAndIncrement(), account, company); - - Result result = sdf01Executor.execute(Collections.singletonList(sdf01), statementRequest); - Statement resultStatement = statementImdg.getSingleObjectByFieldValues(Map.of("account", acc)); - SDf02 resultSdf02 = sdf02Imdg.getSingleObjectByFieldValues(Map.of("account", acc)); - AccountBalance resultAccountBalance = accountBalanceImdg.getSingleObjectByFieldValues(Map.of("account", acc)); - - RESULT_MATCHER.assertMatch(result, predictableResult); - STATEMENT_MATCHER.assertMatch(resultStatement, predictableStatement); - SDF_02_MATCHER.assertMatch(resultSdf02, predictableSdf02); - ACCOUNT_BALANCE_MATCHER.assertMatch(resultAccountBalance, predictableNewResult.getAccount()); - } - - /** - * {@link Sdf01Executor#execute(Collection collection, StatementRequest statementRequest)}
- * Тест проверяет валидацию
- * Входные параметры:
- * accountId - {@link StatementRequest}: new StatementRequest()
- * addresseeId - {@link Collection}
- * addresseeId - {@link SDf01}
- * {@link SDf01#market} - "U"
- * {@link SDf01#deal} - "111111111"
- * {@link SDf01#account} - "123456789"
- * {@link SDf01#curr_code} - "RUR"
- * {@link SDf01#dat} - текущая дата
- * {@link SDf01#acc_type} - "A"
- * {@link SDf01#remainder} - "1000"
- */ - @Test - void validatedExecute() { - //CompanyNotFound - SDf01 sdf01 = getTestSdf01(ID, 1L); - companyMap.delete(addresseeIdNew); - checkError(new EnumMessage(BalanceError.CompanyNotFound), sdf01); - - sdf01.setDeal(null); - checkError(new EnumMessage(BalanceError.CompanyNotFound), sdf01); - - //AccountNotPresent accountType=null - sdf01.setDeal(deal); - Company company = getTestCompany(); - companyMap.put(addresseeIdNew, company); - Account account = new Account(); - account.setAccount(acc); - account.setStatus(Status.Active.getKey()); - accountMap.put(accountIdNew, account); - checkErrorAccountNotPresent(company, sdf01); - - //AccountNotPresent account=null - account.setAccount(null); - account.setAccountType(AccountType.Clrn.getKey()); - account.setStatus(Status.Active.getKey()); - accountMap.put(accountIdNew, account); - checkErrorAccountNotPresent(company, sdf01); - - //AccountNotPresent sdf01.account==null - sdf01.setAccount(null); - checkErrorAccountNotPresent(company, sdf01); - - //CurrencyNotFound sdf01.curr_code =! "RUR" - accountMap.put(accountIdNew, getTestAccount(ID, acc)); - sdf01.setAccount(acc); - sdf01.setCurr_code("RUB"); - checkError(new EnumMessage(BalanceError.CurrencyNotFound), sdf01); - - //CurrencyNotFound sdf01.curr_code =! "RUR" - sdf01.setCurr_code(null); - checkError(new EnumMessage(BalanceError.CurrencyNotFound), sdf01); - - //CurrentDateOnly - sdf01.setCurr_code("RUR"); - sdf01.setDat("19.01.23"); - checkError(new EnumMessage(BalanceError.CurrentDateOnly), sdf01); - - //CurrentDateOnly - sdf01.setDat("19.01.2023"); - checkError(new EnumMessage(BalanceError.CurrentDateOnly), sdf01); - - //CurrentDateOnly - sdf01.setDat(null); - checkError(new EnumMessage(BalanceError.CurrentDateOnly), sdf01); - - //WrongAccount - sdf01.setDat(LocalDate.now().format(datFormatter)); - sdf01.setAcc_type(null); - checkError(new EnumMessage(BalanceError.WrongAccount), sdf01); - - //WrongMarket - sdf01.setAcc_type("A"); - sdf01.setMarket(null); - checkError(new EnumMessage(BalanceError.WrongMarket), sdf01); - - sdf01.setMarket("U"); - } - - private void checkError(EnumMessage enumMessage, SDf01 sdf01) { -// SDf01 sdf01 = getTestSdf01(); - SDf02 predictableSdf02 = getTestErrorSdf02(sdf01, enumMessage, ID); - Result result = sdf01Executor.execute(Collections.singletonList(sdf01), statementRequest); - Collection resultsSdf02 = sdf02Imdg.getCollectionObjectsByFieldValues(Map.of("account", acc)); - SDf02 resultSdf02 = resultsSdf02.stream().max((entry1, entry2) -> entry1.getId() > entry2.getId() ? 1 : -1).get(); - SDF_02_MATCHER.assertMatch(resultSdf02, predictableSdf02); - } - - private void checkErrorAccountNotPresent(Company company, SDf01 sdf01) { - Result predictableResult = new Result(); - predictableResult.getAccountRequests().add(createAccountRequestPart(sdf01.getId(), sdf01.getAccount(), company.getId())); - Result result = sdf01Executor.execute(Collections.singletonList(sdf01), statementRequest); - RESULT_MATCHER.assertMatch(result, predictableResult); - - } - - private SDf02 getTestSdf02(Long id, SDf01 sdf01, Long generationIdForGroup) { - SDf02 sDf02 = new SDf02(); - sDf02.setId(id); - sDf02.setCurr_code(sdf01.getCurr_code()); - sDf02.setAccount(sdf01.getAccount()); - sDf02.setRemainder(sdf01.getRemainder()); - sDf02.setDeal(sdf01.getDeal()); - sDf02.setAcc_code(sdf01.getAcc_code()); - sDf02.setDat(sdf01.getDat()); - sDf02.setMarket(sdf01.getMarket()); - sDf02.setAcc_name(sdf01.getAcc_name()); - sDf02.setAcc_type(sdf01.getAcc_type()); - sDf02.setSumengage(sdf01.getSumengage()); - sDf02.setSumunblock(sdf01.getSumunblock()); - sDf02.setFile_type(sdf01.getFile_type()); - sDf02.setInSDfId(sdf01.getId()); - sDf02.setGenerationId(generationIdForGroup); - sDf02.setGenerationTime(Instant.now()); - sDf02.setResult("OK!"); - return sDf02; - } - - private Statement getTestStatement(Long id, Company company, Account account, SDf01 sdf01) { - Statement statement = new Statement(); - statement.setId(id); - statement.setAddresseeId(company.getId()); - statement.setSenderId(Sender.Prc.getId()); - statement.setCreated(Instant.now()); - statement.setClearingDate(LocalDate.now()); - statement.setStatementType(StatementType.full.getKey()); - statement.setAccountId(account.getId()); - statement.setAccount(sdf01.getAccount()); - statement.setInOutDirection(InOutDirection.in.getKey()); - statement.setSettlementDate(LocalDate.parse(sdf01.getDat(), datFormatter)); - statement.setAmount(BigDecimalUtil.parse(sdf01.getRemainder())); - statement.setOperationStatus(OperationStatus.Pending.getKey()); - statement.setInSDfId(sdf01.getId()); - statement.setInOutSDfType(InOutSDfType.type1.getKey()); - return statement; - } - - private SDf02 getTestErrorSdf02(SDf01 sdf01, EnumMessage error, Long generationIdForGroup) { - SDf02 sDf02 = new SDf02(); - sDf02.setId(ID); - sDf02.setCurr_code(sdf01.getCurr_code()); - sDf02.setAccount(sdf01.getAccount()); - sDf02.setRemainder(sdf01.getRemainder()); - sDf02.setDeal(sdf01.getDeal()); - sDf02.setAcc_code(sdf01.getAcc_code()); - sDf02.setDat(sdf01.getDat()); - sDf02.setMarket(sdf01.getMarket()); - sDf02.setAcc_name(sdf01.getAcc_name()); - sDf02.setAcc_type(sdf01.getAcc_type()); - sDf02.setSumengage(sdf01.getSumengage()); - sDf02.setSumunblock(sdf01.getSumunblock()); - sDf02.setFile_type(sdf01.getFile_type()); - sDf02.setInSDfId(sdf01.getId()); - String errorId = error.getSubject().getId().toString(); - sDf02.setResult(errorId.substring(errorId.length() - 3)); - sDf02.setGenerationId(generationIdForGroup); - sDf02.setGenerationTime(Instant.now()); - return sDf02; - } - - private AccountSdfRequestPart createAccountRequestPart(Long sdf01Id, String account, Long companyId) { - AccountSdfRequestPart req = new AccountSdfRequestPart(); - req.setAccount(account); - req.setCompanyId(companyId); - req.setAccountType(AccountType.Clrn.getKey()); - req.setSdfId(sdf01Id); - return req; - } -} \ No newline at end of file diff --git a/clearing-parent/balance-service/src/test/java/ru/spcex/clearing/balance/service/StatementServiceServiceTest.java b/clearing-parent/balance-service/src/test/java/ru/spcex/clearing/balance/service/StatementServiceServiceTest.java deleted file mode 100644 index 9759178f4..000000000 --- a/clearing-parent/balance-service/src/test/java/ru/spcex/clearing/balance/service/StatementServiceServiceTest.java +++ /dev/null @@ -1,137 +0,0 @@ -package ru.spcex.clearing.balance.service; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.kafka.clients.consumer.MockConsumer; -import org.apache.kafka.clients.producer.MockProducer; -import org.apache.kafka.clients.producer.ProducerRecord; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.SpyBean; -import ru.clearing.classes.statics.data.company.Company; -import ru.clearing.classes.statics.data.sdf.SDf01; -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.balance.StatementRequest; -import ru.spcex.clearing.platform.messaging.service.RequestInfo; - -import javax.annotation.PostConstruct; -import java.util.concurrent.atomic.AtomicLong; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.mockito.Mockito.timeout; -import static org.mockito.Mockito.verify; -import static ru.spcex.clearing.balance.utils.MockKafkaUtils.addRecordToKafka; -import static ru.spcex.platform.enumeration.SdfTable.SDF_01; - -class StatementServiceServiceTest extends AbstractServiceTest { - private static final String TOPIC = Consts.STATEMENT_PROCESS; - private static final int PARTITION = 1; - private static final Long groupId = 111L; - private final static AtomicLong cuurentOffset = new AtomicLong(1L); - private final Long ID = 11L; - @Autowired - StatementService statementService; - @Captor - ArgumentCaptor producerRecord; - private MockConsumer mockConsumer; - private SDf01 sDf01; - private Company company; - @SpyBean - private MockProducer producer; - - @PostConstruct - void init() { - super.init(); - mockConsumer = (MockConsumer) statementService.getConsumer(); - sDf01 = getTestSdf01(ID, groupId); - company = getTestCompany(); - } - - /** - * {@link StatementService}
- * Тест проверяет генерацию сущностей {@link RequestInfo}
- * Входные параметры:
- * {@link StatementRequest}: new StatementRequest()
- * {@link StatementRequest#table} - SDF_01
- */ - @Test - void processEXPORT_PROCESS() { - sdf01Imdg.delete(sDf01); - companyImdg.delete(company); - - companyImdg.delete(company); - StatementRequest statementRequest = new StatementRequest(); - statementRequest.setGroupId(groupId); - statementRequest.setTable(SDF_01); - BaseRequest baseNewRequest = new BaseRequest<>(); - baseNewRequest.setRequestPayload(statementRequest); - baseNewRequest.setId(currentId.getAndIncrement()); - baseNewRequest.setActionType(ActionType.NEW); - String jsonBaseNewRequest; - ObjectMapper objectMapper = new ObjectMapper(); - try { - jsonBaseNewRequest = objectMapper.writeValueAsString(baseNewRequest); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - - addRecordToKafka(mockConsumer, TOPIC, PARTITION, cuurentOffset.getAndIncrement(), jsonBaseNewRequest); - - //waiting for kafka producer send message (finale event) - verify(producer, timeout(30_000L).times(1)) - .send(producerRecord.capture()); - - BaseRequest baseRequest = (BaseRequest) producerRecord.getValue().value(); - RequestInfo resultRequestInfo = requestInfoImdg.getSingleObjectByID(baseRequest.getId()); - - assertEquals(Consts.EXPORT_PROCESS, producerRecord.getValue().topic()); - assertNotNull(baseRequest); - assertNotNull(resultRequestInfo); - } - - /** - * {@link StatementService}
- * Тест проверяет генерацию сущностей {@link RequestInfo}
- * Входные параметры:
- * {@link StatementRequest}: new StatementRequest()
- * {@link StatementRequest#table} - SDF_01
- */ - @Test - void processACCOUNT_NEW() { - sdf01Imdg.insert(sDf01); - companyImdg.insert(company); - - StatementRequest statementRequest = new StatementRequest(); - statementRequest.setGroupId(groupId); - statementRequest.setTable(SDF_01); - BaseRequest baseNewRequest = new BaseRequest<>(); - baseNewRequest.setRequestPayload(statementRequest); - baseNewRequest.setId(currentId.getAndIncrement()); - baseNewRequest.setActionType(ActionType.NEW); - String jsonBaseNewRequest; - ObjectMapper objectMapper = new ObjectMapper(); - try { - jsonBaseNewRequest = objectMapper.writeValueAsString(baseNewRequest); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - - addRecordToKafka(mockConsumer, TOPIC, PARTITION, cuurentOffset.getAndIncrement(), jsonBaseNewRequest); - - //waiting for kafka producer send message (finale event) - verify(producer, timeout(30_000L).times(1)) - .send(producerRecord.capture()); - - BaseRequest baseRequest = (BaseRequest) producerRecord.getValue().value(); - RequestInfo resultRequestInfo = requestInfoImdg.getSingleObjectByID(baseRequest.getId()); - - assertEquals(Consts.ACCOUNT_NEW_SDF01, producerRecord.getValue().topic()); - assertNotNull(baseRequest); - assertNotNull(resultRequestInfo); - } -} \ No newline at end of file diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/SdfExecutorsConfig.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/SdfExecutorsConfig.java new file mode 100644 index 000000000..86a1142e9 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/SdfExecutorsConfig.java @@ -0,0 +1,24 @@ +package ru.spcex.clearing.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import ru.spcex.clearing.service.executors.AbstractExecutor; +import ru.spcex.clearing.service.executors.Sdf01Executor; +import ru.spcex.clearing.service.executors.Sdf57Executor; +import ru.spcex.platform.enumeration.SdfTable; + +import java.util.HashMap; +import java.util.Map; + +@Configuration +public class SdfExecutorsConfig { + + @Bean("sdfExecutors") + public Map> executorsMap(Sdf01Executor sdf01Executor, + Sdf57Executor sdf57Executor) { + Map> executors = new HashMap<>(); + executors.put(SdfTable.SDF_01, sdf01Executor); + executors.put(SdfTable.SDF_57, sdf57Executor); + return executors; + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java index 95f979e72..afa056312 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java @@ -10,12 +10,11 @@ import ru.clearing.classes.statics.data.execution.ExecutionDeposit; import ru.clearing.classes.statics.data.misc.STrades; import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.registry.TradingClearingRegistry; +import ru.clearing.classes.statics.data.sdf.SDf01; +import ru.clearing.classes.statics.data.sdf.SDf57; import ru.clearing.classes.statics.data.security.Security; import ru.spcex.clearing.imdg.IMDGDistributedNames; -import ru.spcex.clearing.service.validation.ClrngValidationStored; -import ru.spcex.clearing.service.validation.ExecutionDepositValidationRule; -import ru.spcex.clearing.service.validation.RegistryStep3ValidationRule; -import ru.spcex.clearing.service.validation.STradesValidationRule; +import ru.spcex.clearing.service.validation.*; import ru.spcex.platform.classes.base.SpcexObjectBase; import ru.spcex.platform.enumeration.ClearingCategory; import ru.spcex.platform.imdg.api.Imdg; @@ -28,6 +27,7 @@ import java.util.HashMap; import java.util.Map; import java.util.function.BiConsumer; import java.util.function.BiFunction; +import java.util.function.Consumer; import java.util.function.Function; @Configuration @@ -107,4 +107,37 @@ public class ValidationConfig { RegistryStep3ValidationRule.TradingClearingRegistryActive); }; } + @Bean("sdf01Validator") + public Function sdf01Validator() { + return sDf01 -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(sDf01); + Consumer addImdg = (s) -> context.addImdg(s, getImdg(s)); + addImdg.accept(IMDGDistributedNames.Map_Account); + addImdg.accept(IMDGDistributedNames.Map_Company); + return new ValidatorImpl<>(context, + Sdf01ValidationRule.CompanyPresent, + Sdf01ValidationRule.AccountPresent, + Sdf01ValidationRule.CurrencyCode, + Sdf01ValidationRule.CurrentDateOnly, + MarketIsUValidationRule.instance, + Sdf01ValidationRule.accountType); + }; + } + + @Bean("sdf57Validator") + public Function sdf57Validator() { + return sDf57 -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(sDf57); + Consumer addImdg = (s) -> context.addImdg(s, getImdg(s)); + addImdg.accept(IMDGDistributedNames.Map_Account); + addImdg.accept(IMDGDistributedNames.Map_Company); + return new ValidatorImpl<>(context, + Sdf57ValidationRule.CompanyDebOrCredPresent, + Sdf57ValidationRule.AccountDebOrCredPresent, + Sdf57ValidationRule.CurrencyCode + ); + }; + } } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingError.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingError.java index 9dd2a2595..578fd53ac 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingError.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingError.java @@ -4,13 +4,16 @@ import ru.spcex.platform.utils.enumeration.IErrorEnumId; public enum ClearingError implements IErrorEnumId { GeneralError(5400L), + IncorrectValue(5404L), RecordNotFound(5406L), + CompanyNotFound(5410L), CompanyNotActive(5411L), CompanyCreditCheck(5412L), CompanyDebitCheck(5413L), - CompanyNotFound(5410L), + AccountNotFound(5414L), AccountNotActive(5415L), SecurityNotFound(5416L), + AccountNotPresent(5417L), TradingClearingRegistryNotFound(5418L), TradingClearingRegistryNotActive(5419L), ClearingUnavailableForCompany(5421L), diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/EventsReceiver.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/EventsReceiver.java index 758b9be7b..3e51ed48e 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/EventsReceiver.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/EventsReceiver.java @@ -9,6 +9,7 @@ import ru.spcex.clearing.platform.messaging.domain.cud.clearing.Sdf04Request; import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonIdRequest; import ru.spcex.clearing.platform.messaging.domain.cud.schedule.LauncherCommandRequest; import ru.spcex.clearing.platform.messaging.service.QueueConsumer; +import ru.spcex.clearing.session.stage.PrimaryAuctionB0Session; import ru.spcex.clearing.session.stage.PrimaryAuctionBnSession; import ru.spcex.platform.enumeration.Task; @@ -17,15 +18,18 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean { private final ClearingService clearingService; private final RegistryService registryService; private final PrimaryAuctionBnSession primaryAuctionBnSession; + private final PrimaryAuctionB0Session primaryAuctionB0Session; public EventsReceiver(Consumer kafkaQueue, ClearingService clearingService, RegistryService registryService, - PrimaryAuctionBnSession primaryAuctionBnSession) { + PrimaryAuctionBnSession primaryAuctionBnSession, + PrimaryAuctionB0Session primaryAuctionB0Session) { super(kafkaQueue); this.clearingService = clearingService; this.registryService = registryService; this.primaryAuctionBnSession = primaryAuctionBnSession; + this.primaryAuctionB0Session = primaryAuctionB0Session; } @Override @@ -42,15 +46,25 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean { callback(LauncherCommandRequest.class) .setConsumer(event -> clearingService.executeVerification()) .forDestination(Task.getVerification.topic(), callbacks::put); - callback(Object.class) - .setConsumer(primaryAuctionBnSession::runSession) - .forDestination(Task.startOfClearing.topic(), callbacks::put); callback(CommonIdRequest.class) .setConsumer(clearingService::continueClearing) .forDestination(Consts.CONTINUE_CLEARING, callbacks::put); + + callback(Object.class) + .setConsumer(primaryAuctionB0Session::runSession) + .forDestination(Task.startOfB0.topic(), callbacks::put); +// callback(Object.class) +// .setConsumer(primaryAuctionB0Session::continueSession) +// .forDestination(Task.startOfB0.topic(), callbacks::put); + + + callback(Object.class) + .setConsumer(primaryAuctionBnSession::runSession) + .forDestination(Task.startOfClearing.topic(), callbacks::put); callback(Object.class) .setConsumer(primaryAuctionBnSession::continueSession) .forDestination(Consts.SDF57_PROCESS, callbacks::put); + callback(Object.class) .setConsumer(event -> clearingService.executeSTrade()) .forDestination(Task.getOfTrades.topic(), callbacks::put); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/LoggingService.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/LoggingService.java new file mode 100644 index 000000000..c12ce4cf4 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/LoggingService.java @@ -0,0 +1,27 @@ +package ru.spcex.clearing.service; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import ru.spcex.platform.utils.enumeration.EnumMessage; +import ru.spcex.platform.utils.enumeration.IMessageResolver; + +@Component +public class LoggingService { + private final Logger log = LoggerFactory.getLogger(getClass()); + private final IMessageResolver errorResolver; + + @Autowired + public LoggingService(IMessageResolver errorResolver) { + this.errorResolver = errorResolver; + } + + public void logError(String message, EnumMessage error, Object... args) { + log.error(message + " {}", args, errorResolver.resolve(error)); + } + + public void logError(EnumMessage error) { + log.error("{}", errorResolver.resolve(error)); + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/StatementService.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/StatementService.java new file mode 100644 index 000000000..dd42e9530 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/StatementService.java @@ -0,0 +1,98 @@ +package ru.spcex.clearing.service; + +import org.apache.kafka.clients.consumer.Consumer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; +import ru.clearing.classes.statics.data.sdf.SDf01; +import ru.clearing.classes.statics.data.sdf.SDf57; +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.account.sdf01.AccountSdf01Request; +import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountSdfRequestPart; +import ru.spcex.clearing.platform.messaging.domain.cud.balance.ExportToFileRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest; +import ru.spcex.clearing.platform.messaging.service.QueueConsumer; +import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; +import ru.spcex.clearing.service.executors.AbstractExecutor; +import ru.spcex.clearing.service.model.Result; +import ru.spcex.platform.classes.base.SpcexObjectBase; +import ru.spcex.platform.enumeration.SdfTable; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; + +import java.util.Collection; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Service +public class StatementService extends QueueConsumer implements InitializingBean { + private final Logger log = LoggerFactory.getLogger(getClass()); + + private final ImdgProvider imdgProvider; + private final KafkaSender kafkaSender; + private final Map> sdfImdgs; + private final Map> executorsMap; + + @Autowired + public StatementService(Consumer kafkaQueue, + ImdgProvider imdgProvider, + KafkaSender kafkaSender, + @Qualifier("sdfExecutors") Map> executorsMap) { + super(kafkaQueue); + this.imdgProvider = imdgProvider; + this.sdfImdgs = new EnumMap<>(SdfTable.class); + this.kafkaSender = kafkaSender; + this.executorsMap = executorsMap; + this.sdfImdgs.put(SdfTable.SDF_01, imdgProvider.getImdg(IMDGDistributedNames.Map_SDf01, SDf01.class)); + this.sdfImdgs.put(SdfTable.SDF_57, imdgProvider.getImdg(IMDGDistributedNames.Map_SDf57, SDf57.class)); + } + + @Override + public void afterPropertiesSet() throws Exception { + callback(StatementRequest.class) + .setConsumer(this::process) + .forDestination(Consts.STATEMENT_PROCESS, callbacks::put); + init(); + } + + private void process(BaseRequest systemRequest) { + StatementRequest statementRequest = systemRequest.getRequestPayload(); + Collection sdfGroup; + SdfTable table = statementRequest.getTable(); + Imdg sdfImdg = sdfImdgs.get(table); + if (statementRequest.getAccountCreationResults().size() == 0) { + sdfGroup = sdfImdg.getCollectionObjectsByFieldValues(Map.of("generationId", statementRequest.getGroupId())); + } else { + sdfGroup = statementRequest.getAccountCreationResults() + .stream() + .filter(part -> part.getErrorCode() == null) //fixme эти случае должны попадать в ошибочный sdf02 + .map(part -> sdfImdg.getSingleObjectByID(part.getSdfId())) + .collect(Collectors.toList()); + } + + AbstractExecutor service = executorsMap.get(table); + Result res = service.execute(sdfGroup, statementRequest); + if (res.getAccountRequests().size() != 0) { + kafkaSender.sendRequestToQueue(Consts.ACCOUNT_NEW_SDF01, createAccountsRequest(statementRequest.getGroupId(), res.getAccountRequests())); + } else if (service.isNeedToSendCommandToExport()) { + ExportToFileRequest exportRequest = new ExportToFileRequest(); + exportRequest.setSdfGroupId(res.getGenerationId()); + exportRequest.setNameOfTable(service.exportTableName()); + kafkaSender.sendRequestToQueue(Consts.EXPORT_PROCESS, exportRequest); + } + } + + private AccountSdf01Request createAccountsRequest(Long sdf01GroupingId, List accountRequests) { + AccountSdf01Request r = new AccountSdf01Request(); + r.setGroupingSdf01Id(sdf01GroupingId); + r.setAccounts(accountRequests); + return r; + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/AbstractExecutor.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/AbstractExecutor.java new file mode 100644 index 000000000..b1bc4cddf --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/AbstractExecutor.java @@ -0,0 +1,12 @@ +package ru.spcex.clearing.service.executors; + +import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest; +import ru.spcex.clearing.service.model.Result; + +import java.util.Collection; + +public abstract class AbstractExecutor { + public abstract Result execute(Collection sdf, StatementRequest statementRequest); + public abstract String exportTableName(); + public abstract boolean isNeedToSendCommandToExport(); +} diff --git a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/Sdf01Executor.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf01Executor.java similarity index 87% rename from clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/Sdf01Executor.java rename to clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf01Executor.java index 4b321782d..e2b30c58c 100644 --- a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/Sdf01Executor.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf01Executor.java @@ -1,4 +1,4 @@ -package ru.spcex.clearing.balance.service; +package ru.spcex.clearing.service.executors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -9,11 +9,13 @@ import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.sdf.SDf01; import ru.clearing.classes.statics.data.sdf.SDf02; import ru.clearing.classes.statics.data.statement.Statement; -import ru.spcex.clearing.balance.errors.BalanceError; -import ru.spcex.clearing.balance.validation.ValidationStored; +import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountSdfRequestPart; import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest; +import ru.spcex.clearing.service.LoggingService; +import ru.spcex.clearing.service.model.Result; +import ru.spcex.clearing.service.validation.ValidationStored; import ru.spcex.platform.enumeration.*; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; @@ -40,14 +42,12 @@ public class Sdf01Executor extends AbstractExecutor { private final LoggingService errorLogger; private final Imdg sdf02Imdg; private final ImdgProvider imdgProvider; - private final AccountBalanceService accountBalanceService; private final IMessageResolver errorResolver; private final Imdg accountBalanceImdg; public Sdf01Executor(Function sDf01Validator, LoggingService errorLogger, ImdgProvider imdgProvider, - AccountBalanceService accountBalanceService, IMessageResolver errorResolver) { this.statementImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class); this.sdf02Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf02, SDf02.class); @@ -56,15 +56,19 @@ public class Sdf01Executor extends AbstractExecutor { this.sDf01Validator = sDf01Validator; this.errorLogger = errorLogger; this.imdgProvider = imdgProvider; - this.accountBalanceService = accountBalanceService; this.errorResolver = errorResolver; } @Override - String exportTableName() { + public String exportTableName() { return "DF-02"; } + @Override + public boolean isNeedToSendCommandToExport() { + return true; + } + public Result execute(Collection sdf, StatementRequest statementRequest) { Result result = new Result(); Long generationIdForGroup = imdgProvider.getImdgIdGenerator().nextId(); @@ -74,14 +78,14 @@ public class Sdf01Executor extends AbstractExecutor { Optional error = validator.tillFirstError(); Company company = validator.getStored(ValidationStored.Company); if (statementRequest.getAccountCreationResults().size() == 0 - && BalanceError.AccountNotPresent.equals(error.map(EnumMessage::getSubject).orElse(null))) { + && ClearingError.AccountNotPresent.equals(error.map(EnumMessage::getSubject).orElse(null))) { //на данном шаге company существует -> getId ok //формируем пакетный запрос на добавление account //ответ придет в этот же метод, process result.getAccountRequests().add(createAccountRequestPart(sdf01.getId(), sdf01.getAccount(), company.getId())); log.info("account {} for sdf01.id={} not found - send request for creation", sdf01.getAccount(), sdf01.getId()); continue; - } else if (BalanceError.AccountNotPresent.equals(error.map(EnumMessage::getSubject).orElse(null))) { + } else if (ClearingError.AccountNotPresent.equals(error.map(EnumMessage::getSubject).orElse(null))) { log.error("fatal error: resumed processing after generating accounts, but no account found for sdf01.id={}", sdf01.getId()); } if (error.isPresent()) { @@ -101,15 +105,15 @@ public class Sdf01Executor extends AbstractExecutor { SDf02 sdf02New = createSuccessSdf02(sdf01, generationIdForGroup); sdf02Imdg.insert(sdf02New); statement.setOutSDfId(sdf02New.getId()); - AccountResult accountResult = accountBalanceService.createAccountBalance(statement.getAddresseeId(), statement.getAccountId(), statement.getAmount(), - null/*statement.getCashMovementCurrencyCode()*/); - if (accountResult.getError() != null) { - statement.setErrorCodeId(accountResult.getError().getSubject().getId()); - // todo statement.setErrorText(errorResolver.resolve(accountResult.getError())); - } else { - accountBalanceImdg.insert(accountResult.getAccount()); //insert == update? - statement.setOperationStatus(OperationStatus.Executed.getKey()); - } +// AccountResult accountResult = accountBalanceService.createAccountBalance(statement.getAddresseeId(), statement.getAccountId(), statement.getAmount(), +// null/*statement.getCashMovementCurrencyCode()*/); +// if (accountResult.getError() != null) { +// statement.setErrorCodeId(accountResult.getError().getSubject().getId()); +// todo statement.setErrorText(errorResolver.resolve(accountResult.getError())); +// } else { +// accountBalanceImdg.insert(accountResult.getAccount()); //insert == update? +// statement.setOperationStatus(OperationStatus.Executed.getKey()); +// } statementImdg.update(statement); } return result; diff --git a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/Sdf57Executor.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf57Executor.java similarity index 56% rename from clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/Sdf57Executor.java rename to clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf57Executor.java index aefba2ef7..21fd8fa77 100644 --- a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/Sdf57Executor.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf57Executor.java @@ -1,4 +1,4 @@ -package ru.spcex.clearing.balance.service; +package ru.spcex.clearing.service.executors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -10,20 +10,29 @@ import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.sdf.SDf02; import ru.clearing.classes.statics.data.sdf.SDf57; +import ru.clearing.classes.statics.data.security.Security; import ru.clearing.classes.statics.data.statement.Statement; -import ru.spcex.clearing.balance.errors.BalanceError; -import ru.spcex.clearing.balance.validation.ValidationStored; +import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest; +import ru.spcex.clearing.service.LoggingService; +import ru.spcex.clearing.service.model.Result; +import ru.spcex.clearing.service.validation.ValidationStored; +import ru.spcex.clearing.session.stage.util.RegistryUtil; import ru.spcex.platform.enumeration.*; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; +import ru.spcex.platform.imdg.api.predicate.specific.RegistryCodeSqlBuilder; import ru.spcex.platform.utils.enumeration.EnumMessage; +import ru.spcex.platform.utils.enumeration.IEnumKey; import ru.spcex.platform.utils.enumeration.IMessageResolver; import ru.spcex.platform.utils.text.TextUtil; import ru.spcex.platform.utils.validation.IValidator; import java.math.BigDecimal; +import java.time.Instant; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.Collection; @@ -42,15 +51,14 @@ public class Sdf57Executor extends AbstractExecutor { private final LoggingService errorLogger; private final Imdg sdf02Imdg; private final ImdgProvider imdgProvider; - private final AccountBalanceService accountBalanceService; private final IMessageResolver errorResolver; private final Imdg accountBalanceImdg; + private final Imdg securityImdg; private final IMessageResolver messageResolver; public Sdf57Executor(@Qualifier("sdf57Validator") Function sDf57Validator, LoggingService errorLogger, ImdgProvider imdgProvider, - AccountBalanceService accountBalanceService, IMessageResolver errorResolver, IMessageResolver messageResolver) { this.statementImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class); this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); @@ -59,15 +67,20 @@ public class Sdf57Executor extends AbstractExecutor { this.sDf57Validator = sDf57Validator; this.errorLogger = errorLogger; this.imdgProvider = imdgProvider; - this.accountBalanceService = accountBalanceService; this.errorResolver = errorResolver; this.messageResolver = messageResolver; + this.securityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Security, Security.class); } @Override - String exportTableName() { - return "DF-57"; - } //no need... + public String exportTableName() { + return null; + } + + @Override + public boolean isNeedToSendCommandToExport() { + return false; + }//no need... //V - Изменение statement по sDf57 // @@ -99,31 +112,45 @@ public class Sdf57Executor extends AbstractExecutor { log.error("error while validating sdf57.id={} - {}", sdf57.getId(), messageResolver.resolve(error.get())); continue; } + TriFunction> createStatementIfNeeded = (company, account, inOut) -> { + if (company == null || account == null) { + return Optional.empty(); + } + Statement statement = create(sdf57, company, account, inOut); + statementImdg.insert(statement); + return Optional.of(statement); + }; //create by companyDeb - Company companyDeb = validator.getStored(ValidationStored.Sdf57CompanyDeb); + Company companyDeb = validator.getStored(ValidationStored.Sdf57CompanyDeb); //плательщик Account accountDeb = validator.getStored(ValidationStored.Sdf57AccountDeb); - Statement statementDeb = create(sdf57, companyDeb, accountDeb); - statementImdg.insert(statementDeb); - //create by companyCred - Company companyCred = validator.getStored(ValidationStored.Sdf57CompanyCred); + Company companyCred = validator.getStored(ValidationStored.Sdf57CompanyCred);//получатель Account accountCred = validator.getStored(ValidationStored.Sdf57AccountCred); - Statement statementCred = create(sdf57, companyCred, accountCred); - statementImdg.insert(statementCred); + + //адресат CREDIT / владелец DEBIT + Optional statementDeb = createStatementIfNeeded.apply(companyDeb, accountDeb, InOutDirection.in); + //адресат DEBIT / владелец CREDIT + Optional statementCred = createStatementIfNeeded.apply(companyCred, accountCred, InOutDirection.out); Consumer createRegistryIfNeeded = stmtCmpAcc -> { Statement stmt = stmtCmpAcc.statement(); - Optional err = validateActiveness(stmtCmpAcc.company(), stmtCmpAcc.account(), stmt); + Company company = stmtCmpAcc.company(); + Account account = stmtCmpAcc.account(); + if (account == null) + return; + Optional err = validateActiveness(company, account); if (err.isEmpty()) { Consumer update = rgs -> { updateReg(stmt, rgs); registryImdg.update(rgs); }; - Runnable create = () -> { - Registry registry = createRegistryByStatement(stmt); + Consumer create = (dsgn) -> { + Registry registry = createRegistryByStatement(stmt, company, account, dsgn); registryImdg.insert(registry); }; - findReg(stmt, RegistryDesignation.A).ifPresentOrElse(update, create); - findReg(stmt, RegistryDesignation.D).ifPresentOrElse(update, create); + + //todo понять что происходит со инициатором/контрагентом, особенно если у нас только один Statement + findReg(stmt, RegistryDesignation.A).ifPresentOrElse(update, () -> create.accept(RegistryDesignation.A)); + findReg(stmt, RegistryDesignation.D).ifPresentOrElse(update, () -> create.accept(RegistryDesignation.D)); stmt.setOperationStatus(OperationStatus.Executed.getKey()); } else { stmt.setErrorCodeId(err.get().getSubject().getId()); // fixme ErrorText insert @@ -131,26 +158,26 @@ public class Sdf57Executor extends AbstractExecutor { statementImdg.update(stmt); } }; - createRegistryIfNeeded.accept(new StmtCmpAcc(statementDeb, companyDeb, accountDeb)); - createRegistryIfNeeded.accept(new StmtCmpAcc(statementCred, companyCred, accountCred)); + statementDeb.ifPresent(stmt -> createRegistryIfNeeded.accept(new StmtCmpAcc(stmt, companyDeb, accountDeb))); + statementCred.ifPresent(stmt -> createRegistryIfNeeded.accept(new StmtCmpAcc(stmt, companyCred, accountCred))); } return result; } - private static record StmtCmpAcc(Statement statement, Company company, Account account) { + private record StmtCmpAcc(Statement statement, Company company, Account account) { } - private Optional validateActiveness(Company company, Account account, Statement statement) { + private Optional validateActiveness(Company company, Account account) { if (!WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus())) { - return Optional.of(new EnumMessage(BalanceError.CompanyNotActive, company.getId())); + return Optional.of(new EnumMessage(ClearingError.CompanyNotActive, company.getId())); } if (!WorkflowStatus.Active.equalsByKey(account.getStatus())) { - return Optional.of(new EnumMessage(BalanceError.AccountNotActive, account.getId())); + return Optional.of(new EnumMessage(ClearingError.AccountNotActive, account.getId())); } return Optional.empty(); } - private Statement create(SDf57 sdf57, Company companyDeb, Account accountDeb) { + private Statement create(SDf57 sdf57, Company companyDeb, Account accountDeb, InOutDirection inOutDirection) { Statement statement = new Statement(); statement.setAddresseeId(companyDeb.getId()); statement.setSenderId(Sender.Prc.getId()); @@ -158,8 +185,8 @@ public class Sdf57Executor extends AbstractExecutor { statement.setContract(getContractFromSpecif(sdf57.getSpecif())); statement.setAccountId(accountDeb.getId()); statement.setAccount(accountDeb.getAccount()); - statement.setInOutDirection(InOutDirection.out.getKey()); - statement.setSettlementDate(payDate(sdf57.getPay_date())); //fixme pay_date format + statement.setInOutDirection(inOutDirection.getKey()); + statement.setSettlementDate(payDate(sdf57.getPay_date())); statement.setAmount(TextUtil.isEmpty(sdf57.getSum_deb()) ? null : new BigDecimal(sdf57.getSum_deb())); statement.setOperationStatus(OperationStatus.Pending.getKey()); statement.setInSDfId(sdf57.getId()); @@ -167,34 +194,83 @@ public class Sdf57Executor extends AbstractExecutor { return statement; } - private Registry createRegistryByStatement(Statement statement) { - //todo - return new Registry(); + private Registry createRegistryByStatement(Statement statement, Company company, Account account, RegistryDesignation designation) { + Registry rgs = new Registry(); + rgs.setCompanyId(statement.getAddresseeId()); + rgs.setTradingCode(company.getTradingCode()); + rgs.setClearingCode(company.getClearingCode()); + rgs.setShortName(company.getShortName()); + rgs.setFullName(company.getFullName()); + rgs.setAccountId(account.getId()); + rgs.setAccountType(account.getAccountType()); + rgs.setAccount(account.getAccount()); + rgs.setRegistryDesignation(designation.getKey()); + rgs.setRegistryInstrumentType(RegistryInstrumentType.M.getKey()); + rgs.setRegistryCapacity(RegistryCapacity.A.getKey()); + rgs.setRegistryUnit(RegistryUnit.T.getKey()); + rgs.setRegistryCode(RegistryUtil.clearingCode(rgs)); + //rgs.setTradingClearingRegistryId(); //todo ! + //rgs.setTradingClearingRegistry(); //todo ! + rgs.setRegistryStatus(RegistryStatus.PROC.getKey()); + rgs.setSecurityId(statement.getSecurityId()); + if (statement.getSecurityId() != null) { + Security security = securityImdg.getSingleObjectByID(statement.getSecurityId()); + if (security != null) { + rgs.setSecuritySymbol(security.getSecuritySymbol()); + } + } + InOutDirection inOutDirection = IEnumKey.getEnumByKey(InOutDirection.class, statement.getInOutDirection()); + //считаю balance при создании нулевым и исхожу из этого + //При добавлении (на базе изменения statement по sDf57): + //Если значение statement.inOutDirection=IN, то: + //= текущее значение registry.balance + statement.amount + // + //Если значение statement.inOutDirection=OUT, то: + //= текущее значение registry.balance - statement.amount + switch (inOutDirection) { + case in -> rgs.setBalance(statement.getAmount()); + case out -> rgs.setBalance(statement.getAmount().negate()); + } + rgs.setBalanceDimension(BalanceDimension.MONY.getKey()); //fixme ! смотри описание и ссылка на начало html'ки + //fixme !rgs.setSettlementCode(); + rgs.setTradingDate(statement.getSettlementDate()); //fixme ! today ? + rgs.setClearingDate(LocalDate.now()); + //fixme rgs.setRefundDate(); + //fixme rgs.setValueDate(); + rgs.setContract(statement.getContract()); + //создается на базе stmt, companyCred, accountDeb + rgs.setCounterPartyId(statement.getAddresseeId()); + rgs.setCreated(Instant.now()); + return rgs; } private void updateReg(Statement s, Registry r) { - //todo + InOutDirection direction = IEnumKey.getEnumByKey(InOutDirection.class, s.getInOutDirection()); + switch (direction) { + case in -> r.setBalance(r.getBalance().add(s.getAmount())); + case out -> r.setBalance(r.getBalance().subtract(s.getAmount())); + } + r.setUpdated(Instant.now()); } private Optional findReg(Statement s, RegistryDesignation des) { - //todo add dependency on Registry search -// RegistryTradingParams p = new RegistryTradingParams( -// des, RegistryInstrumentType.M, RegistryCapacity.A, RegistryUnit.T -// ); -// String sql = RegistryCodeSqlBuilder.getInstance(p).build(); -// ImdgPredicateBuilder pb = registryImdg.predicateBuilder(); -// ImdgPredicate rgstrPredicate = pb.and(pb.sql(sql), -// pb.sql(sql), -// pb.equals("companyId", s.getAddresseeId()) //fixme companyId? -// ); -// if (des.equals(RegistryDesignation.D) && !TextUtil.isEmpty(s.getContract())) { -// rgstrPredicate = pb.and(rgstrPredicate, pb.equals("contract", s.getContract())); -// } -// return Optional.ofNullable(registryImdg.getSingleObjectByPredicate(rgstrPredicate)); - return null; + RegistryTradingParams p = new RegistryTradingParams( + des, RegistryInstrumentType.M, RegistryCapacity.A, RegistryUnit.T + ); + String sql = RegistryCodeSqlBuilder.getInstance(p).build(); + ImdgPredicateBuilder pb = registryImdg.predicateBuilder(); + ImdgPredicate rgstrPredicate = pb.and(pb.sql(sql), + pb.sql(sql), + pb.equals("companyId", s.getAddresseeId()) //fixme companyId? + ); + if (des.equals(RegistryDesignation.D) && !TextUtil.isEmpty(s.getContract())) { + rgstrPredicate = pb.and(rgstrPredicate, pb.equals("contract", s.getContract())); + } + return Optional.ofNullable(registryImdg.getSingleObjectByPredicate(rgstrPredicate)); } - DateTimeFormatter payDateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd"); + DateTimeFormatter payDateFormatter = DateTimeFormatter.ofPattern("yy.MM.dd"); + private LocalDate payDate(String payDate) { if (TextUtil.isEmpty(payDate)) { return null; @@ -212,4 +288,9 @@ public class Sdf57Executor extends AbstractExecutor { } return specif.substring(index + 1); } + + @FunctionalInterface + private static interface TriFunction { + R apply(T1 arg1, T2 arg2, T3 arg3); + } } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/model/Result.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/model/Result.java new file mode 100644 index 000000000..d5e3896cb --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/model/Result.java @@ -0,0 +1,27 @@ +package ru.spcex.clearing.service.model; + +import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountSdfRequestPart; + +import java.util.ArrayList; +import java.util.List; + +public class Result { + private List accountRequests = new ArrayList<>(); + private Long generationId; + + public List getAccountRequests() { + return accountRequests; + } + + public void setAccountRequests(List accountRequests) { + this.accountRequests = accountRequests; + } + + public Long getGenerationId() { + return generationId; + } + + public void setGenerationId(Long generationId) { + this.generationId = generationId; + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/MarketIsUValidationRule.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/MarketIsUValidationRule.java new file mode 100644 index 000000000..fe69b0b2d --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/MarketIsUValidationRule.java @@ -0,0 +1,23 @@ +package ru.spcex.clearing.service.validation; + +import ru.spcex.clearing.error.ClearingError; +import ru.spcex.platform.classes.base.interfaces.WithMarket; +import ru.spcex.platform.imdg.validation.ImdgValidationContext; +import ru.spcex.platform.utils.enumeration.EnumMessage; +import ru.spcex.platform.utils.validation.IValidationRule; + +import java.util.Optional; + +public class MarketIsUValidationRule implements IValidationRule> { + + public static final MarketIsUValidationRule instance = new MarketIsUValidationRule(); + + @Override + public Optional validate(ImdgValidationContext context) { + WithMarket validatedObject = context.getValidatedObject(); + if (!"U".equals(validatedObject.getMarket())) { + return of(ClearingError.AccountNotActive); + } + return empty(); + } +} diff --git a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/validation/Sdf01ValidationRule.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf01ValidationRule.java similarity index 84% rename from clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/validation/Sdf01ValidationRule.java rename to clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf01ValidationRule.java index 400afda73..9fbaa9e42 100644 --- a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/validation/Sdf01ValidationRule.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf01ValidationRule.java @@ -1,9 +1,9 @@ -package ru.spcex.clearing.balance.validation; +package ru.spcex.clearing.service.validation; import ru.clearing.classes.statics.data.account.Account; import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.sdf.SDf01; -import ru.spcex.clearing.balance.errors.BalanceError; +import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.platform.enumeration.AccountType; import ru.spcex.platform.imdg.api.Imdg; @@ -23,12 +23,12 @@ public enum Sdf01ValidationRule implements IValidationRule validate(ImdgValidationContext context) { SDf01 sdf01 = context.getValidatedObject(); if (sdf01.getDeal() == null) { - return of(BalanceError.CompanyNotFound); + return of(ClearingError.CompanyNotFound); } Imdg companyImdg = context.obtainMap(IMDGDistributedNames.Map_Company, Company.class); Company company = companyImdg.getSingleObjectByFieldValues(Map.of("tradingCode", sdf01.getDeal())); if (company == null) { - return of(BalanceError.CompanyNotFound); + return of(ClearingError.CompanyNotFound); } context.storeObject(ValidationStored.Company, company); return empty(); @@ -39,13 +39,13 @@ public enum Sdf01ValidationRule implements IValidationRule validate(ImdgValidationContext context) { SDf01 sdf01 = context.getValidatedObject(); if (sdf01.getAccount() == null) { - return of(BalanceError.AccountNotPresent); + return of(ClearingError.AccountNotPresent); } Imdg accountImdg = context.obtainMap(IMDGDistributedNames.Map_Account, Account.class); Account account = accountImdg.getSingleObjectByFieldValues(Map.of("account", sdf01.getAccount(), "accountType", AccountType.Clrn.getKey())); if (account == null) { - return of(BalanceError.AccountNotPresent); + return of(ClearingError.AccountNotPresent); } context.storeObject(ValidationStored.Account, account); return empty(); @@ -56,7 +56,7 @@ public enum Sdf01ValidationRule implements IValidationRule validate(ImdgValidationContext context) { SDf01 sdf01 = context.getValidatedObject(); if (!"RUR".equals(sdf01.getCurr_code())) { - return of(BalanceError.CurrencyNotFound); + return of(ClearingError.CompanyDebitCheck); } return empty(); } @@ -66,16 +66,16 @@ public enum Sdf01ValidationRule implements IValidationRule validate(ImdgValidationContext context) { SDf01 sdf01 = context.getValidatedObject(); if (sdf01.getDat() == null) { - return of(BalanceError.CurrentDateOnly); + return of(ClearingError.IncorrectValue); } LocalDate date; try { date = LocalDate.parse(sdf01.getDat(), datFormatter); } catch (DateTimeParseException e) { - return of(BalanceError.CurrentDateOnly); + return of(ClearingError.IncorrectValue); } if (!LocalDate.now().equals(date)) { - return of(BalanceError.CurrentDateOnly); + return of(ClearingError.IncorrectValue); } return empty(); } @@ -85,7 +85,7 @@ public enum Sdf01ValidationRule implements IValidationRule validate(ImdgValidationContext context) { SDf01 sdf01 = context.getValidatedObject(); if (!"A".equals(sdf01.getAcc_type())) { - return of(BalanceError.WrongAccount); + return of(ClearingError.SecurityNotFound); } return empty(); } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf57ValidationRule.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf57ValidationRule.java new file mode 100644 index 000000000..cbb0a4c86 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf57ValidationRule.java @@ -0,0 +1,80 @@ +package ru.spcex.clearing.service.validation; + +import ru.clearing.classes.statics.data.account.Account; +import ru.clearing.classes.statics.data.company.Company; +import ru.clearing.classes.statics.data.sdf.SDf57; +import ru.spcex.clearing.error.ClearingError; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.validation.ImdgValidationContext; +import ru.spcex.platform.utils.enumeration.EnumMessage; +import ru.spcex.platform.utils.text.TextUtil; +import ru.spcex.platform.utils.validation.IValidationRule; + +import java.util.Optional; + +public enum Sdf57ValidationRule implements IValidationRule> { + CompanyDebOrCredPresent() { + @Override + public Optional validate(ImdgValidationContext context) { + SDf57 sdf57 = context.getValidatedObject(); + Imdg companyImdg = context.obtainMap(IMDGDistributedNames.Map_Company, Company.class); + + Optional companyDebFound = Optional.empty(); + Optional companyCredFound = Optional.empty(); + + if (!TextUtil.isEmpty(sdf57.getDeal_deb())) { + companyDebFound = Optional.ofNullable(companyImdg.getSingleObjectBySQL("tradingCode = '" + sdf57.getDeal_deb() + "'")); + companyDebFound.ifPresent(companyDeb -> context.storeObject(ValidationStored.Sdf57CompanyDeb, companyDeb)); + } + if (!TextUtil.isEmpty(sdf57.getDeal_cred())) { + companyCredFound = Optional.ofNullable(companyImdg.getSingleObjectBySQL("tradingCode = '" + sdf57.getDeal_cred() + "'")); + companyCredFound.ifPresent(companyCred -> context.storeObject(ValidationStored.Sdf57CompanyCred, companyCred)); + } + + if (companyDebFound.isEmpty() && companyCredFound.isEmpty()) { + return of(ClearingError.CompanyNotFound, String.format("dealDeb = '%s'/ dealCred = '%s'", + sdf57.getDeal_deb(), sdf57.getDeal_cred())); + } + return empty(); + } + }, AccountDebOrCredPresent() { + @Override + public Optional validate(ImdgValidationContext context) { + SDf57 sdf57 = context.getValidatedObject(); + Imdg accountImdg = context.obtainMap(IMDGDistributedNames.Map_Account, Account.class); + + Optional accountDebFound = Optional.empty(); + Optional accountCredFound = Optional.empty(); + if (!TextUtil.isEmpty(sdf57.getC_acc_deb())) { + accountDebFound = Optional.ofNullable(accountImdg.getSingleObjectBySQL("account = '" + sdf57.getC_acc_deb() + "'")); + accountDebFound.ifPresent(accountDeb -> context.storeObject(ValidationStored.Sdf57AccountDeb, accountDeb)); + } + + if (!TextUtil.isEmpty(sdf57.getC_acc_cred())) { + accountCredFound = Optional.ofNullable(accountImdg.getSingleObjectBySQL("account = '" + sdf57.getC_acc_cred() + "'")); + accountCredFound.ifPresent(accountCred -> context.storeObject(ValidationStored.Sdf57AccountCred, accountCred)); + } + if (accountDebFound.isEmpty() && accountCredFound.isEmpty()) { + return of(ClearingError.AccountNotPresent, String.format("accDeb = '%s'/ accCred = '%s'", + sdf57.getC_acc_deb(), sdf57.getC_acc_cred())); + } + return empty(); + } + + }, CurrencyCode() { + @Override + public Optional validate(ImdgValidationContext context) { + SDf57 sdf57 = context.getValidatedObject(); + if (!ru.spcex.platform.enumeration.CurrencyCode.RUR.equalsByKey(sdf57.getPay_val())) { + return of(ClearingError.CompanyDebitCheck, sdf57.getPay_val()); + } + return empty(); + } + }; + + @Override + public String ruleName() { + return "Sdf57ValidationRule." + name(); + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java index e1c671c24..861950ecb 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java @@ -1,5 +1,8 @@ package ru.spcex.clearing.service.validation; public enum ValidationStored { - STradesCompany, STradesCounterCompany, STradesSecurity, STradesTradingClearingRegistry + STradesCompany, STradesCounterCompany, STradesSecurity, STradesTradingClearingRegistry, + Account, Company, + + Sdf57CompanyDeb, Sdf57CompanyCred, Sdf57AccountDeb, Sdf57AccountCred } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/AbstractSession.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/AbstractSession.java new file mode 100644 index 000000000..c159463d4 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/AbstractSession.java @@ -0,0 +1,68 @@ +package ru.spcex.clearing.session.stage; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ru.clearing.classes.statics.data.misc.Session; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.utils.enumeration.IMessageResolver; + +import java.util.concurrent.atomic.AtomicReference; + +public class AbstractSession { + private final Logger log = LoggerFactory.getLogger(getClass()); + + protected final Imdg sessionImdg; + protected final IMessageResolver messageResolver; + protected final AtomicReference currStage = new AtomicReference<>(); + protected Session currSession; + + public AbstractSession( + ImdgProvider imdgProvider, + IMessageResolver messageResolver) { + this.sessionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Session, Session.class); + this.messageResolver = messageResolver; + } + + protected StageResult runStage(TaskType type, ISessionStage stage) { + return runStage(type, null, stage); + } + + @SuppressWarnings("unchecked") + protected StageResult runStage(TaskType type, T payload, ISessionStage stage) { + continueRunning(type); + log.info("session.id={} step {} started", currSession.getId(), currStage.get()); + Task t = new Task<>(type, payload); + StageResult stgRes = stage.submit(t); + log.info("session.id={} step {} result: {} ", + currSession.getId(), + currStage.get(), + stgRes.success ? "success" : messageResolver.resolve(stgRes.error)); + if (!stgRes.success) { + endSession(); + throw new StageException(); + } + return (StageResult) stgRes; + } + + protected void endSession() { + synchronized (this.currStage) { + this.currStage.set(null); + this.currSession = null; + } + } + + protected void continueRunning(TaskType t) { + synchronized (this.currStage) { + this.currStage.set(t); + } + } + + protected boolean checkStage(TaskType t) { + synchronized (this.currStage) { + return this.currStage.get().equals(t); + } + } + +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionB0Session.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionB0Session.java new file mode 100644 index 000000000..543bb940e --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionB0Session.java @@ -0,0 +1,165 @@ +package ru.spcex.clearing.session.stage; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.stereotype.Service; +import ru.clearing.classes.statics.data.execution.ExecutionCommon; +import ru.clearing.classes.statics.data.execution.ExecutionFond; +import ru.clearing.classes.statics.data.misc.Session; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.BaseRequest; +import ru.spcex.clearing.session.stage.impl.*; +import ru.spcex.clearing.session.stage.task.*; +import ru.spcex.platform.classes.base.interfaces.ExecutionType; +import ru.spcex.platform.enumeration.MarketType; +import ru.spcex.platform.enumeration.Section; +import ru.spcex.platform.enumeration.SessionStatus; +import ru.spcex.platform.enumeration.SessionType; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; +import ru.spcex.platform.utils.enumeration.IMessageResolver; + +import java.util.List; + +@Service +public class PrimaryAuctionB0Session extends AbstractSession implements InitializingBean { + private final Logger log = LoggerFactory.getLogger(getClass()); + private final BalanceRevise balanceRevise; + private final DealsPrepare dealsPrepare; + private final RequirementsAndObligationCreation requirementsAndObligationCreation; + private final ObligationAdmission obligationsAdmission; + + private final InclusionObligations inclusionObligations; + private final FormingRegistersOnOS formingRegistersOnOS; + private final FormingPaymentInstruction formingPaymentInstruction; + private final UnlockResources unlockResources; + private final FinishingSession finishingSession; + private final EndStageNotification endStageNotification; + + private final Imdg executionFondImdg; + + public PrimaryAuctionB0Session( + ImdgProvider imdgProvider, + BalanceRevise balanceRevise, + DealsPrepare dealsPrepare, + RequirementsAndObligationCreation requirementsAndObligationCreation, + ObligationAdmission obligationsAdmission, + InclusionObligations inclusionObligations, + FormingRegistersOnOS formingRegistersOnOS, + FormingPaymentInstruction formingPaymentInstruction, + UnlockResources unlockResources, + FinishingSession finishingSession, EndStageNotification endStageNotification, IMessageResolver messageResolver) { + super(imdgProvider, messageResolver); + this.balanceRevise = balanceRevise; + this.dealsPrepare = dealsPrepare; + this.requirementsAndObligationCreation = requirementsAndObligationCreation; + this.obligationsAdmission = obligationsAdmission; + this.inclusionObligations = inclusionObligations; + this.formingRegistersOnOS = formingRegistersOnOS; + this.formingPaymentInstruction = formingPaymentInstruction; + this.unlockResources = unlockResources; + this.finishingSession = finishingSession; + this.endStageNotification = endStageNotification; + this.executionFondImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionFond, ExecutionFond.class); + } + + @Override + public void afterPropertiesSet() throws Exception { + dealsPrepare.searchForExecutions(ExecutionType.ExecutionFond); + ImdgPredicateBuilder execFondPb = executionFondImdg.predicateBuilder(); + dealsPrepare.addExecutionFondCondition(execFondPb.regex("settlementCode", "^B0.*$")); + dealsPrepare.addExecutionFondCondition(execFondPb.equals("marketType", MarketType.PRMR.getKey())); + } + + public void runSession(BaseRequest req) { + if (!startSession()) { + return; + } + StageResult submit = balanceRevise.submit(new Task<>(TaskType.StartRevise, null)); + if (!submit.success) { + log.error("stage {} error={}", balanceRevise.getClass().getSimpleName(), messageResolver.resolve(submit.error)); + endSession(); + } else { + log.info("stage BalanceRevise success, waiting for a response from kafka"); + } + } + + public void continueSession(BaseRequest req) { + try { + if (!checkStage(TaskType.StartRevise)) { + log.error("cannot continue session, current stage is {}", currStage.get()); + throw new StageException(); + } + //stage 0 + runStage(TaskType.ContinueRevise, balanceRevise); + //stage 1 + StageResult> dealsPreparationResult; + { + DealsPreparePayload payload = new DealsPreparePayload(); + payload.setSessionId(currSession.getId()); + dealsPreparationResult = runStage(TaskType.DealsPrepare , payload, dealsPrepare); + } + //stage 2 + runStage(TaskType.RequirementsAndObligationsCreate, dealsPreparationResult.getStageResult(), requirementsAndObligationCreation); + //stage 3 + runStage(TaskType.ObligationsAdmission, currSession.getId(), obligationsAdmission); + //stage 4 + { + InclusionToPoolPayload inclusionToPoolPayload = new InclusionToPoolPayload(); + inclusionToPoolPayload.setSessionType(currSession.getSessionType()); + runStage(TaskType.InclusionToPool, inclusionToPoolPayload, inclusionObligations); + } + //stage 5 + { + InspectionPoolPayload companyIdPayload = new InspectionPoolPayload(); + companyIdPayload.setProcessedCompanyId(currSession.getCompanyId()); + runStage(TaskType.InspectionObligations, companyIdPayload, inclusionObligations); + } + //stage 6 + runStage(TaskType.FormingRegistersOnOS, formingRegistersOnOS); //returns Collection + //stage 7 + runStage(TaskType.FormingPaymentInstruction, formingPaymentInstruction); + //stage 8 + { + UnlockResourcesPayload unlockResourcesPayload = new UnlockResourcesPayload(); + //todo set arguments + runStage(TaskType.UnlockResources, unlockResourcesPayload, unlockResources); //returns Collection + } + //stage 9 + { + FinishingSessionPayload payload = new FinishingSessionPayload(); + payload.setSessionId(currSession.getId()); + runStage(TaskType.FinishingSession, payload, finishingSession); + } + { + EndStageNotificationPayload payload = new EndStageNotificationPayload(); + payload.setSection(currSession.getSection()); + runStage(TaskType.EndStageNotification, payload, endStageNotification); + } + } catch (StageException e) { + //already logged + } + } + + private boolean startSession() { + synchronized (this.currStage) { + if (this.currStage.get() != null) { + log.info("already running session.id={}", this.currSession.getId()); + return false; + } else { + Session newSession = new Session(); + newSession.setSection(Section.FOND.getKey()); + newSession.setSessionType(SessionType.IPO0.getKey()); + newSession.setSessionStatus(SessionStatus.CLRN.getKey()); + //todo companyId/securityId/userId передается из сообщения очереди + sessionImdg.insert(newSession); + currSession = newSession; + log.info("started new session.id={}", this.currSession.getId()); + currStage.set(TaskType.StartRevise); + return true; + } + } + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionBnSession.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionBnSession.java index 3d7a35f1d..7beadc73e 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionBnSession.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionBnSession.java @@ -2,25 +2,30 @@ package ru.spcex.clearing.session.stage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.execution.ExecutionCommon; +import ru.clearing.classes.statics.data.execution.ExecutionFond; import ru.clearing.classes.statics.data.misc.Session; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.session.stage.impl.*; import ru.spcex.clearing.session.stage.task.*; +import ru.spcex.platform.classes.base.interfaces.ExecutionType; +import ru.spcex.platform.enumeration.MarketType; import ru.spcex.platform.enumeration.Section; import ru.spcex.platform.enumeration.SessionStatus; import ru.spcex.platform.enumeration.SessionType; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; import ru.spcex.platform.utils.enumeration.IMessageResolver; +import java.time.LocalDate; import java.util.List; -import java.util.concurrent.atomic.AtomicReference; @Service -public class PrimaryAuctionBnSession { +public class PrimaryAuctionBnSession extends AbstractSession implements InitializingBean { private final Logger log = LoggerFactory.getLogger(getClass()); private final BalanceRevise balanceRevise; private final DealsPrepare dealsPrepare; @@ -34,10 +39,7 @@ public class PrimaryAuctionBnSession { private final FinishingSession finishingSession; private final EndStageNotification endStageNotification; - private Imdg sessionImdg; - private final IMessageResolver messageResolver; - private final AtomicReference currStage = new AtomicReference<>(); - private Session currSession; + private final Imdg executionFondImdg; public PrimaryAuctionBnSession( ImdgProvider imdgProvider, @@ -50,6 +52,7 @@ public class PrimaryAuctionBnSession { FormingPaymentInstruction formingPaymentInstruction, UnlockResources unlockResources, FinishingSession finishingSession, EndStageNotification endStageNotification, IMessageResolver messageResolver) { + super(imdgProvider, messageResolver); this.balanceRevise = balanceRevise; this.dealsPrepare = dealsPrepare; this.requirementsAndObligationCreation = requirementsAndObligationCreation; @@ -60,9 +63,15 @@ public class PrimaryAuctionBnSession { this.unlockResources = unlockResources; this.finishingSession = finishingSession; this.endStageNotification = endStageNotification; + this.executionFondImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionFond, ExecutionFond.class); + } - this.sessionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Session, Session.class); - this.messageResolver = messageResolver; + @Override + public void afterPropertiesSet() throws Exception { + dealsPrepare.searchForExecutions(ExecutionType.ExecutionFond); + ImdgPredicateBuilder execFondPb = executionFondImdg.predicateBuilder(); + dealsPrepare.addExecutionFondCondition(execFondPb.regex("settlementCode", "^B[^0]\\d*$")); + dealsPrepare.addExecutionFondCondition(execFondPb.equals("marketType", MarketType.PRMR.getKey())); } public void runSession(BaseRequest req) { @@ -135,27 +144,6 @@ public class PrimaryAuctionBnSession { } } - private StageResult runStage(TaskType type, ISessionStage stage) { - return runStage(type, null, stage); - } - - @SuppressWarnings("unchecked") - private StageResult runStage(TaskType type, T payload, ISessionStage stage) { - continueRunning(type); - log.info("session.id={} step {} started", currSession.getId(), currStage.get()); - Task t = new Task<>(type, payload); - StageResult stgRes = stage.submit(t); - log.info("session.id={} step {} result: {} ", - currSession.getId(), - currStage.get(), - stgRes.success ? "success" : messageResolver.resolve(stgRes.error)); - if (!stgRes.success) { - endSession(); - throw new StageException(); - } - return (StageResult) stgRes; - } - private boolean startSession() { synchronized (this.currStage) { if (this.currStage.get() != null) { @@ -166,6 +154,8 @@ public class PrimaryAuctionBnSession { newSession.setSection(Section.FOND.getKey()); newSession.setSessionType(SessionType.IPOB.getKey()); newSession.setSessionStatus(SessionStatus.CLRN.getKey()); + newSession.setClearingDate(LocalDate.now()); + //todo companyId/securityId/userId передается из сообщения очереди sessionImdg.insert(newSession); currSession = newSession; @@ -175,26 +165,4 @@ public class PrimaryAuctionBnSession { } } } - - private void endSession() { - synchronized (this.currStage) { - this.currStage.set(null); - this.currSession = null; - } - } - - private void continueRunning(TaskType t) { - synchronized (this.currStage) { - this.currStage.set(t); - } - } - - private boolean checkStage(TaskType t) { - synchronized (this.currStage) { - return this.currStage.get().equals(t); - } - } - - private static class StageException extends RuntimeException { - } } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/StageException.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/StageException.java new file mode 100644 index 000000000..0f79a5c86 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/StageException.java @@ -0,0 +1,4 @@ +package ru.spcex.clearing.session.stage; + +class StageException extends RuntimeException { +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/DealsPrepare.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/DealsPrepare.java index d0613654c..62f726a24 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/DealsPrepare.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/DealsPrepare.java @@ -3,6 +3,8 @@ package ru.spcex.clearing.session.stage.impl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.execution.ExecutionCommon; import ru.clearing.classes.statics.data.execution.ExecutionDeposit; @@ -12,27 +14,27 @@ import ru.spcex.clearing.session.stage.ISessionStage; import ru.spcex.clearing.session.stage.StageResult; import ru.spcex.clearing.session.stage.Task; import ru.spcex.clearing.session.stage.task.DealsPreparePayload; -import ru.spcex.platform.classes.base.interfaces.WithExchangeExecutionId; +import ru.spcex.platform.classes.base.interfaces.ExecutionType; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; import java.util.List; import java.util.function.BiFunction; import java.util.function.Function; -import java.util.stream.Stream; +import java.util.stream.Collectors; @Service +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class DealsPrepare implements ISessionStage { private final Logger log = LoggerFactory.getLogger(getClass()); private final Imdg executionDepositImdg; private final Imdg executionFondImdg; private final List execDepositPredicates = new ArrayList<>(); private final List execFondPredicates = new ArrayList<>(); + private ExecutionType executionType = ExecutionType.ExecutionFond; @Autowired public DealsPrepare(ImdgProvider imdgProvider) { @@ -40,6 +42,10 @@ public class DealsPrepare implements ISessionStage { this.executionFondImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionFond, ExecutionFond.class); } + public void searchForExecutions(ExecutionType executionType) { + this.executionType = executionType; + } + @Override public StageResult submit(Task task) { DealsPreparePayload payload = (DealsPreparePayload) task.getData(); @@ -67,17 +73,27 @@ public class DealsPrepare implements ISessionStage { if (imdgPredicates.isEmpty()) { return sqlPredicate; } else { - return pb.and(sqlPredicate, pb.and(execDepositPredicates.toArray(new ImdgPredicate[0]))); + return pb.and(sqlPredicate, pb.and(imdgPredicates.toArray(new ImdgPredicate[0]))); } }; - ImdgPredicate excDepPrct = prdComposer.apply(execDepositPredicates, executionDepositImdg); - ImdgPredicate excFondPrct = prdComposer.apply(execFondPredicates, executionFondImdg); - Collection excDpsts = executionDepositImdg.getCollectionObjectsByPredicate(excDepPrct); - Collection excFonds = executionFondImdg.getCollectionObjectsByPredicate(excFondPrct); - List excs = Stream.concat(excDpsts.stream().map(execToInterface()), - excFonds.stream().map(execToInterface())) - .sorted(Comparator.comparing(WithExchangeExecutionId::getExchangeExecutionId)) - .toList(); + List excs; + switch (executionType) { + case ExecutionDeposit -> { + ImdgPredicate excDepPrct = prdComposer.apply(execDepositPredicates, executionDepositImdg); + excs = executionDepositImdg.getCollectionObjectsByPredicate(excDepPrct) + .stream() + .map(execToInterface()) + .collect(Collectors.toList()); + } + case ExecutionFond -> { + ImdgPredicate excFondPrct = prdComposer.apply(execFondPredicates, executionFondImdg); + excs = executionFondImdg.getCollectionObjectsByPredicate(excFondPrct) + .stream() + .map(execToInterface()) + .collect(Collectors.toList()); + } + default -> throw new IllegalStateException("Unknown execution type: " + executionType); + } for (ExecutionCommon exc : excs) { exc.setSessionId(sessionId); if (exc instanceof ExecutionDeposit) { diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/EndStageNotification.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/EndStageNotification.java index ad6481639..89bf8da24 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/EndStageNotification.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/EndStageNotification.java @@ -3,6 +3,8 @@ package ru.spcex.clearing.session.stage.impl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.registry.Registry; import ru.spcex.clearing.imdg.IMDGDistributedNames; @@ -13,7 +15,8 @@ import ru.spcex.clearing.session.stage.ISessionStage; import ru.spcex.clearing.session.stage.StageResult; import ru.spcex.clearing.session.stage.Task; import ru.spcex.clearing.session.stage.task.EndStageNotificationPayload; -import ru.spcex.platform.enumeration.*; +import ru.spcex.platform.enumeration.RegistryStatus; +import ru.spcex.platform.enumeration.Section; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.utils.enumeration.EnumMessage; @@ -26,6 +29,7 @@ import java.util.stream.Collectors; import static ru.spcex.clearing.error.ClearingErrorInternal.SessionGeneralError; @Service +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class EndStageNotification implements ISessionStage { private final Logger log = LoggerFactory.getLogger(getClass()); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FinishingSession.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FinishingSession.java index 051a05eca..f40635de5 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FinishingSession.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FinishingSession.java @@ -3,6 +3,8 @@ package ru.spcex.clearing.session.stage.impl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.misc.Session; import ru.clearing.classes.statics.data.registry.Registry; @@ -32,6 +34,7 @@ import java.util.Collection; import static ru.spcex.clearing.error.ClearingErrorInternal.SessionGeneralError; @Service +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class FinishingSession implements ISessionStage { private final Logger log = LoggerFactory.getLogger(getClass()); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstruction.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstruction.java index 3c99589e9..a9d203374 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstruction.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstruction.java @@ -3,6 +3,8 @@ package ru.spcex.clearing.session.stage.impl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.payment.PaymentInstruction; import ru.clearing.classes.statics.data.registry.Registry; @@ -25,6 +27,7 @@ import java.util.Collection; import java.util.List; @Service +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class FormingPaymentInstruction implements ISessionStage { private final Logger log = LoggerFactory.getLogger(getClass()); //todo remove (set all in single method setImdg(provider -> setImdg1();setIdGenerator();...) diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingRegistersOnOS.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingRegistersOnOS.java index 54b16f861..1329f7232 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingRegistersOnOS.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingRegistersOnOS.java @@ -3,6 +3,8 @@ package ru.spcex.clearing.session.stage.impl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.registry.Registry; import ru.spcex.clearing.imdg.IMDGDistributedNames; @@ -24,6 +26,7 @@ import java.util.ArrayList; import java.util.Collection; @Service +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class FormingRegistersOnOS implements ISessionStage { private final Logger log = LoggerFactory.getLogger(getClass()); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InclusionObligations.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InclusionObligations.java index b3aae427f..01e0f7d6c 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InclusionObligations.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InclusionObligations.java @@ -3,6 +3,8 @@ package ru.spcex.clearing.session.stage.impl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.registry.Registry; import ru.spcex.clearing.imdg.IMDGDistributedNames; @@ -23,6 +25,7 @@ import java.util.stream.Collectors; @Service +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class InclusionObligations implements ISessionStage { private final Logger log = LoggerFactory.getLogger(getClass()); //todo remove (set all in single method setImdg(provider -> setImdg1();setIdGenerator();...) diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/ObligationAdmission.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/ObligationAdmission.java index f62cdd211..b82b092a0 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/ObligationAdmission.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/ObligationAdmission.java @@ -4,6 +4,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.registry.Registry; import ru.spcex.clearing.imdg.IMDGDistributedNames; @@ -26,6 +28,7 @@ import java.util.function.Function; import java.util.stream.Collectors; @Service +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class ObligationAdmission implements ISessionStage { private final Logger log = LoggerFactory.getLogger(getClass()); private final Imdg registryImdg; diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/RequirementsAndObligationCreation.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/RequirementsAndObligationCreation.java index 150456493..f1c09034d 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/RequirementsAndObligationCreation.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/RequirementsAndObligationCreation.java @@ -3,6 +3,8 @@ package ru.spcex.clearing.session.stage.impl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.execution.ExecutionCommon; import ru.clearing.classes.statics.data.execution.ExecutionDeposit; @@ -31,6 +33,7 @@ import java.util.function.BiConsumer; import java.util.function.BiFunction; @Service +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class RequirementsAndObligationCreation implements ISessionStage { private final Logger log = LoggerFactory.getLogger(getClass()); private final Imdg registryImdg; diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/UnlockResources.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/UnlockResources.java index 91c0a60f2..c9771965d 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/UnlockResources.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/UnlockResources.java @@ -3,6 +3,8 @@ package ru.spcex.clearing.session.stage.impl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.registry.Registry; import ru.spcex.clearing.imdg.IMDGDistributedNames; @@ -24,6 +26,7 @@ import java.time.Instant; import java.util.Collection; @Service +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class UnlockResources implements ISessionStage { private final Logger log = LoggerFactory.getLogger(getClass()); diff --git a/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/StatementServiceServiceTest.java b/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/StatementServiceServiceTest.java new file mode 100644 index 000000000..bd7655f7c --- /dev/null +++ b/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/StatementServiceServiceTest.java @@ -0,0 +1,111 @@ +package ru.spcex.clearing.service; + +//todo раскоментить тест +class StatementServiceServiceTest { +// extends AbstractServiceTest { +// private static final String TOPIC = Consts.STATEMENT_PROCESS; +// private static final int PARTITION = 1; +// private static final Long groupId = 111L; +// private final static AtomicLong cuurentOffset = new AtomicLong(1L); +// private final Long ID = 11L; +// @Autowired +// StatementService statementService; +// @Captor +// ArgumentCaptor producerRecord; +// private MockConsumer mockConsumer; +// private SDf01 sDf01; +// private Company company; +// @SpyBean +// private MockProducer producer; +// +// @PostConstruct +// void init() { +// super.init(); +// mockConsumer = (MockConsumer) statementService.getConsumer(); +// sDf01 = getTestSdf01(ID, groupId); +// company = getTestCompany(); +// } +// +// /** +// * {@link StatementService}
+// * Тест проверяет генерацию сущностей {@link RequestInfo}
+// * Входные параметры:
+// * {@link StatementRequest}: new StatementRequest()
+// * {@link StatementRequest#table} - SDF_01
+// */ +// @Test +// void processEXPORT_PROCESS() { +// sdf01Imdg.delete(sDf01); +// companyImdg.delete(company); +// +// companyImdg.delete(company); +// StatementRequest statementRequest = new StatementRequest(); +// statementRequest.setGroupId(groupId); +// statementRequest.setTable(SDF_01); +// BaseRequest baseNewRequest = new BaseRequest<>(); +// baseNewRequest.setRequestPayload(statementRequest); +// baseNewRequest.setId(currentId.getAndIncrement()); +// baseNewRequest.setActionType(ActionType.NEW); +// String jsonBaseNewRequest; +// ObjectMapper objectMapper = new ObjectMapper(); +// try { +// jsonBaseNewRequest = objectMapper.writeValueAsString(baseNewRequest); +// } catch (JsonProcessingException e) { +// throw new RuntimeException(e); +// } +// +// addRecordToKafka(mockConsumer, TOPIC, PARTITION, cuurentOffset.getAndIncrement(), jsonBaseNewRequest); +// +// //waiting for kafka producer send message (finale event) +// verify(producer, timeout(30_000L).times(1)) +// .send(producerRecord.capture()); +// +// BaseRequest baseRequest = (BaseRequest) producerRecord.getValue().value(); +// RequestInfo resultRequestInfo = requestInfoImdg.getSingleObjectByID(baseRequest.getId()); +// +// assertEquals(Consts.EXPORT_PROCESS, producerRecord.getValue().topic()); +// assertNotNull(baseRequest); +// assertNotNull(resultRequestInfo); +// } +// +// /** +// * {@link StatementService}
+// * Тест проверяет генерацию сущностей {@link RequestInfo}
+// * Входные параметры:
+// * {@link StatementRequest}: new StatementRequest()
+// * {@link StatementRequest#table} - SDF_01
+// */ +// @Test +// void processACCOUNT_NEW() { +// sdf01Imdg.insert(sDf01); +// companyImdg.insert(company); +// +// StatementRequest statementRequest = new StatementRequest(); +// statementRequest.setGroupId(groupId); +// statementRequest.setTable(SDF_01); +// BaseRequest baseNewRequest = new BaseRequest<>(); +// baseNewRequest.setRequestPayload(statementRequest); +// baseNewRequest.setId(currentId.getAndIncrement()); +// baseNewRequest.setActionType(ActionType.NEW); +// String jsonBaseNewRequest; +// ObjectMapper objectMapper = new ObjectMapper(); +// try { +// jsonBaseNewRequest = objectMapper.writeValueAsString(baseNewRequest); +// } catch (JsonProcessingException e) { +// throw new RuntimeException(e); +// } +// +// addRecordToKafka(mockConsumer, TOPIC, PARTITION, cuurentOffset.getAndIncrement(), jsonBaseNewRequest); +// +// //waiting for kafka producer send message (finale event) +// verify(producer, timeout(30_000L).times(1)) +// .send(producerRecord.capture()); +// +// BaseRequest baseRequest = (BaseRequest) producerRecord.getValue().value(); +// RequestInfo resultRequestInfo = requestInfoImdg.getSingleObjectByID(baseRequest.getId()); +// +// assertEquals(Consts.ACCOUNT_NEW_SDF01, producerRecord.getValue().topic()); +// assertNotNull(baseRequest); +// assertNotNull(resultRequestInfo); +// } +} \ No newline at end of file diff --git a/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/builder/sql/RegistryCodeSqlBuilderTest.java b/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/builder/sql/RegistryCodeSqlBuilderTest.java index ca1c7b68c..c1ffcec83 100644 --- a/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/builder/sql/RegistryCodeSqlBuilderTest.java +++ b/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/builder/sql/RegistryCodeSqlBuilderTest.java @@ -1,54 +1,47 @@ package ru.spcex.clearing.service.builder.sql; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import ru.spcex.clearing.models.RegistryTradingParams; -import ru.spcex.platform.enumeration.RegistryCapacity; -import ru.spcex.platform.enumeration.RegistryDesignation; -import ru.spcex.platform.enumeration.RegistryInstrumentType; -import ru.spcex.platform.enumeration.RegistryUnit; - public class RegistryCodeSqlBuilderTest { +//todo раскоментить тесты - @Test - public void testBuildByOneObject() { - RegistryTradingParams registryTradingParams = new RegistryTradingParams(RegistryDesignation.C, RegistryInstrumentType.M, RegistryCapacity.B, RegistryUnit.R); - RegistryCodeSqlBuilder registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams); - String sql = registryCodeSqlBuilder.build(); - Assertions.assertEquals("(registryDesignation = 'C' and registryInstrumentType = 'M' and registryCapacity = 'B' and registryUnit = 'R')", sql); - - registryTradingParams = new RegistryTradingParams(null, RegistryInstrumentType.M, RegistryCapacity.B, RegistryUnit.R); - registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams); - sql = registryCodeSqlBuilder.build(); - Assertions.assertEquals("(registryInstrumentType = 'M' and registryCapacity = 'B' and registryUnit = 'R')", sql); - - registryTradingParams = new RegistryTradingParams(RegistryDesignation.C, null, null, RegistryUnit.R); - registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams); - sql = registryCodeSqlBuilder.build(); - Assertions.assertEquals("(registryDesignation = 'C' and registryUnit = 'R')", sql); - } - - @Test - public void testBuildByFewObjects() { - RegistryTradingParams registryTradingParams_first = new RegistryTradingParams(RegistryDesignation.C, RegistryInstrumentType.M, RegistryCapacity.B, RegistryUnit.R); - RegistryTradingParams registryTradingParams_second = new RegistryTradingParams(RegistryDesignation.O, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.F); - RegistryCodeSqlBuilder registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams_first, registryTradingParams_second); - String sql = registryCodeSqlBuilder.build(); - Assertions.assertEquals("(registryDesignation = 'C' and registryInstrumentType = 'M' and registryCapacity = 'B' and registryUnit = 'R')" + - " or (registryDesignation = 'O' and registryInstrumentType = 'S' and registryCapacity = 'A' and registryUnit = 'F')", sql); - - registryTradingParams_first = new RegistryTradingParams(null, RegistryInstrumentType.M, RegistryCapacity.B, RegistryUnit.R); - registryTradingParams_second = new RegistryTradingParams(null, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.F); - registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams_first, registryTradingParams_second); - sql = registryCodeSqlBuilder.build(); - Assertions.assertEquals("(registryInstrumentType = 'M' and registryCapacity = 'B' and registryUnit = 'R') or " + - "(registryInstrumentType = 'S' and registryCapacity = 'A' and registryUnit = 'F')", sql); - - registryTradingParams_first = new RegistryTradingParams(RegistryDesignation.C, null, null, RegistryUnit.R); - registryTradingParams_second = new RegistryTradingParams(null, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.F); - registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams_first, registryTradingParams_second); - sql = registryCodeSqlBuilder.build(); - Assertions.assertEquals("(registryDesignation = 'C' and registryUnit = 'R') or " + - "(registryInstrumentType = 'S' and registryCapacity = 'A' and registryUnit = 'F')", sql); - } +// @Test +// public void testBuildByOneObject() { +// RegistryTradingParams registryTradingParams = new RegistryTradingParams(RegistryDesignation.C, RegistryInstrumentType.M, RegistryCapacity.B, RegistryUnit.R); +// RegistryCodeSqlBuilder registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams); +// String sql = registryCodeSqlBuilder.build(); +// Assertions.assertEquals("(registryDesignation = 'C' and registryInstrumentType = 'M' and registryCapacity = 'B' and registryUnit = 'R')", sql); +// +// registryTradingParams = new RegistryTradingParams(null, RegistryInstrumentType.M, RegistryCapacity.B, RegistryUnit.R); +// registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams); +// sql = registryCodeSqlBuilder.build(); +// Assertions.assertEquals("(registryInstrumentType = 'M' and registryCapacity = 'B' and registryUnit = 'R')", sql); +// +// registryTradingParams = new RegistryTradingParams(RegistryDesignation.C, null, null, RegistryUnit.R); +// registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams); +// sql = registryCodeSqlBuilder.build(); +// Assertions.assertEquals("(registryDesignation = 'C' and registryUnit = 'R')", sql); +// } +// +// @Test +// public void testBuildByFewObjects() { +// RegistryTradingParams registryTradingParams_first = new RegistryTradingParams(RegistryDesignation.C, RegistryInstrumentType.M, RegistryCapacity.B, RegistryUnit.R); +// RegistryTradingParams registryTradingParams_second = new RegistryTradingParams(RegistryDesignation.O, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.F); +// RegistryCodeSqlBuilder registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams_first, registryTradingParams_second); +// String sql = registryCodeSqlBuilder.build(); +// Assertions.assertEquals("(registryDesignation = 'C' and registryInstrumentType = 'M' and registryCapacity = 'B' and registryUnit = 'R')" + +// " or (registryDesignation = 'O' and registryInstrumentType = 'S' and registryCapacity = 'A' and registryUnit = 'F')", sql); +// +// registryTradingParams_first = new RegistryTradingParams(null, RegistryInstrumentType.M, RegistryCapacity.B, RegistryUnit.R); +// registryTradingParams_second = new RegistryTradingParams(null, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.F); +// registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams_first, registryTradingParams_second); +// sql = registryCodeSqlBuilder.build(); +// Assertions.assertEquals("(registryInstrumentType = 'M' and registryCapacity = 'B' and registryUnit = 'R') or " + +// "(registryInstrumentType = 'S' and registryCapacity = 'A' and registryUnit = 'F')", sql); +// +// registryTradingParams_first = new RegistryTradingParams(RegistryDesignation.C, null, null, RegistryUnit.R); +// registryTradingParams_second = new RegistryTradingParams(null, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.F); +// registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(registryTradingParams_first, registryTradingParams_second); +// sql = registryCodeSqlBuilder.build(); +// Assertions.assertEquals("(registryDesignation = 'C' and registryUnit = 'R') or " + +// "(registryInstrumentType = 'S' and registryCapacity = 'A' and registryUnit = 'F')", sql); +// } } diff --git a/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/executors/Sdf01ExecutorTest.java b/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/executors/Sdf01ExecutorTest.java new file mode 100644 index 000000000..0b358ae18 --- /dev/null +++ b/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/executors/Sdf01ExecutorTest.java @@ -0,0 +1,238 @@ +package ru.spcex.clearing.service.executors; + +//todo раскоментить тест +// +class Sdf01ExecutorTest { +// extends AbstractServiceTest { +// public final static DateTimeFormatter datFormatter = DateTimeFormatter.ofPattern("dd.MM.yy"); +// public final static String acc = "123456789"; +// private static final MatcherFactory.Matcher SDF_02_MATCHER = usingIgnoringFieldsComparator("created", "comment", "outSDfId", "generationTime", "generationId", "id"); +// private final Long ID = 1L; +// @Autowired +// Sdf01Executor sdf01Executor; +// private StatementRequest statementRequest; +// @SpyBean +// private MockProducer producer; +// +// @PostConstruct +// void init() { +// super.init(); +// statementRequest = new StatementRequest(); +// } +// +// /** +// * {@link Sdf01Executor#execute(Collection collection, StatementRequest statementRequest)}
+// * Тест проверяет генерацию сущностей {@link Result}, {@link Statement}, {@link SDf02}
+// * Входные параметры:
+// * accountId - {@link StatementRequest}: new StatementRequest()
+// * addresseeId - {@link Collection}
+// * addresseeId - {@link SDf01}
+// * {@link SDf01#market} - "U"
+// * {@link SDf01#deal} - "111111111"
+// * {@link SDf01#account} - "123456789"
+// * {@link SDf01#curr_code} - "RUR"
+// * {@link SDf01#dat} - текущая дата
+// * {@link SDf01#acc_type} - "A"
+// * {@link SDf01#remainder} - "1000"
+// */ +// @Test +// void execute() { +// //check create statement, SDf02 and AccountBalance +// SDf01 sdf01 = getTestSdf01(ID, 1L); +// Company company = getTestCompany(); +// companyMap.put(addresseeIdNew, company); +// +// Account account = getTestAccount(ID, acc); +// accountMap.put(accountIdNew, account); +// +// Result predictableResult = new Result(); +// predictableResult.setGenerationId(ID); +// Statement predictableStatement = getTestStatement(currentId.getAndIncrement(), company, account, sdf01); +// predictableStatement.setOperationStatus(OperationStatus.Executed.getKey()); +// SDf02 predictableSdf02 = getTestSdf02(currentId.getAndIncrement(), sdf01, ID); +// predictableStatement.setOutSDfId(predictableSdf02.getId()); +// AccountResult predictableNewResult = getTestAccountResult(currentId.getAndIncrement(), account, company); +// +// Result result = sdf01Executor.execute(Collections.singletonList(sdf01), statementRequest); +// Statement resultStatement = statementImdg.getSingleObjectByFieldValues(Map.of("account", acc)); +// SDf02 resultSdf02 = sdf02Imdg.getSingleObjectByFieldValues(Map.of("account", acc)); +// AccountBalance resultAccountBalance = accountBalanceImdg.getSingleObjectByFieldValues(Map.of("account", acc)); +// +// RESULT_MATCHER.assertMatch(result, predictableResult); +// STATEMENT_MATCHER.assertMatch(resultStatement, predictableStatement); +// SDF_02_MATCHER.assertMatch(resultSdf02, predictableSdf02); +// ACCOUNT_BALANCE_MATCHER.assertMatch(resultAccountBalance, predictableNewResult.getAccount()); +// } +// +// /** +// * {@link Sdf01Executor#execute(Collection collection, StatementRequest statementRequest)}
+// * Тест проверяет валидацию
+// * Входные параметры:
+// * accountId - {@link StatementRequest}: new StatementRequest()
+// * addresseeId - {@link Collection}
+// * addresseeId - {@link SDf01}
+// * {@link SDf01#market} - "U"
+// * {@link SDf01#deal} - "111111111"
+// * {@link SDf01#account} - "123456789"
+// * {@link SDf01#curr_code} - "RUR"
+// * {@link SDf01#dat} - текущая дата
+// * {@link SDf01#acc_type} - "A"
+// * {@link SDf01#remainder} - "1000"
+// */ +// @Test +// void validatedExecute() { +// //CompanyNotFound +// SDf01 sdf01 = getTestSdf01(ID, 1L); +// companyMap.delete(addresseeIdNew); +// checkError(new EnumMessage(BalanceError.CompanyNotFound), sdf01); +// +// sdf01.setDeal(null); +// checkError(new EnumMessage(BalanceError.CompanyNotFound), sdf01); +// +// //AccountNotPresent accountType=null +// sdf01.setDeal(deal); +// Company company = getTestCompany(); +// companyMap.put(addresseeIdNew, company); +// Account account = new Account(); +// account.setAccount(acc); +// account.setStatus(Status.Active.getKey()); +// accountMap.put(accountIdNew, account); +// checkErrorAccountNotPresent(company, sdf01); +// +// //AccountNotPresent account=null +// account.setAccount(null); +// account.setAccountType(AccountType.Clrn.getKey()); +// account.setStatus(Status.Active.getKey()); +// accountMap.put(accountIdNew, account); +// checkErrorAccountNotPresent(company, sdf01); +// +// //AccountNotPresent sdf01.account==null +// sdf01.setAccount(null); +// checkErrorAccountNotPresent(company, sdf01); +// +// //CurrencyNotFound sdf01.curr_code =! "RUR" +// accountMap.put(accountIdNew, getTestAccount(ID, acc)); +// sdf01.setAccount(acc); +// sdf01.setCurr_code("RUB"); +// checkError(new EnumMessage(BalanceError.CurrencyNotFound), sdf01); +// +// //CurrencyNotFound sdf01.curr_code =! "RUR" +// sdf01.setCurr_code(null); +// checkError(new EnumMessage(BalanceError.CurrencyNotFound), sdf01); +// +// //CurrentDateOnly +// sdf01.setCurr_code("RUR"); +// sdf01.setDat("19.01.23"); +// checkError(new EnumMessage(BalanceError.CurrentDateOnly), sdf01); +// +// //CurrentDateOnly +// sdf01.setDat("19.01.2023"); +// checkError(new EnumMessage(BalanceError.CurrentDateOnly), sdf01); +// +// //CurrentDateOnly +// sdf01.setDat(null); +// checkError(new EnumMessage(BalanceError.CurrentDateOnly), sdf01); +// +// //WrongAccount +// sdf01.setDat(LocalDate.now().format(datFormatter)); +// sdf01.setAcc_type(null); +// checkError(new EnumMessage(BalanceError.WrongAccount), sdf01); +// +// //WrongMarket +// sdf01.setAcc_type("A"); +// sdf01.setMarket(null); +// checkError(new EnumMessage(BalanceError.WrongMarket), sdf01); +// +// sdf01.setMarket("U"); +// } +// +// private void checkError(EnumMessage enumMessage, SDf01 sdf01) { +//// SDf01 sdf01 = getTestSdf01(); +// SDf02 predictableSdf02 = getTestErrorSdf02(sdf01, enumMessage, ID); +// Result result = sdf01Executor.execute(Collections.singletonList(sdf01), statementRequest); +// Collection resultsSdf02 = sdf02Imdg.getCollectionObjectsByFieldValues(Map.of("account", acc)); +// SDf02 resultSdf02 = resultsSdf02.stream().max((entry1, entry2) -> entry1.getId() > entry2.getId() ? 1 : -1).get(); +// SDF_02_MATCHER.assertMatch(resultSdf02, predictableSdf02); +// } +// +// private void checkErrorAccountNotPresent(Company company, SDf01 sdf01) { +// Result predictableResult = new Result(); +// predictableResult.getAccountRequests().add(createAccountRequestPart(sdf01.getId(), sdf01.getAccount(), company.getId())); +// Result result = sdf01Executor.execute(Collections.singletonList(sdf01), statementRequest); +// RESULT_MATCHER.assertMatch(result, predictableResult); +// +// } +// +// private SDf02 getTestSdf02(Long id, SDf01 sdf01, Long generationIdForGroup) { +// SDf02 sDf02 = new SDf02(); +// sDf02.setId(id); +// sDf02.setCurr_code(sdf01.getCurr_code()); +// sDf02.setAccount(sdf01.getAccount()); +// sDf02.setRemainder(sdf01.getRemainder()); +// sDf02.setDeal(sdf01.getDeal()); +// sDf02.setAcc_code(sdf01.getAcc_code()); +// sDf02.setDat(sdf01.getDat()); +// sDf02.setMarket(sdf01.getMarket()); +// sDf02.setAcc_name(sdf01.getAcc_name()); +// sDf02.setAcc_type(sdf01.getAcc_type()); +// sDf02.setSumengage(sdf01.getSumengage()); +// sDf02.setSumunblock(sdf01.getSumunblock()); +// sDf02.setFile_type(sdf01.getFile_type()); +// sDf02.setInSDfId(sdf01.getId()); +// sDf02.setGenerationId(generationIdForGroup); +// sDf02.setGenerationTime(Instant.now()); +// sDf02.setResult("OK!"); +// return sDf02; +// } +// +// private Statement getTestStatement(Long id, Company company, Account account, SDf01 sdf01) { +// Statement statement = new Statement(); +// statement.setId(id); +// statement.setAddresseeId(company.getId()); +// statement.setSenderId(Sender.Prc.getId()); +// statement.setCreated(Instant.now()); +// statement.setClearingDate(LocalDate.now()); +// statement.setStatementType(StatementType.full.getKey()); +// statement.setAccountId(account.getId()); +// statement.setAccount(sdf01.getAccount()); +// statement.setInOutDirection(InOutDirection.in.getKey()); +// statement.setSettlementDate(LocalDate.parse(sdf01.getDat(), datFormatter)); +// statement.setAmount(BigDecimalUtil.parse(sdf01.getRemainder())); +// statement.setOperationStatus(OperationStatus.Pending.getKey()); +// statement.setInSDfId(sdf01.getId()); +// statement.setInOutSDfType(InOutSDfType.type1.getKey()); +// return statement; +// } +// +// private SDf02 getTestErrorSdf02(SDf01 sdf01, EnumMessage error, Long generationIdForGroup) { +// SDf02 sDf02 = new SDf02(); +// sDf02.setId(ID); +// sDf02.setCurr_code(sdf01.getCurr_code()); +// sDf02.setAccount(sdf01.getAccount()); +// sDf02.setRemainder(sdf01.getRemainder()); +// sDf02.setDeal(sdf01.getDeal()); +// sDf02.setAcc_code(sdf01.getAcc_code()); +// sDf02.setDat(sdf01.getDat()); +// sDf02.setMarket(sdf01.getMarket()); +// sDf02.setAcc_name(sdf01.getAcc_name()); +// sDf02.setAcc_type(sdf01.getAcc_type()); +// sDf02.setSumengage(sdf01.getSumengage()); +// sDf02.setSumunblock(sdf01.getSumunblock()); +// sDf02.setFile_type(sdf01.getFile_type()); +// sDf02.setInSDfId(sdf01.getId()); +// String errorId = error.getSubject().getId().toString(); +// sDf02.setResult(errorId.substring(errorId.length() - 3)); +// sDf02.setGenerationId(generationIdForGroup); +// sDf02.setGenerationTime(Instant.now()); +// return sDf02; +// } +// +// private AccountSdfRequestPart createAccountRequestPart(Long sdf01Id, String account, Long companyId) { +// AccountSdfRequestPart req = new AccountSdfRequestPart(); +// req.setAccount(account); +// req.setCompanyId(companyId); +// req.setAccountType(AccountType.Clrn.getKey()); +// req.setSdfId(sdf01Id); +// return req; +// } +} \ No newline at end of file diff --git a/clearing-parent/clearing-validation/src/main/java/ru/spcex/clearing/util/services/IMDGMessageResolver.java b/clearing-parent/clearing-validation/src/main/java/ru/spcex/clearing/util/services/IMDGMessageResolver.java index 3d64121d6..0149ece9f 100644 --- a/clearing-parent/clearing-validation/src/main/java/ru/spcex/clearing/util/services/IMDGMessageResolver.java +++ b/clearing-parent/clearing-validation/src/main/java/ru/spcex/clearing/util/services/IMDGMessageResolver.java @@ -1,6 +1,5 @@ package ru.spcex.clearing.util.services; -import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ru.clearing.platform.dictionary.ErrorCodeDictionary; @@ -11,6 +10,7 @@ import ru.spcex.platform.utils.enumeration.EnumMessage; import ru.spcex.platform.utils.enumeration.IMessageResolver; import java.util.Arrays; +import java.util.function.Supplier; /** * Использует ErrorCodeDictionary для расшифровки текста кодов ошибок. @@ -24,19 +24,20 @@ public class IMDGMessageResolver implements IMessageResolver { } @Override - public String resolve(EnumMessage errorMessage) { - if (errorMessage == null) return "null"; + public String resolve(EnumMessage errMsg) { + if (errMsg == null) return "null"; + Supplier simplFormatter = () -> String.format("(%d) args %s", errMsg.getSubject().getId(), Arrays.toString(errMsg.getArgs())); try { - ErrorCodeDictionary errorDictionary = errorCodeDictionaryIMDG.getSingleObjectByID(errorMessage.getSubject().getId()); + ErrorCodeDictionary errorDictionary = errorCodeDictionaryIMDG.getSingleObjectByID(errMsg.getSubject().getId()); if (errorDictionary == null) { - log.warn("ERROR_CODE_DICTIONARY not found fo id={}", errorMessage.getSubject().getId()); - return String.format("(%d) args %s", errorMessage.getSubject().getId(), Arrays.toString(errorMessage.getArgs())); + log.warn("ERROR_CODE_DICTIONARY not found fo id={}", errMsg.getSubject().getId()); + return simplFormatter.get(); } String textTemplate = errorDictionary.getName(); - return String.format(textTemplate, errorMessage.getArgs()); + return String.format(textTemplate, errMsg.getArgs()); } catch (Exception errFormatting) { // MissingFormatArgumentException - log.warn("Error in message resolver for error {}: {}", errorMessage.getSubject(), ExceptionUtils.getStackTrace(errFormatting)); - return String.format("(%d) args %s", errorMessage.getSubject().getId(), Arrays.toString(errorMessage.getArgs())); + log.warn("Error in message resolver for error {} id {}", errMsg.getSubject(), errMsg.getSubject().getId()); + return simplFormatter.get(); } } } diff --git a/clearing-parent/clearing-validation/src/main/java/ru/spcex/clearing/util/services/exchangers/BiDirectionQueueExchanger.java b/clearing-parent/clearing-validation/src/main/java/ru/spcex/clearing/util/services/exchangers/BiDirectionQueueExchanger.java index 0d8ec8a1d..eaec45cc3 100644 --- a/clearing-parent/clearing-validation/src/main/java/ru/spcex/clearing/util/services/exchangers/BiDirectionQueueExchanger.java +++ b/clearing-parent/clearing-validation/src/main/java/ru/spcex/clearing/util/services/exchangers/BiDirectionQueueExchanger.java @@ -27,6 +27,8 @@ import java.util.concurrent.Future; *

* Ожидает из очереди (CommonIdRequest) * + * Похожая функция ожидания: KafkaSender.sendToQueueWaitForAnswer + * * @param отправляется в очередь */ public class BiDirectionQueueExchanger> extends QueueConsumer implements Closeable { diff --git a/clearing-parent/clearing-validation/src/main/java/ru/spcex/clearing/validation/common/rules/EndDtAfterStartDtRule.java b/clearing-parent/clearing-validation/src/main/java/ru/spcex/clearing/validation/common/rules/EndDtAfterStartDtRule.java index 169e5589f..1403e9338 100644 --- a/clearing-parent/clearing-validation/src/main/java/ru/spcex/clearing/validation/common/rules/EndDtAfterStartDtRule.java +++ b/clearing-parent/clearing-validation/src/main/java/ru/spcex/clearing/validation/common/rules/EndDtAfterStartDtRule.java @@ -80,7 +80,7 @@ public record EndDtAfterStartDtRule( LocalDate startDt = getterStartDt.apply(validatedObject); if (endDt == null) return required ? of(errorEmptyRequiredValue, endDtFieldName) : Optional.empty(); if (startDt == null) return required ? of(errorEmptyRequiredValue, startDtFieldName) : Optional.empty(); - if (endDt.isAfter(startDt)) return of(errorEndDtAfterStartDt, startDtFieldName, endDtFieldName); + if (startDt.isAfter(endDt)) return of(errorEndDtAfterStartDt, startDtFieldName, endDtFieldName); return Optional.empty(); } } diff --git a/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/service/ClearingMemberCategoryService.java b/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/service/ClearingMemberCategoryService.java index 9fcac3f22..33bdb7ed2 100644 --- a/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/service/ClearingMemberCategoryService.java +++ b/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/service/ClearingMemberCategoryService.java @@ -9,6 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.company.ClearingMemberCategory; +import ru.clearing.classes.statics.data.company.Company; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.Consts; @@ -21,20 +22,25 @@ import ru.spcex.clearing.util.security.UserRoleVerification; import ru.spcex.clearing.validation.common.ValidationHelper; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.ImdgTransaction; import ru.spcex.platform.utils.validation.IValidator; +import java.util.Map; import java.util.function.Function; @Service public class ClearingMemberCategoryService extends QueueConsumer implements InitializingBean { private final Logger log = LoggerFactory.getLogger(getClass()); private final Imdg clearingMemberCategoryMap; + private final Imdg companyMap; + private final ImdgProvider imdgProvider; private final Function clearingMemberCategoryNewRequestValidator; private final Function clearingMemberCategoryUpdateRequestValidator; private final Function clearingMemberCategoryDeleteRequestValidator; private final ValidationHelper validationHelper; private final UserRoleVerification userRoleVerification; + private final CompanyService companyService; @Autowired public ClearingMemberCategoryService(Consumer kafkaQueue, @@ -44,14 +50,18 @@ public class ClearingMemberCategoryService extends QueueConsumer implements Init UserRoleVerification userRoleVerification, @Qualifier("clearingMemberCategoryNewRequestValidator") Function clearingMemberCategoryNewRequestValidator, @Qualifier("clearingMemberCategoryUpdateRequestValidator") Function clearingMemberCategoryUpdateRequestValidator, - @Qualifier("clearingMemberCategoryDeleteRequestValidator") Function clearingMemberCategoryDeleteRequestValidator) { + @Qualifier("clearingMemberCategoryDeleteRequestValidator") Function clearingMemberCategoryDeleteRequestValidator, + CompanyService companyService) { super(kafkaQueue, kafkaProducer); this.clearingMemberCategoryMap = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class); + this.companyMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class); + this.imdgProvider = imdgProvider; this.clearingMemberCategoryNewRequestValidator = clearingMemberCategoryNewRequestValidator; this.clearingMemberCategoryUpdateRequestValidator = clearingMemberCategoryUpdateRequestValidator; this.clearingMemberCategoryDeleteRequestValidator = clearingMemberCategoryDeleteRequestValidator; this.validationHelper = validationHelper; this.userRoleVerification = userRoleVerification; + this.companyService = companyService; } @Override @@ -76,14 +86,28 @@ public class ClearingMemberCategoryService extends QueueConsumer implements Init requestInfoUpdate = validationHelper.validateTillFirstError(userRequest, clearingMemberCategoryNewRequestValidator); if (requestInfoUpdate != null) return requestInfoUpdate; - ClearingMemberCategoryNewRequest req = userRequest.getRequestPayload(); ClearingMemberCategory newCategory = new ClearingMemberCategory(); newCategory.setCompanyId(req.getCompanyId()); newCategory.setClearingMemberCategory(req.getClearingMemberCategory()); - clearingMemberCategoryMap.insert(newCategory); - log.debug("successfully processed, new category id {}", newCategory.getId()); + synchronized (companyService) { + ImdgTransaction transaction = imdgProvider.newTransaction(); + transaction.beginTransaction(); + boolean txOk = false; + try { + companyService.relationService.createNewRelation(transaction, req.getCompanyId()); + Imdg txClearingMemberCategoryMap = transaction.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class); + txClearingMemberCategoryMap.insert(newCategory); + txOk = true; + } finally { + if (txOk) + transaction.commitTransaction(); + else + transaction.rollbackTransaction(); + } + } + log.debug("Successfully processed, new category id {}", newCategory.getId()); return null; } diff --git a/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/service/CompanyService.java b/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/service/CompanyService.java index 3b51e8ed6..5ee1b2778 100644 --- a/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/service/CompanyService.java +++ b/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/service/CompanyService.java @@ -143,7 +143,7 @@ public class CompanyService extends QueueConsumer implements InitializingBean { companyMap.insert(company); log.debug("company-new request processed, BaseRequest.id = {}, company.id={}", companyNewRequestBaseRequest.getId(), company.getId()); - relationService.createNewRelation(transaction, company); + relationService.createNewRelation(transaction, company.getId()); if (!(WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus()))) { // Block relationService.onChangeWorkflowStatus(transaction, company, null, company.getWorkflowStatus()); } 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 index 30eab291e..b9fd8f5ad 100644 --- 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 @@ -9,6 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.lang.NonNull; import org.springframework.stereotype.Service; +import ru.clearing.classes.statics.data.company.ClearingMemberCategory; import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.profile.ProfileDocument; import ru.spcex.clearing.company.error.CompanyErrors; @@ -27,6 +28,7 @@ import ru.spcex.platform.enumeration.DocumentTypes; import ru.spcex.platform.enumeration.WorkflowStatus; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.ImdgTransaction; import ru.spcex.platform.utils.enumeration.IMessageResolver; import ru.spcex.platform.utils.validation.IValidator; @@ -41,6 +43,7 @@ public class ProfileDocumentService extends QueueConsumer implements Initializin private ImdgProvider imdgProvider; private AccountNotificationHelper accountNotificationHelper; + private final CompanyService companyService; private final Function profileDocumentNewRequestValidator; private final Function profileDocumentUpdateRequestValidator; private final Function profileDocumentDeleteRequestValidator; @@ -60,7 +63,8 @@ public class ProfileDocumentService extends QueueConsumer implements Initializin ValidationHelper validationHelper, IMessageResolver messageResolver, RequestHelper requestHelper, - AccountNotificationHelper accountNotificationHelper) { + AccountNotificationHelper accountNotificationHelper, + CompanyService companyService) { super(kafkaQueue, kafkaProducer); this.imdgProvider = imdgProvider; this.accountNotificationHelper = accountNotificationHelper; @@ -71,6 +75,7 @@ public class ProfileDocumentService extends QueueConsumer implements Initializin this.userRoleVerification = userRoleVerification; this.messageResolver = messageResolver; this.requestHelper = requestHelper.setLogger(log); + this.companyService = companyService; } @Override @@ -148,9 +153,22 @@ public class ProfileDocumentService extends QueueConsumer implements Initializin log.debug("Company {} not active", profileDocument.getCompanyId()); return requestHelper.makeErrorResponse(deleteRequest, CompanyErrors.CompanyNotFound, profileDocument.getCompanyId()); } - - profileDocumentMap.delete(profileDocument); - + synchronized (companyService) { + ImdgTransaction transaction = imdgProvider.newTransaction(); + transaction.beginTransaction(); + boolean txOk = false; + try { + companyService.relationService.cancelingOfAgreementUpdateRelation(transaction, profileDocument.getCompanyId()); + Imdg txProfileDocumentMap= transaction.getImdg(IMDGDistributedNames.Map_ProfileDocument, ProfileDocument.class); + txProfileDocumentMap.delete(profileDocument); + txOk = true; + } finally { + if (txOk) + transaction.commitTransaction(); + else + transaction.rollbackTransaction(); + } + } log.trace("successfully deleted, id {}", profileDocument.getId()); return null; diff --git a/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/service/RelationService.java b/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/service/RelationService.java index d91417af6..0fbd00f46 100644 --- a/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/service/RelationService.java +++ b/clearing-parent/company-service/src/main/java/ru/spcex/clearing/company/service/RelationService.java @@ -8,6 +8,7 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; +import ru.clearing.classes.statics.data.company.ClearingMemberCategory; import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.company.relation.Relation; import ru.spcex.clearing.company.error.CompanyErrors; @@ -29,6 +30,7 @@ import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgId; import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.ImdgTransaction; +import ru.spcex.platform.utils.enumeration.IEnumKey; import ru.spcex.platform.utils.error.ValidationException; import ru.spcex.platform.utils.validation.IValidator; @@ -38,6 +40,11 @@ import java.util.Map; import java.util.Objects; import java.util.function.Function; +import static ru.spcex.platform.enumeration.Service.FOND; +import static ru.spcex.platform.enumeration.Service.MKR; +import static ru.spcex.platform.enumeration.SessionStatus.CLOS; +import static ru.spcex.platform.utils.enumeration.IEnumKey.getEnumByKey; + @Service public class RelationService extends QueueConsumer implements InitializingBean { protected static final Long SPVB_ID = 1L; // СПВБ @@ -106,6 +113,14 @@ public class RelationService extends QueueConsumer implements InitializingBean { private synchronized RequestInfoUpdate relationNew(BaseRequest relationNewBaseRequest) { RelationNewRequest req = relationNewBaseRequest.getRequestPayload(); log.debug("relation-new request received, BaseRequest.id = {}", relationNewBaseRequest.getId()); + + { //проверка заполнен ли serviceStatus + String serviceStatus = req.getServiceStatus(); + if (serviceStatus == null || serviceStatus.isEmpty()) { + Company company = companyMap.getSingleObjectByFieldValues(Map.of("id", req.getCompanyId())); + req.setServiceStatus(company.getWorkflowStatus()); + } + } { // Валидация RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(relationNewBaseRequest); if (requestInfoUpdate != null) return requestInfoUpdate; @@ -120,7 +135,7 @@ public class RelationService extends QueueConsumer implements InitializingBean { Relation existRelation = searchRelation(req.getClearingMemberCategory(), req.getCompanyId()); if (existRelation != null && !WorkflowStatus.Blocked.equalsByKey(existRelation.getServiceStatus())) { CompanyErrors errorType; - if (ru.spcex.platform.enumeration.Service.MKR.equalsByKey(existRelation.getService())) { + if (MKR.equalsByKey(existRelation.getService())) { errorType = CompanyErrors.ClearingMemberCategoryOnMKRAlreadyExist; } else if (ru.spcex.platform.enumeration.Service.FOND.equalsByKey(existRelation.getService())) { errorType = CompanyErrors.ClearingMemberCategoryOnFONDAlreadyExist; @@ -160,7 +175,7 @@ public class RelationService extends QueueConsumer implements InitializingBean { relation.setServiceStatus(toStatus); } } - relation.setService(ru.spcex.platform.enumeration.Service.MKR.getKey()); // MKR + relation.setService(MKR.getKey()); // MKR relation.setServiceProduct(ServiceProduct.ZERO.getKey()); relation.setComment(req.getComment()); @@ -176,7 +191,7 @@ public class RelationService extends QueueConsumer implements InitializingBean { || ClearingCategory.I.equalsByKey(clearingMemberCategory) || ClearingCategory.V.equalsByKey(clearingMemberCategory) ) { - svc = ru.spcex.platform.enumeration.Service.MKR.getKey(); + svc = MKR.getKey(); } else if (ClearingCategory.C.equalsByKey(clearingMemberCategory) || ClearingCategory.F.equalsByKey(clearingMemberCategory) ) { @@ -265,21 +280,46 @@ public class RelationService extends QueueConsumer implements InitializingBean { // --- internal API --- - protected void createNewRelation(ImdgTransaction transaction, Company company) { + protected void createNewRelation(ImdgTransaction transaction, Long companyId) { + Imdg relationMap = transaction.getImdg(IMDGDistributedNames.Map_Relation, Relation.class); Relation relation = new Relation(); -// relation.setId(idSequence.nextId()); + Company company = transaction.getImdg(IMDGDistributedNames.Map_Company, Company.class).getSingleObjectByFieldValues(Map.of("id", companyId)); + ClearingMemberCategory clearingMemberCategory = transaction.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class).getSingleObjectByFieldValues(Map.of("companyId", companyId)); + + WorkflowStatus workflowStatus = getEnumByKey(WorkflowStatus.class, company.getWorkflowStatus()); + ClearingCategory clearingCategory = getEnumByKey(ClearingCategory.class, clearingMemberCategory.getClearingMemberCategory()); + String serviceStatus; + switch (Objects.requireNonNull(clearingCategory)){ + case B: + case I: + case V: + serviceStatus = MKR.getKey(); + break; + case C: + case F: + serviceStatus = FOND.getKey(); + break; + default: + throw new IllegalStateException("Illegal state of clearingCategory"); + } + relation.setCreated(Instant.now()); relation.setUpdated(relation.getCreated()); - - relation.setConsumerId(company.getId()); + relation.setConsumerId(companyId); relation.setSupplierId(SPVB_ID); // 1 СПВБ - relation.setServiceStatus(WorkflowStatus.Active.getKey()); - relation.setService(ru.spcex.platform.enumeration.Service.MKR.getKey()); // MKR + relation.setServiceStatus(Objects.requireNonNull(workflowStatus).getKey()); + relation.setService(serviceStatus); relation.setServiceProduct(ServiceProduct.ZERO.getKey()); log.debug("New Relation[{}] created.", relation.getId()); - Imdg relationMap = transaction.getImdg(IMDGDistributedNames.Map_Relation, Relation.class); relationMap.insert(relation); } + protected void cancelingOfAgreementUpdateRelation(ImdgTransaction transaction, Long companyId) { + Imdg relationMap = transaction.getImdg(IMDGDistributedNames.Map_Relation, Relation.class); + Relation relation = relationMap.getSingleObjectByFieldValues(Map.of("consumerId", companyId)); + relation.setServiceStatus(CLOS.getKey()); + relationMap.update(relation); + log.debug("New Relation[{}] updated.", relation.getId()); + } /** * @param company diff --git a/clearing-parent/dbf-importer/src/main/java/ru/spcex/clearing/dbf/importer/logic/data/tables/SDf57Table.java b/clearing-parent/dbf-importer/src/main/java/ru/spcex/clearing/dbf/importer/logic/data/tables/SDf57Table.java index 7e8c1e6fd..312320548 100644 --- a/clearing-parent/dbf-importer/src/main/java/ru/spcex/clearing/dbf/importer/logic/data/tables/SDf57Table.java +++ b/clearing-parent/dbf-importer/src/main/java/ru/spcex/clearing/dbf/importer/logic/data/tables/SDf57Table.java @@ -4,6 +4,7 @@ import ru.clearing.classes.statics.data.sdf.SDf57; import ru.spcex.clearing.dbf.importer.logic.data.enums.ETable; import ru.spcex.clearing.imdg.IMDGDistributedNames; +import java.math.BigDecimal; import java.time.Instant; public class SDf57Table extends AbstractTable { @@ -19,42 +20,43 @@ public class SDf57Table extends AbstractTable { @Override public SDf57 getEntity(Object[] entity) { SDf57 result = new SDf57(); - result.setDeal_deb((String) entity[0]); - result.setDeal_cred((String) entity[1]); - result.setSbankcode((String) entity[2]); - result.setSbanknam1((String) entity[3]); - result.setSbanknam2((String) entity[4]); - result.setSbanknam3((String) entity[5]); - result.setSbanknam4((String) entity[6]); - result.setSbanknam5((String) entity[7]); - result.setC_acc_cred((String) entity[8]); - result.setRbanknam1((String) entity[9]); - result.setRbanknam2((String) entity[10]); - result.setRbanknam3((String) entity[11]); - result.setRbanknam4((String) entity[12]); - result.setRbanknam5((String) entity[13]); - result.setOp_type((String) entity[14]); - result.setPay_date((String) entity[15]); - result.setExt_date((String) entity[16]); - result.setPay_val((String) entity[17]); - result.setSum_deb((String) entity[18]); - result.setSclientn1((String) entity[19]); - result.setSclientn1((String) entity[20]); - result.setSclientn2((String) entity[21]); - result.setSclientn3((String) entity[22]); - result.setSclientn4((String) entity[23]); - result.setInn_deb((String) entity[24]); - result.setKpp_deb((String) entity[25]); - result.setAcc_deb((String) entity[26]); - result.setRclientn1((String) entity[27]); - result.setRclientn2((String) entity[28]); - result.setRclientn3((String) entity[29]); - result.setRclientn4((String) entity[30]); - result.setInn_cred((String) entity[31]); - result.setInn_cred((String) entity[32]); - result.setKpp_cred((String) entity[33]); - result.setAcc_kr((String) entity[34]); - result.setSpecif((String) entity[35]); + result.setDbfId(((BigDecimal) entity[0]).longValue()); + result.setDeal_deb((String) entity[1]); + result.setDeal_cred((String) entity[2]); + result.setSbankcode((String) entity[3]); + result.setC_acc_deb((String) entity[4]); + result.setSbanknam1((String) entity[5]); + result.setSbanknam2((String) entity[6]); + result.setSbanknam3((String) entity[7]); + result.setSbanknam4((String) entity[8]); + result.setSbanknam5((String) entity[9]); + result.setRbankcode((String) entity[10]); + result.setC_acc_cred((String) entity[11]); + result.setRbanknam1((String) entity[12]); + result.setRbanknam2((String) entity[13]); + result.setRbanknam3((String) entity[14]); + result.setRbanknam4((String) entity[15]); + result.setRbanknam5((String) entity[16]); + result.setOp_type((String) entity[17]); + result.setPay_date((String) entity[18]); + result.setExt_date((String) entity[19]); + result.setPay_val((String) entity[20]); + result.setSum_deb((String) entity[21]); + result.setSclientn1((String) entity[22]); + result.setSclientn2((String) entity[23]); + result.setSclientn3((String) entity[24]); + result.setSclientn4((String) entity[25]); + result.setInn_deb((String) entity[26]); + result.setKpp_deb((String) entity[27]); + result.setAcc_deb((String) entity[28]); + result.setRclientn1((String) entity[29]); + result.setRclientn2((String) entity[30]); + result.setRclientn3((String) entity[31]); + result.setRclientn4((String) entity[32]); + result.setInn_cred((String) entity[33]); + result.setKpp_cred((String) entity[34]); + result.setAcc_kr((String) entity[35]); + result.setSpecif((String) entity[36]); result.setFileName(filename); result.setGenerationTime(Instant.now()); result.setGenerationId(fileId); diff --git a/clearing-parent/lim-exporter/src/main/java/ru/spcex/clearing/lim/exporter/config/KafkaConfig.java b/clearing-parent/lim-exporter/src/main/java/ru/spcex/clearing/lim/exporter/config/KafkaConfig.java index 45fc6642c..6721788f6 100644 --- a/clearing-parent/lim-exporter/src/main/java/ru/spcex/clearing/lim/exporter/config/KafkaConfig.java +++ b/clearing-parent/lim-exporter/src/main/java/ru/spcex/clearing/lim/exporter/config/KafkaConfig.java @@ -7,9 +7,17 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.kafka.core.ProducerFactory; +import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.lim.exporter.config.settings.ExportLimServiceSettings; import ru.spcex.clearing.platform.messaging.config.KafkaConsumerFactory; import ru.spcex.clearing.platform.messaging.config.KafkaProducerFactory; +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 KafkaConfig { @@ -25,4 +33,24 @@ public class KafkaConfig { public Producer createProducer(ExportLimServiceSettings settings) { return KafkaProducerFactory.producer(settings.getKafkaProducer()); } + + @Bean + public KafkaTemplate kafkaTemplate(ProducerFactory pf) { + return new KafkaTemplate<>(pf); + } + + @Autowired + @Bean + public KafkaSender kafkaSender(KafkaTemplate kafkaTemplate, ImdgProvider imdgProvider) { + ImdgId imdgIdGenerator = imdgProvider.getImdgIdGenerator(); + return KafkaSender + .setup() + .setKafkaTemplate(kafkaTemplate) + .idGenerator(imdgIdGenerator::nextId) + .imdgProvider(s -> { + Imdg imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_RequestInfo, RequestInfo.class); + return imdg::insert; + }) + .build(); + } } diff --git a/clearing-parent/lim-exporter/src/main/java/ru/spcex/clearing/lim/exporter/services/AbstractExporterService.java b/clearing-parent/lim-exporter/src/main/java/ru/spcex/clearing/lim/exporter/services/AbstractExporterService.java index e92739815..5d3989f4f 100644 --- a/clearing-parent/lim-exporter/src/main/java/ru/spcex/clearing/lim/exporter/services/AbstractExporterService.java +++ b/clearing-parent/lim-exporter/src/main/java/ru/spcex/clearing/lim/exporter/services/AbstractExporterService.java @@ -1,7 +1,5 @@ package ru.spcex.clearing.lim.exporter.services; -import org.apache.kafka.clients.producer.Producer; -import org.apache.kafka.clients.producer.ProducerRecord; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.StringUtils; @@ -10,6 +8,8 @@ import ru.clearing.classes.statics.data.registry.TradingClearingRegistry; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.lim.exporter.config.SFTPConfig; import ru.spcex.clearing.platform.messaging.domain.cud.utilities.LimExportedRequest; +import ru.spcex.clearing.platform.messaging.serialization.LogFormatter; +import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.utils.log.ExceptionUtils; @@ -32,11 +32,12 @@ public abstract class AbstractExporterService { private final Imdg tradingClearingRegistryImdg; private final DateTimeFormatter dtFormatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); private final SFTPConfig.LimGateway gateway; - private final Producer producer; + private final KafkaSender kafkaSender; - protected AbstractExporterService(SFTPConfig.LimGateway gateway, Producer producer, ImdgProvider imdgProvider) { + protected AbstractExporterService(SFTPConfig.LimGateway gateway, + KafkaSender kafkaSender, ImdgProvider imdgProvider) { this.gateway = gateway; - this.producer = producer; + this.kafkaSender = kafkaSender; this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); this.tradingClearingRegistryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class); } @@ -68,9 +69,14 @@ public abstract class AbstractExporterService { } log.debug("Successfully exported {} file", fileName); + sendLimExportedNotification(fileName); + } + + void sendLimExportedNotification(String fileName) { LimExportedRequest limExportedRequest = new LimExportedRequest(); limExportedRequest.setLimFileName(fileName); - producer.send(new ProducerRecord<>(LIM_EXPORTED, limExportedRequest)); + log.debug("Send message to kafka \"{}\": {}", LIM_EXPORTED, LogFormatter.toStringWrapper(limExportedRequest)); + kafkaSender.sendRequestToQueue(LIM_EXPORTED, limExportedRequest); } protected String prepareFileName(String target) { diff --git a/clearing-parent/lim-exporter/src/main/java/ru/spcex/clearing/lim/exporter/services/MoneyExporterService.java b/clearing-parent/lim-exporter/src/main/java/ru/spcex/clearing/lim/exporter/services/MoneyExporterService.java index 121b32210..5ab00cc30 100644 --- a/clearing-parent/lim-exporter/src/main/java/ru/spcex/clearing/lim/exporter/services/MoneyExporterService.java +++ b/clearing-parent/lim-exporter/src/main/java/ru/spcex/clearing/lim/exporter/services/MoneyExporterService.java @@ -1,11 +1,11 @@ package ru.spcex.clearing.lim.exporter.services; -import org.apache.kafka.clients.producer.Producer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.registry.Registry; import ru.spcex.clearing.lim.exporter.config.SFTPConfig; +import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; import ru.spcex.platform.imdg.api.ImdgProvider; import java.math.BigDecimal; @@ -21,9 +21,9 @@ public class MoneyExporterService extends AbstractExporterService { private final Logger log = LoggerFactory.getLogger(getClass()); public MoneyExporterService(SFTPConfig.LimGateway gateway, - Producer producer, + KafkaSender kafkaSender, ImdgProvider imdgProvider) { - super(gateway, producer, imdgProvider); + super(gateway, kafkaSender, imdgProvider); } @Override diff --git a/clearing-parent/lim-exporter/src/main/java/ru/spcex/clearing/lim/exporter/services/SecurityExporterService.java b/clearing-parent/lim-exporter/src/main/java/ru/spcex/clearing/lim/exporter/services/SecurityExporterService.java index 63d439dda..ae079aacc 100644 --- a/clearing-parent/lim-exporter/src/main/java/ru/spcex/clearing/lim/exporter/services/SecurityExporterService.java +++ b/clearing-parent/lim-exporter/src/main/java/ru/spcex/clearing/lim/exporter/services/SecurityExporterService.java @@ -6,6 +6,7 @@ import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.registry.Registry; import ru.spcex.clearing.lim.exporter.config.SFTPConfig; +import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; import ru.spcex.platform.imdg.api.ImdgProvider; import java.time.LocalDate; @@ -19,9 +20,9 @@ public class SecurityExporterService extends AbstractExporterService { private final Logger log = LoggerFactory.getLogger(getClass()); public SecurityExporterService(SFTPConfig.LimGateway gateway, - Producer producer, + KafkaSender kafkaSender, ImdgProvider imdgProvider) { - super(gateway, producer, imdgProvider); + super(gateway, kafkaSender, imdgProvider); } diff --git a/clearing-parent/lim-exporter/src/test/java/ru/spcex/clearing/lim/exporter/AbstractServiceTest.java b/clearing-parent/lim-exporter/src/test/java/ru/spcex/clearing/lim/exporter/AbstractServiceTest.java index 103207f84..34bb55987 100644 --- a/clearing-parent/lim-exporter/src/test/java/ru/spcex/clearing/lim/exporter/AbstractServiceTest.java +++ b/clearing-parent/lim-exporter/src/test/java/ru/spcex/clearing/lim/exporter/AbstractServiceTest.java @@ -9,6 +9,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.registry.TradingClearingRegistry; import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; import ru.spcex.clearing.test.config.ImdgTestConfig; import ru.spcex.clearing.test.config.KafkaTestConfig; import ru.spcex.platform.imdg.api.Imdg; @@ -37,6 +38,9 @@ public abstract class AbstractServiceTest { @Qualifier("mockProducer") protected Producer mockProducer; + @Autowired + protected KafkaSender kafkaSender; + @Autowired @Qualifier("hazelcastServiceTest") protected ImdgProvider imdgProvider; diff --git a/clearing-parent/lim-exporter/src/test/java/ru/spcex/clearing/lim/exporter/services/AbstractExporterServiceTest.java b/clearing-parent/lim-exporter/src/test/java/ru/spcex/clearing/lim/exporter/services/AbstractExporterServiceTest.java new file mode 100644 index 000000000..d1a6bfa32 --- /dev/null +++ b/clearing-parent/lim-exporter/src/test/java/ru/spcex/clearing/lim/exporter/services/AbstractExporterServiceTest.java @@ -0,0 +1,27 @@ +package ru.spcex.clearing.lim.exporter.services; + +import org.junit.jupiter.api.Test; +import ru.spcex.clearing.lim.exporter.AbstractServiceTest; +import ru.spcex.clearing.test.TestUtils; + +import javax.annotation.PostConstruct; + +import java.time.LocalDateTime; + +import static org.junit.jupiter.api.Assertions.*; + +class AbstractExporterServiceTest extends AbstractServiceTest { + @PostConstruct + public void init() { + super.init(); + } + + @Test + void sendLimExportedNotification() { + AbstractExporterService moneyExporterService = new MoneyExporterService(null, kafkaSender, imdgProvider); + + String fileName = "limits_money_202305241832.lim"; + moneyExporterService.sendLimExportedNotification(fileName); + //TestUtils.waitingSendAndCheckRecord(null, mockProducer); + } +} \ No newline at end of file diff --git a/clearing-parent/lim-exporter/src/test/java/ru/spcex/clearing/lim/exporter/services/MoneyExporterServiceTest.java b/clearing-parent/lim-exporter/src/test/java/ru/spcex/clearing/lim/exporter/services/MoneyExporterServiceTest.java index 8163fd83e..10741693c 100644 --- a/clearing-parent/lim-exporter/src/test/java/ru/spcex/clearing/lim/exporter/services/MoneyExporterServiceTest.java +++ b/clearing-parent/lim-exporter/src/test/java/ru/spcex/clearing/lim/exporter/services/MoneyExporterServiceTest.java @@ -36,7 +36,7 @@ class MoneyExporterServiceTest extends AbstractServiceTest { registryImdg.insert(registryA); registryImdg.insert(registryD); - MoneyExporterService moneyExporterService = new MoneyExporterService(null, mockProducer, imdgProvider); + MoneyExporterService moneyExporterService = new MoneyExporterService(null, kafkaSender, imdgProvider); Collection limFileRows = moneyExporterService.getLimFileRows(); assertEquals(0, limFileRows.size()); diff --git a/clearing-parent/lim-exporter/src/test/java/ru/spcex/clearing/lim/exporter/services/SecurityExporterServiceTest.java b/clearing-parent/lim-exporter/src/test/java/ru/spcex/clearing/lim/exporter/services/SecurityExporterServiceTest.java index cf7099a4d..72813baf7 100644 --- a/clearing-parent/lim-exporter/src/test/java/ru/spcex/clearing/lim/exporter/services/SecurityExporterServiceTest.java +++ b/clearing-parent/lim-exporter/src/test/java/ru/spcex/clearing/lim/exporter/services/SecurityExporterServiceTest.java @@ -36,7 +36,7 @@ class SecurityExporterServiceTest extends AbstractServiceTest { registryImdg.insert(registry1); registryImdg.insert(registry2); - SecurityExporterService securityExporterService = new SecurityExporterService(null, mockProducer, imdgProvider); + SecurityExporterService securityExporterService = new SecurityExporterService(null, kafkaSender, imdgProvider); Collection limFileRows = securityExporterService.getLimFileRows(); assertEquals(0, limFileRows.size()); diff --git a/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/cud/MoneyMarketSecurityService.java b/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/cud/MoneyMarketSecurityService.java index 3b37d72a7..d9f5bd9e2 100644 --- a/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/cud/MoneyMarketSecurityService.java +++ b/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/service/cud/MoneyMarketSecurityService.java @@ -102,8 +102,14 @@ public class MoneyMarketSecurityService extends QueueConsumer implements Initial ImdgTransaction transaction = imdgProvider.newTransaction(); MoneyMarketSecurityNewRequest req = userRequest.getRequestPayload(); - RequestInfoUpdate requestInfoUpdate = validationHelper.validateTillFirstError(userRequest, validation.mmsNewValidator()); - if (requestInfoUpdate != null) return requestInfoUpdate; + { + RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(userRequest); + if (requestInfoUpdate != null) return requestInfoUpdate; + } + { + RequestInfoUpdate requestInfoUpdate = validationHelper.validateTillFirstError(userRequest, validation.mmsNewValidator()); + if (requestInfoUpdate != null) return requestInfoUpdate; + } log.debug("MoneyMarketSecurityNewRequest received"); MoneyMarketSecurity mms = new MoneyMarketSecurity(); @@ -165,6 +171,7 @@ public class MoneyMarketSecurityService extends QueueConsumer implements Initial .setMessage(errorMsg); } MoneyMarketSecurity mms = validator.getStored(Stored.PresentById); + if (mms == null) log.error("Validator return null stored mms object."); Instant updateTime = Instant.now(); mms.setUpdated(updateTime); mms.setStartDate(req.getStartDate()); @@ -216,6 +223,7 @@ public class MoneyMarketSecurityService extends QueueConsumer implements Initial } Instant updateTime = Instant.now(); MoneyMarketSecurity mms = validator.getStored(Stored.PresentById); + if (mms == null) log.error("Validator return null stored mms object."); mms.setWorkflowStatus(ru.spcex.platform.enumeration.Status.Blocked.getKey()); mms.setUpdated(updateTime); moneyMarketSecurityMap.update(mms); diff --git a/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/validation/rule/NotPresentBySecuritySymbolAndWorkflowStatusActv.java b/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/validation/rule/NotPresentBySecuritySymbolAndWorkflowStatusActv.java index a65516a81..397df369b 100644 --- a/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/validation/rule/NotPresentBySecuritySymbolAndWorkflowStatusActv.java +++ b/clearing-parent/securities-service/src/main/java/ru/spcex/clearing/securities/validation/rule/NotPresentBySecuritySymbolAndWorkflowStatusActv.java @@ -4,7 +4,7 @@ import org.springframework.util.StringUtils; import ru.spcex.clearing.securities.errors.SecuritiesError; import ru.spcex.platform.classes.base.SpcexObjectBase; import ru.spcex.platform.classes.base.interfaces.WithSecuritySymbol; -import ru.spcex.platform.enumeration.Status; +import ru.spcex.platform.enumeration.WorkflowStatus; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.validation.ImdgValidationContext; import ru.spcex.platform.utils.enumeration.EnumMessage; @@ -30,11 +30,11 @@ public class NotPresentBySecuritySymbolAndWorkflowStatusActv imdg = context.obtainMap(mapName, clazz); if(!StringUtils.hasText(action.getSecuritySymbol())) { - return of(SecuritiesError.RequiredFieldIsEmpty, "securitySymbole"); + return of(SecuritiesError.RequiredFieldIsEmpty, "securitySymbol"); } T object = imdg.getSingleObjectByFieldValues(Map.of( "securitySymbol", action.getSecuritySymbol(), - "workflowStatus", Status.Active.getKey())); + "workflowStatus", WorkflowStatus.Active.getKey())); if (object != null) { return of(errorEnum); } else { diff --git a/clearing-parent/securities-service/src/test/java/ru/spcex/clearing/securities/service/MoneyMarketSecurityServiceTest.java b/clearing-parent/securities-service/src/test/java/ru/spcex/clearing/securities/service/MoneyMarketSecurityServiceTest.java index 80f5141d0..8c574787e 100644 --- a/clearing-parent/securities-service/src/test/java/ru/spcex/clearing/securities/service/MoneyMarketSecurityServiceTest.java +++ b/clearing-parent/securities-service/src/test/java/ru/spcex/clearing/securities/service/MoneyMarketSecurityServiceTest.java @@ -88,6 +88,47 @@ public class MoneyMarketSecurityServiceTest extends AbstractServiceTest { LISTING_MATCHER.assertMatch(listingResult, listingPrediction); } +// @Test todo тест с проверкой валидатора +// public void testNewMoneyMarketSecurity2() { +// clearAllInImdg(moneyMarketSecurityMap); +// final String TOPIC = Consts.DESTINATION_MONEY_MARKET_SECURITY_NEW; +// +// final MoneyMarketSecurity moneyMarketSecurityPrediction = moneyMarketSecurityFactory +// .getMoneyMarketSecurity(); +// final MoneyMarketSecurityNewRequest keyRequest = moneyMarketSecurityFactory +// .getMoneyMarketSecurityNewRequest(); +// Listing listingPrediction = ListingBuilder.builder() +// .append(moneyMarketSecurityPrediction).append(keyRequest).build(); +// +// // Создание копии инструмента - не должен задублировать его +// MoneyMarketSecurity existMMS = new MoneyMarketSecurity(); +// existMMS.setId(123L); +// existMMS.setSecuritySymbol(keyRequest.getSecuritySymbol()); +// existMMS.setWorkflowStatus(WorkflowStatus.Active.getKey()); +// moneyMarketSecurityMap.insert(existMMS); +// +// //ACT +// String jsonString = getJsonStringForNew(keyRequest, ID); +// +// addRecordToKafka((MockConsumer) moneyMarketSecurityService.getConsumer(), TOPIC, PARTITION, 0, jsonString); +// +// //ASSERT +// waitingWhenTryAddRecordAndCheckError(ID, mockProducer, +// "1010" //SecuritiesError.InstrumentAlreadyExists +// , Arrays.asList("")); +// waitingSendAndCheckRecord(ID, mockProducer); +// +// MoneyMarketSecurity moneyMarketSecurityResult = moneyMarketSecurityMap.getSingleObjectBySQL(String.format("fullName = %s", moneyMarketSecurityFactory.getFullName())); +// moneyMarketSecurityPrediction.setId(moneyMarketSecurityResult.getId()); +// moneyMarketSecurityPrediction.setSecurityId(moneyMarketSecurityResult.getSecurityId()); +// MONEY_MARKET_SECURITY_MATCHER.assertMatch(moneyMarketSecurityResult, moneyMarketSecurityPrediction); +// +// Listing listingResult = listingImdg.getSingleObjectByFieldValues(Map.of("securityId", moneyMarketSecurityPrediction.getId())); +// listingPrediction.setId(listingResult.getId()); +// listingPrediction.setSecurityId(listingResult.getSecurityId()); +// LISTING_MATCHER.assertMatch(listingResult, listingPrediction); +// } + /** * {@link MoneyMarketSecurityService#deleteMoneyMarket(BaseRequest)}
* Тест проверяет удаление сущности {@link MoneyMarketSecurity} в Hazelcast при передаче из Apache Kafka.
diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/MarketType.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/MarketType.java new file mode 100644 index 000000000..930e40a2c --- /dev/null +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/MarketType.java @@ -0,0 +1,18 @@ +package ru.spcex.platform.enumeration; + +import ru.spcex.platform.utils.enumeration.IEnumKey; + +public enum MarketType implements IEnumKey { + PRMR("PRMR"); + + private final String key; + + MarketType(String key) { + this.key = key; + } + + @Override + public String getKey() { + return key; + } +} diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/SessionType.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/SessionType.java index 70ba05bd5..43ea888fb 100644 --- a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/SessionType.java +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/SessionType.java @@ -3,7 +3,7 @@ package ru.spcex.platform.enumeration; import ru.spcex.platform.utils.enumeration.IEnumKey; public enum SessionType implements IEnumKey { - IPOB("IPOB"), + IPOB("IPOB"), IPO0("IPO0"), ; SessionType(String key) { diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Task.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Task.java index 40bd8c007..422a649ae 100644 --- a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Task.java +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Task.java @@ -10,6 +10,7 @@ public enum Task implements IEnumKey { getVerification("GVER"),// Запуск сверки @Deprecated /* todo GBLD удаляется по CLS-267, CLS-275 */ getBalance("GBLD"),// Поступление средств startOfClearing("SCLR"),// Запуск клиринговой сессии + startOfB0("IPO0"),// Запуск клиринговой сессии startOfPreClearing("SPRC"),// Запуск преклиринга startPostClearing("SPOC"),// Запуск постклиринга createOrder("CORD"), diff --git a/platform-parent/platform-imdg-api-hazelcast-impl/src/main/java/ru/spcex/platform/imdg/iml/hazelcast/adapter/ImdgHazelcast.java b/platform-parent/platform-imdg-api-hazelcast-impl/src/main/java/ru/spcex/platform/imdg/iml/hazelcast/adapter/ImdgHazelcast.java index 4cbde8b72..7b54770ae 100644 --- a/platform-parent/platform-imdg-api-hazelcast-impl/src/main/java/ru/spcex/platform/imdg/iml/hazelcast/adapter/ImdgHazelcast.java +++ b/platform-parent/platform-imdg-api-hazelcast-impl/src/main/java/ru/spcex/platform/imdg/iml/hazelcast/adapter/ImdgHazelcast.java @@ -257,7 +257,7 @@ public class ImdgHazelcast implements Imdg { if (els.size() > 1) { throw new RuntimeException("More than one element found by predicate - " + els.size()); } - return els.iterator().next(); + return els.size() == 1 ? els.iterator().next() : null; } @Override diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/Consts.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/Consts.java index f19bf4da3..e0197d92c 100644 --- a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/Consts.java +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/Consts.java @@ -16,6 +16,10 @@ public interface Consts { String DESTINATION_FIXED_INCOME_CASH_FLOW_NEW = "fixed-income-cash-flow-new"; String DESTINATION_FIXED_INCOME_CASH_FLOW_UPDATE = "fixed-income-cash-flow-update"; + String LISTING_NEW = "listing-new"; + String LISTING_UPDATE = "listing-update"; + String LISTING_DELETE = "listing-delete"; + String DESTINATION_CURRENCY_NEW = "currency-new"; String DESTINATION_CURRENCY_UPDATE = "currency-update"; String DESTINATION_COUPON_PERIOD_NEW = "coupon_period-new"; diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/ListingNewRequest.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/ListingNewRequest.java new file mode 100644 index 000000000..d5784e5c4 --- /dev/null +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/ListingNewRequest.java @@ -0,0 +1,58 @@ +package ru.spcex.clearing.platform.messaging.domain.cud.securitites; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.math.BigDecimal; + +public class ListingNewRequest { + @JsonProperty + private Long securityId; + @JsonProperty + private String market; + @JsonProperty + private BigDecimal lotSize; + @JsonProperty + private String tradingCurrency; + @JsonProperty + private String workflowStatus; + + public Long getSecurityId() { + return securityId; + } + + public void setSecurityId(Long securityId) { + this.securityId = securityId; + } + + public String getMarket() { + return market; + } + + public void setMarket(String market) { + this.market = market; + } + + public BigDecimal getLotSize() { + return lotSize; + } + + public void setLotSize(BigDecimal lotSize) { + this.lotSize = lotSize; + } + + public String getTradingCurrency() { + return tradingCurrency; + } + + public void setTradingCurrency(String tradingCurrency) { + this.tradingCurrency = tradingCurrency; + } + + public String getWorkflowStatus() { + return workflowStatus; + } + + public void setWorkflowStatus(String workflowStatus) { + this.workflowStatus = workflowStatus; + } +} diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/ListingUpdateRequest.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/ListingUpdateRequest.java new file mode 100644 index 000000000..fc414f37b --- /dev/null +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/securitites/ListingUpdateRequest.java @@ -0,0 +1,68 @@ +package ru.spcex.clearing.platform.messaging.domain.cud.securitites; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.math.BigDecimal; + +public class ListingUpdateRequest { + @JsonProperty + private Long id; + @JsonProperty + private Long securityId; + @JsonProperty + private String market; + @JsonProperty + private BigDecimal lotSize; + @JsonProperty + private String tradingCurrency; + @JsonProperty + private String workflowStatus; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getSecurityId() { + return securityId; + } + + public void setSecurityId(Long securityId) { + this.securityId = securityId; + } + + public String getMarket() { + return market; + } + + public void setMarket(String market) { + this.market = market; + } + + public BigDecimal getLotSize() { + return lotSize; + } + + public void setLotSize(BigDecimal lotSize) { + this.lotSize = lotSize; + } + + public String getTradingCurrency() { + return tradingCurrency; + } + + public void setTradingCurrency(String tradingCurrency) { + this.tradingCurrency = tradingCurrency; + } + + public String getWorkflowStatus() { + return workflowStatus; + } + + public void setWorkflowStatus(String workflowStatus) { + this.workflowStatus = workflowStatus; + } +}