From 10cf6bc3cb5e08c6366464568e333427b0482a1d Mon Sep 17 00:00:00 2001 From: AKurakin Date: Tue, 31 Jan 2023 13:58:05 +0300 Subject: [PATCH 01/42] =?UTF-8?q?reports-service=20=D0=BF=D0=BE=D0=BF?= =?UTF-8?q?=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=BE=D1=82=D0=BA=D1=83=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BE=D0=BA?= =?UTF-8?q?:=20=D0=B5=D1=81=D0=BB=D0=B8=201=20=D0=B2=D0=B8=D0=B4=20=D0=BE?= =?UTF-8?q?=D1=82=D1=87=D1=91=D1=82=D0=B0=20=D0=BD=D0=B5=20=D1=81=D0=BC?= =?UTF-8?q?=D0=BE=D0=B6=D0=B5=D1=82=20=D1=81=D0=B4=D0=B5=D0=BB=D0=B0=D1=82?= =?UTF-8?q?=D1=8C,=20=D1=82=D0=BE=20=D0=B4=D0=B1=D1=83=D0=B4=D0=B5=D1=82?= =?UTF-8?q?=20=D0=BF=D1=80=D0=BE=D0=B1=D0=BE=D0=B2=D0=B0=D1=82=D1=8C=20?= =?UTF-8?q?=D0=B4=D0=BE=D0=B4=D0=B5=D0=BB=D0=B0=D1=82=D1=8C=20=D0=BE=D1=81?= =?UTF-8?q?=D1=82=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5;=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=20ReportBR=5F0420314=5FP2?= =?UTF-8?q?=20=D0=BF=D1=80=D0=B8=20=D0=BE=D1=82=D1=81=D1=83=D1=82=D1=81?= =?UTF-8?q?=D1=82=D0=B2=D0=B8=D0=B8=20company=20=D0=BF=D0=B8=D1=88=D0=B5?= =?UTF-8?q?=D1=82=20warn=20=D0=B8=20=D0=BF=D1=80=D0=BE=D0=BF=D1=83=D1=81?= =?UTF-8?q?=D0=BA=D0=B0=D0=B5=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reports/services/ReportsServiceCommand.java | 13 +++++++++++-- .../collector/ReportBR_0420314_P2_Collector.java | 4 ++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/ReportsServiceCommand.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/ReportsServiceCommand.java index 260a368d0..499228968 100644 --- a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/ReportsServiceCommand.java +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/ReportsServiceCommand.java @@ -12,6 +12,7 @@ import ru.spcex.clearing.reports.reports.ReportId; import ru.spcex.clearing.reports.services.builders.XMLReportBuilder; import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.utils.enumeration.IEnumKey; +import ru.spcex.platform.utils.log.ExceptionUtils; import java.io.File; import java.io.IOException; @@ -74,12 +75,20 @@ public class ReportsServiceCommand implements InitializingBean { public void generateReportAll(@Nullable String reportGroup, LocalDate startDate, LocalDate endDate) throws IOException { for (ReportWithPeriodCollector reportDataCollector : allPeriodReports) { if (reportGroup == null || QUEUE_RUN_REPORT_COMMAND.equals(reportGroup)) { - makeSingleReport(reportDataCollector, startDate, endDate); + try { + makeSingleReport(reportDataCollector, startDate, endDate); + } catch (Exception e) { + log.error("Error generate report of type {}: {}", reportDataCollector, ExceptionUtils.getStackTrace(e)); + } } } for (SimpleReportCollector reportDataCollector : allSimpleReports) { if (reportGroup == null || QUEUE_RUN_DAILY_REPORT_COMMAND.equals(reportGroup)) { - makeSingleReport(reportDataCollector); + try { + makeSingleReport(reportDataCollector); + } catch (Exception e) { + log.error("Error generate report of type {}: {}", reportDataCollector, ExceptionUtils.getStackTrace(e)); + } } } } diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportBR_0420314_P2_Collector.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportBR_0420314_P2_Collector.java index 027135ddc..46bacd498 100644 --- a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportBR_0420314_P2_Collector.java +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportBR_0420314_P2_Collector.java @@ -68,6 +68,10 @@ public class ReportBR_0420314_P2_Collector extends ReportWithPeriodCollector paymentInstructionsByCompany = entry.getValue(); Company company = companyImdg.getSingleObjectByID(companyId); + if (company == null) { + log.warn("Company not found, id={}", companyId); + continue; + } ProfileDocument profileDocumentCntr = profileDocumentImdg.getSingleObjectByFieldValues(Map.of( "companyId", companyId, "documentType", DocumentTypes.cntr.getKey() From 270a27187c33a68f45bac8aa324d16872085e7de Mon Sep 17 00:00:00 2001 From: etreshenkov Date: Tue, 31 Jan 2023 14:48:01 +0300 Subject: [PATCH 02/42] http://jira.mfd.msk:8088/browse/CLS-217 --- .../queue/scheduler/LauncherController.java | 36 ++++++++++++++++--- .../request/cud/schedule/LauncherNew.java | 24 +++++++++++++ .../service/ExecutionDepositComponent.java | 28 +++++---------- .../service/LauncherCommandReceiver.java | 33 +++++++++++++++++ .../scheduler/service/LauncherService.java | 6 ++++ .../cud/schedule/LauncherCommandRequest.java | 21 ++++++++++- 6 files changed, 124 insertions(+), 24 deletions(-) create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/LauncherCommandReceiver.java diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/scheduler/LauncherController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/scheduler/LauncherController.java index a6e7bb993..f0dcfa17f 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/scheduler/LauncherController.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/scheduler/LauncherController.java @@ -24,6 +24,8 @@ import ru.spcex.clearing.backendapi.security.KeycloakUtils; import ru.spcex.clearing.backendapi.service.IOperator; import ru.spcex.clearing.backendapi.service.IStateLoader; import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.Consts; +import ru.spcex.platform.enumeration.Task; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.utils.enumeration.EnumMessage; @@ -67,7 +69,7 @@ public class LauncherController extends AbstractQueueController { @RequestMapping(value = "/{task-code}", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) @ResponseBody public CudResponse add(@ApiParam(value = "Код задания из taskDictionary", required = true, example = "ABLK") - @PathVariable("task-code") String dictionaryName) throws ExecutionException, InterruptedException { + @PathVariable("task-code") String dictionaryName) throws ExecutionException, InterruptedException { AbstractDictionary taskEnum = taskDictionary.getSingleObjectByFieldValues(Map.of("code", dictionaryName)); if (taskEnum == null) { throw new NotFound404Exception("task dictionary element with code '" + dictionaryName + "'"); @@ -81,11 +83,37 @@ public class LauncherController extends AbstractQueueController { } launcherCommand.setTask(dictionaryName); launcherCommand.setUserId(user.getId()); - // пока здесь, это требуется для сохранения истории - saveLauncher(dictionaryName, user.getId()); //топики ограничиваются наличием в taskDictionary //подписываются на разные топики в разных модулях, см. ru.spcex.platform.enumeration.Task#topic - return processRequest("launcher-" + dictionaryName, launcherCommand); + return processRequest(Consts.LAUNCHER_NEW, launcherCommand); + } + + @ApiOperation(value = "create specific launcher.") + @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CudResponse.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)}) + @RequestMapping(value = "/specific/{task-code}", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public CudResponse addSpecific(@ApiParam(value = "Код задания из taskDictionary", required = true, example = "ABLK") + @PathVariable("task-code") String dictionaryName, + @RequestBody LauncherNew launcherNew) throws ExecutionException, InterruptedException { + AbstractDictionary taskEnum = taskDictionary.getSingleObjectByFieldValues(Map.of("code", dictionaryName)); + if (taskEnum == null) { + throw new NotFound404Exception("task dictionary element with code '" + dictionaryName + "'"); + } + if (!Task.startOfClearing.getKey().equals(taskEnum.getCode())) { + throw new IllegalStateException(String.format("Task %s not support request with body", taskEnum.getCode())); + } + LauncherNew launcherCommand = new LauncherNew(); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + String username = KeycloakUtils.getUserNameFromAuthentication(authentication); + User user = userImdg.getSingleObjectByFieldValues(Map.of("identifier", username)); + if (user == null) { + throw new IllegalStateException("cannot obtain userId from logged in user " + username); + } + launcherCommand.setTask(dictionaryName); + launcherCommand.setUserId(user.getId()); + launcherCommand.setCompanyId(launcherNew.getCompanyId()); + launcherCommand.setSecurityId(launcherNew.getSecurityId()); + return processRequest(Consts.LAUNCHER_NEW, launcherCommand); } private void saveLauncher(String taskCode, Long userId) { diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/schedule/LauncherNew.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/schedule/LauncherNew.java index ce810d0e8..31ceac638 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/schedule/LauncherNew.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/schedule/LauncherNew.java @@ -19,6 +19,12 @@ public class LauncherNew implements IAction { @ApiModelProperty(value = "Идентификатор единоличного исполнительного органа", example = "ABCD") @JsonProperty private String task; + @ApiModelProperty(value = "Идентификатор инициатора", example = "1000") + @JsonProperty + private Long companyId; + @ApiModelProperty(value = "Идентификатор инструмента", example = "1000") + @JsonProperty + private Long securityId; @JsonIgnore private Long userId; @@ -32,6 +38,8 @@ public class LauncherNew implements IAction { } else { LauncherCommandRequest taskRunnerCommandRequest = new LauncherCommandRequest(); taskRunnerCommandRequest.setTaskName(task); + taskRunnerCommandRequest.setCompanyId(companyId); + taskRunnerCommandRequest.setSecurityId(securityId); taskRunnerCommandRequest.setUserId(userId); return taskRunnerCommandRequest; } @@ -65,4 +73,20 @@ public class LauncherNew implements IAction { public void setUserId(Long userId) { this.userId = userId; } + + public Long getCompanyId() { + return companyId; + } + + public void setCompanyId(Long companyId) { + this.companyId = companyId; + } + + public Long getSecurityId() { + return securityId; + } + + public void setSecurityId(Long securityId) { + this.securityId = securityId; + } } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecutionDepositComponent.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecutionDepositComponent.java index e16d34736..bbe554b3a 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecutionDepositComponent.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecutionDepositComponent.java @@ -1,6 +1,5 @@ package ru.spcex.clearing.service; -import com.fasterxml.jackson.annotation.JsonProperty; import org.apache.kafka.clients.producer.Producer; import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.clients.producer.RecordMetadata; @@ -10,15 +9,11 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; import ru.clearing.classes.statics.data.account.Account; -import ru.clearing.classes.statics.data.account.AccountBalance; -import ru.clearing.classes.statics.data.clearing.VerificationResult; import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.execution.ExecutionDeposit; import ru.clearing.classes.statics.data.misc.Listing; import ru.clearing.classes.statics.data.misc.STrade; -import ru.clearing.classes.statics.data.sdf.SDf01; import ru.clearing.classes.statics.data.security.Security; import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.error.ClearingException; @@ -26,12 +21,10 @@ import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.ActionType; import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.Consts; +import ru.spcex.clearing.platform.messaging.domain.cud.registry.CoveredDealRegisterNewRequest; import ru.spcex.clearing.platform.messaging.domain.cud.securitites.MoneyMarketSecurityNewRequest; -import ru.spcex.platform.classes.base.interfaces.WithId; -import ru.spcex.platform.enumeration.AccountType; import ru.spcex.platform.enumeration.Allowed; import ru.spcex.platform.enumeration.Market; -import ru.spcex.platform.enumeration.ResultStatuses; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgId; import ru.spcex.platform.imdg.api.ImdgProvider; @@ -40,17 +33,13 @@ import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; import ru.spcex.platform.utils.enumeration.EnumMessage; import ru.spcex.platform.utils.log.ExceptionUtils; import ru.spcex.platform.utils.time.TimeUtil; -import ru.spcex.clearing.platform.messaging.domain.cud.registry.CoveredDealRegisterNewRequest; - import java.math.BigDecimal; -import java.math.RoundingMode; import java.time.Instant; import java.time.LocalDate; import java.util.*; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; -import java.util.function.Function; import java.util.stream.Collectors; /** @@ -96,7 +85,7 @@ public class ExecutionDepositComponent { /** * Сбрасывать каждый день в 01:00:01 "0 1 0 1 * ?" */ - @Scheduled(cron = "${clearing-service.scheduler.check-s-trade}") + @Scheduled(cron = "${clearing-service.scheduler.check-s-trade}") public void resetTradingDay() { Instant today = TimeUtil.localDateToInstant(LocalDate.now()); if (tradingDay == null || !tradingDay.equals(today)) { @@ -109,7 +98,7 @@ public class ExecutionDepositComponent { public void processNewTS() { Long tradeNum = -1L; // todo уточнить как он обновляется ImdgPredicateBuilder pb = sTradeImdg.predicateBuilder(); - ImdgPredicate sql = pb.and(pb.greater("tradeNum",tradeNum), pb.greatEqual("tradeDateTime", tradingDay)); + ImdgPredicate sql = pb.and(pb.greater("tradeNum", tradeNum), pb.greatEqual("tradeDateTime", tradingDay)); Collection sTrades = sTradeImdg.getCollectionObjectsByPredicate(sql); log.info("Found {} new s_trade with trade_num>{}", sTrades.size(), tradeNum); @@ -145,7 +134,7 @@ public class ExecutionDepositComponent { Long generationId = idGenerator.nextId(); log.info("generationId = {}", generationId); - for (STrade trade:sTrades) { + for (STrade trade : sTrades) { log.trace("Check s_trade[{}].tradeNum={}", trade.getId(), trade.getTradeNum()); Collection existsEDeposit = executionDepositImdg.getCollectionObjectsByFieldValues(Map.of( "exchangeExecutionId", trade.getTradeNum(), @@ -170,13 +159,13 @@ public class ExecutionDepositComponent { } } else { - long[] idToLong = existsEDeposit.stream().mapToLong(ed-> ed.getId()).toArray(); + long[] idToLong = existsEDeposit.stream().mapToLong(ed -> ed.getId()).toArray(); log.warn("S_TRADE[{}] already has executionDeposit: {}", trade.getId(), Arrays.toString(idToLong)); } } - Long newMaxTradeNum = sTrades.stream().mapToLong(STrade::getTradeNum).max().orElseGet(()-> tradeNum); + Long newMaxTradeNum = sTrades.stream().mapToLong(STrade::getTradeNum).max().orElseGet(() -> tradeNum); log.debug("Next tradeNum is {}", newMaxTradeNum); } @@ -203,13 +192,14 @@ public class ExecutionDepositComponent { /** * в очередь kafka для модуля securities-service сообщение о добавлении инструмента с параметром securitySymbol=s_trade.sec_code + * * @param newSymbolRequest */ protected void createNewSecurities(Collection newSymbolRequest) { final String destination = Consts.DESTINATION_MONEY_MARKET_SECURITY_NEW; List symbolRequests = new ArrayList<>(newSymbolRequest); // чтобы в случае ошибки отобразить номер в логе List> sendAll = new ArrayList<>(symbolRequests.size()); - for (String newSymbol: symbolRequests) { + for (String newSymbol : symbolRequests) { if (newSymbol == null || newSymbol.isEmpty()) { log.warn("Empty SecuritySumbol"); } else { @@ -228,7 +218,7 @@ public class ExecutionDepositComponent { } } int i = 0; - for (Future future: sendAll) { + for (Future future : sendAll) { try { future.get(); // get exception } catch (InterruptedException e) { diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/LauncherCommandReceiver.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/LauncherCommandReceiver.java new file mode 100644 index 000000000..06d5aa4ef --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/LauncherCommandReceiver.java @@ -0,0 +1,33 @@ +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.stereotype.Service; +import ru.spcex.clearing.platform.messaging.domain.cud.schedule.LauncherCommandRequest; +import ru.spcex.clearing.platform.messaging.service.QueueConsumer; +import ru.spcex.platform.enumeration.Task; + +@Service +public class LauncherCommandReceiver extends QueueConsumer implements InitializingBean { + private final Logger log = LoggerFactory.getLogger(getClass()); + + private final ClearingService clearingService; + @Autowired + public LauncherCommandReceiver(Consumer kafkaQueue, + ClearingService clearingService) { + super(kafkaQueue); + this.clearingService = clearingService; + } + + @Override + public void afterPropertiesSet() { + callback(LauncherCommandRequest.class) + .setConsumer(action -> clearingService.executeVerification()) + .forDestination(Task.createOrderConfirm.topic(), callbacks::put); // CORC + + init(); + } +} diff --git a/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/LauncherService.java b/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/LauncherService.java index a41698909..7f9e2f44f 100644 --- a/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/LauncherService.java +++ b/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/LauncherService.java @@ -2,10 +2,12 @@ package ru.spcex.clearing.scheduler.service; import org.apache.kafka.clients.consumer.Consumer; 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.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.scheduler.Launcher; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.BaseRequest; @@ -20,14 +22,17 @@ import java.time.Instant; import static ru.spcex.platform.utils.enumeration.IEnumKey.getEnumByKey; +@Service public class LauncherService extends QueueConsumer implements InitializingBean { private final Logger log = LoggerFactory.getLogger(getClass()); private final Imdg launcherMap; + private final Producer kafkaProducer; @Autowired public LauncherService(Consumer kafkaQueue, Producer kafkaProducer, ImdgProvider imdgProvider) { super(kafkaQueue, kafkaProducer); + this.kafkaProducer = kafkaProducer; this.launcherMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Launcher, Launcher.class); } @@ -53,6 +58,7 @@ public class LauncherService extends QueueConsumer implements InitializingBean { launcher.setUpdated(created); launcherMap.insert(launcher); log.debug("successfully processed, new id {}", launcher.getId()); + kafkaProducer.send(new ProducerRecord<>("launcher-" + launcher.getTask(), req)); } } diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/schedule/LauncherCommandRequest.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/schedule/LauncherCommandRequest.java index 4382eecb7..b05686017 100644 --- a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/schedule/LauncherCommandRequest.java +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/schedule/LauncherCommandRequest.java @@ -6,9 +6,12 @@ public class LauncherCommandRequest { @JsonProperty private Long userId; - @JsonProperty private String taskName; + @JsonProperty + private Long companyId; + @JsonProperty + private Long securityId; public Long getUserId() { @@ -26,4 +29,20 @@ public class LauncherCommandRequest { public void setTaskName(String taskName) { this.taskName = taskName; } + + public Long getCompanyId() { + return companyId; + } + + public void setCompanyId(Long companyId) { + this.companyId = companyId; + } + + public Long getSecurityId() { + return securityId; + } + + public void setSecurityId(Long securityId) { + this.securityId = securityId; + } } From 52ff31204462dc51f09b4fa225f9f465d57f98d6 Mon Sep 17 00:00:00 2001 From: ialbert Date: Tue, 31 Jan 2023 15:24:57 +0300 Subject: [PATCH 03/42] http://jira.mfd.msk:8088/browse/CLS-189 --- .../spcex/clearing/config/SortingConfig.java | 34 ++++++ .../ru/spcex/clearing/service/Clearing.java | 46 ++++++++ .../clearing/service/ClearingService.java | 16 ++- .../clearing/service/EventsReceiver.java | 3 + .../service/ExecDepositWCategory.java | 26 +++++ .../service/order/ExecutionDepositSorter.java | 108 ++++++++++++++++++ .../service/order/PaymentBatchInfo.java | 10 +- .../order/PaymentInstructionSorter.java | 12 +- .../reports/reports/bt_12_2/ReportPA_B.java | 4 +- .../reports/reports/bt_12_2/ReportPA_IV.java | 6 +- .../reports/bt_17_1/ReportBR_0420315_P1.java | 6 +- .../collector/ReportPA_B_Collector.java | 4 +- .../collector/ReportPA_IV_Collector.java | 4 +- ...emberCategoryD.java => MoneyFlowSide.java} | 8 +- 14 files changed, 259 insertions(+), 28 deletions(-) create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/SortingConfig.java create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecDepositWCategory.java create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/ExecutionDepositSorter.java rename platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/{ClearingMemberCategoryD.java => MoneyFlowSide.java} (64%) diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/SortingConfig.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/SortingConfig.java new file mode 100644 index 000000000..b45a0085d --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/SortingConfig.java @@ -0,0 +1,34 @@ +package ru.spcex.clearing.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import ru.clearing.classes.statics.data.generated.ClearingMemberCategory; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.platform.enumeration.ClearingCategory; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.utils.enumeration.IEnumKey; + +import java.util.Map; +import java.util.function.Function; + +@Configuration +public class SortingConfig { + private final Imdg clearingCategoryImdg; + + @Autowired + public SortingConfig(ImdgProvider imdgProvider) { + this.clearingCategoryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class); + } + + @Bean + public Function clearingMemberCategoryProvider() { + return companyId -> { + ClearingMemberCategory category = clearingCategoryImdg.getSingleObjectByFieldValues( + Map.of("companyId", companyId)); + return IEnumKey.getEnumByKey(ClearingCategory.class, + category.getClearingMemberCategory()); + }; + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java new file mode 100644 index 000000000..90a4bf630 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java @@ -0,0 +1,46 @@ +package ru.spcex.clearing.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import ru.clearing.classes.statics.data.execution.ExecutionDeposit; +import ru.clearing.classes.statics.data.generated.ClearingMemberCategory; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.service.order.ExecutionDepositSorter; +import ru.spcex.platform.enumeration.ClearingCategory; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.List; + +@Service +public class Clearing { + private final Imdg executionDepositImdg; + private final Imdg clearingCategoryImdg; + private final ExecutionDepositSorter sorter; + + @Autowired + public Clearing(ImdgProvider imdgProvider, ExecutionDepositSorter sorter) { + this.executionDepositImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionDeposit, ExecutionDeposit.class); + this.clearingCategoryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class); + this.sorter = sorter; + } + + public void startClearing() { + //выгружаем ExecutionDeposit с пустым sessionId + Collection execDeposits = executionDepositImdg.getCollectionObjectsBySQL("sessionId = null"); + //делаем группировку ExecutionDeposit по категории и компании, делаем сортировку + LinkedHashMap>> executionDeposits = sorter.sortExecutionDeposit(execDeposits); + + executionDeposits.forEach((category, companies) -> { + for (List companyExecDeposits : companies) { + processSingleCompany(category, companyExecDeposits); + } + }); + } + + private void processSingleCompany(ClearingCategory category, List executionDeposits) { + + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ClearingService.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ClearingService.java index 58c25acfe..7213ef7f6 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ClearingService.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ClearingService.java @@ -5,7 +5,6 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import ru.spcex.platform.utils.log.ExceptionUtils; @@ -20,13 +19,15 @@ public class ClearingService implements DisposableBean { private final SdfCreatorBySTLDPayment sdfCreator; private final PaymentUpdateBySdf04 paymentUpdater; private final VerificationResultComponent verificationResultComponent; + private final Clearing clearing; @Autowired public ClearingService(SdfCreatorBySTLDPayment sdfCreator, PaymentUpdateBySdf04 paymentUpdater, - VerificationResultComponent verificationResultComponent) { + VerificationResultComponent verificationResultComponent, Clearing clearing) { this.sdfCreator = sdfCreator; this.paymentUpdater = paymentUpdater; this.verificationResultComponent = verificationResultComponent; + this.clearing = clearing; this.executor = Executors.newSingleThreadExecutor(); } @@ -69,4 +70,15 @@ public class ClearingService implements DisposableBean { log.debug("Shutdown {}", getClass().getSimpleName()); executor.shutdown(); } + + public void executeClearing() { + log.info("start clearing"); + executor.execute(() -> { + try { + clearing.startClearing(); + } catch (Throwable e) { + log.error("{}", ExceptionUtils.getStackTrace(e)); + } + }); + } } 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 f7911379f..76e0aba39 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 @@ -31,6 +31,9 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean { callback(LauncherCommandRequest.class) .setConsumer(event -> clearingService.executeVerification()) .forDestination(Task.getVerification.topic(), callbacks::put); + callback(Object.class) //todo check Object suitable + .setConsumer(event -> clearingService.executeClearing()) + .forDestination(Task.startOfClearing.topic(), callbacks::put); init(); } } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecDepositWCategory.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecDepositWCategory.java new file mode 100644 index 000000000..91f745949 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecDepositWCategory.java @@ -0,0 +1,26 @@ +package ru.spcex.clearing.service; + +import ru.clearing.classes.statics.data.execution.ExecutionDeposit; +import ru.spcex.platform.enumeration.ClearingCategory; + +public class ExecDepositWCategory { + private final ExecutionDeposit executionDeposit; + private final ClearingCategory clearingMemberCategory; + + public ExecDepositWCategory(ExecutionDeposit executionDeposit, ClearingCategory clearingMemberCategory) { + this.executionDeposit = executionDeposit; + this.clearingMemberCategory = clearingMemberCategory; + } + + public ExecutionDeposit getExecutionDeposit() { + return executionDeposit; + } + + public ClearingCategory getClearingMemberCategory() { + return clearingMemberCategory; + } + + public Long getCompanyId() { + return executionDeposit.getCompanyId(); + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/ExecutionDepositSorter.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/ExecutionDepositSorter.java new file mode 100644 index 000000000..21178cd47 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/ExecutionDepositSorter.java @@ -0,0 +1,108 @@ +package ru.spcex.clearing.service.order; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import ru.clearing.classes.statics.data.execution.ExecutionDeposit; +import ru.spcex.clearing.service.ExecDepositWCategory; +import ru.spcex.platform.enumeration.ClearingCategory; +import ru.spcex.platform.enumeration.MoneyFlowSide; +import ru.spcex.platform.utils.enumeration.IEnumKey; + +import java.util.*; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Component +public class ExecutionDepositSorter { + private Function clearingMemberCategoryProvider; + + @Autowired + public void setClearingMemberCategoryProvider(Function clearingMemberCategoryProvider) { + this.clearingMemberCategoryProvider = clearingMemberCategoryProvider; + } + + public LinkedHashMap>> sortExecutionDeposit(CollectionexecDeposits) { + //отсортировали все записи по категориям + // → внутри каждой подгруппы по категориям сортируем по компаниям + // → обрабатываем почередно все записи первой компании + // → когда по первой компании записи закончились, начинаем обработавать все записи второй компании и так далее + // → когда по первой категории закончились записи для всех компаниий, + // начинаем аналогично обработавать все записи второй категории и так далее). + + //сортируем по категориям + Map> categoryGrouping = execDeposits.stream().map(executionDeposit -> { + ClearingCategory category = clearingMemberCategoryProvider.apply(executionDeposit.getCompanyId()); + return new ExecDepositWCategory(executionDeposit, category); + }).collect(Collectors.groupingBy(ExecDepositWCategory::getClearingMemberCategory)); + + //внутри категорий сортируем по компаниям + LinkedHashMap>> byCategoryByCompany = new LinkedHashMap<>(); + Consumer takeByClearingCategoryAnSortByCompaniId = clearingCategory -> { + List wrappers = categoryGrouping.remove(clearingCategory); + if (wrappers != null) { + List> batches = wrappers.stream() + .collect(Collectors.groupingBy(ExecDepositWCategory::getCompanyId)) + .entrySet() + .stream() + .sorted(Map.Entry.comparingByKey()) + .map(Map.Entry::getValue) + .toList(); + byCategoryByCompany.put(clearingCategory, batches); + } + }; + //кладем в порядке I, V, B + takeByClearingCategoryAnSortByCompaniId.accept(ClearingCategory.I); + takeByClearingCategoryAnSortByCompaniId.accept(ClearingCategory.V); + takeByClearingCategoryAnSortByCompaniId.accept(ClearingCategory.B); + //для всех остальных порядок не важен, будут последними + categoryGrouping.keySet().forEach(takeByClearingCategoryAnSortByCompaniId); + + //метод для дополнительной сортировки внутри групп по категории и компании + BiConsumer> additionalSorting = + (clearingCategory, comparator) -> byCategoryByCompany + .get(clearingCategory) + .forEach(singleCompanyBatch -> singleCompanyBatch.sort(comparator)); + //применяем дополнительные сортировки + //для V сначала Sell, потом Buy, в первую очередь должны обрабатываться новые сделки с наименьшими объемами + additionalSorting.accept(ClearingCategory.V, firstSellThenBuy + .thenComparing(wrapper -> wrapper.getExecutionDeposit().getFirstLegAmount())); + //для V сначала Buy, потом Sell, exchangeExecutionId - возрастающий + additionalSorting.accept(ClearingCategory.B, firstBuyThenSell + .thenComparing(wrapper -> wrapper.getExecutionDeposit().getExchangeExecutionId())); + return byCategoryByCompany; + } + + public static Comparator firstSellThenBuy = Comparator.comparing(wrapper -> { + MoneyFlowSide side = IEnumKey.getEnumByKey(MoneyFlowSide.class, wrapper.getExecutionDeposit().getSide()); + if (side == null) return Integer.MAX_VALUE; + switch (side) { + case BUY -> { + return 1; + } + case SELL -> { + return 0; + } + default -> { + return Integer.MAX_VALUE; + } + } + }); + + public static Comparator firstBuyThenSell = Comparator.comparing(wrapper -> { + MoneyFlowSide side = IEnumKey.getEnumByKey(MoneyFlowSide.class, wrapper.getExecutionDeposit().getSide()); + if (side == null) return Integer.MAX_VALUE; + switch (side) { + case BUY -> { + return 0; + } + case SELL -> { + return 1; + } + default -> { + return Integer.MAX_VALUE; + } + } + }); +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentBatchInfo.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentBatchInfo.java index 4f96a3856..fbf555bde 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentBatchInfo.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentBatchInfo.java @@ -1,7 +1,7 @@ package ru.spcex.clearing.service.order; import ru.clearing.classes.statics.data.payment.PaymentInstruction; -import ru.spcex.platform.enumeration.ClearingMemberCategoryD; +import ru.spcex.platform.enumeration.ClearingCategory; import ru.spcex.platform.utils.enumeration.EnumMessage; import java.util.Collection; @@ -13,13 +13,13 @@ public class PaymentBatchInfo { private List initialOrder; private List fromClearingToBank; private List fromBankToClearing; - private ClearingMemberCategoryD categoryD; + private ClearingCategory categoryD; private EnumMessage error; public Stream getOrderedPaymentInstructions() { Function, Stream> safeStream = paymentInstructions -> paymentInstructions != null ? paymentInstructions.stream() : Stream.empty(); - if (categoryD.equals(ClearingMemberCategoryD.B)) { + if (categoryD.equals(ClearingCategory.B)) { return safeStream.apply(initialOrder); } else { return Stream.concat(safeStream.apply(fromClearingToBank), safeStream.apply(fromBankToClearing)); @@ -43,11 +43,11 @@ public class PaymentBatchInfo { this.fromBankToClearing = fromBankToClearing; } - public ClearingMemberCategoryD getCategoryD() { + public ClearingCategory getCategoryD() { return categoryD; } - public void setCategoryD(ClearingMemberCategoryD categoryD) { + public void setCategoryD(ClearingCategory categoryD) { this.categoryD = categoryD; } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentInstructionSorter.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentInstructionSorter.java index c898213d2..031bcf128 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentInstructionSorter.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentInstructionSorter.java @@ -10,7 +10,7 @@ import ru.clearing.classes.statics.data.payment.PaymentInstruction; import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.platform.enumeration.AccountType; -import ru.spcex.platform.enumeration.ClearingMemberCategoryD; +import ru.spcex.platform.enumeration.ClearingCategory; import ru.spcex.platform.enumeration.TransactionStatus; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; @@ -46,15 +46,15 @@ public class PaymentInstructionSorter { List result = new ArrayList<>(2); log.info("processing PaymentInstruction's generationId={} senderId={} size={}", generationId, senderId, payments.size()); Collection cmcList = clrngMmbrImdg.getCollectionObjectsByFieldValues(Map.of("companyId", senderId)); - Collection companyCategory = cmcList.stream() + Collection companyCategory = cmcList.stream() .filter(cat -> cat.getClearingMemberCategory() != null) - .map(cat -> IEnumKey.getEnumByKey(ClearingMemberCategoryD.class, cat.getClearingMemberCategory())) + .map(cat -> IEnumKey.getEnumByKey(ClearingCategory.class, cat.getClearingMemberCategory())) .collect(Collectors.toSet()); - for (ClearingMemberCategoryD categoryValue : companyCategory) { + for (ClearingCategory categoryValue : companyCategory) { log.debug("For category {}", categoryValue); PaymentBatchInfo batchInfo = new PaymentBatchInfo(); batchInfo.setCategoryD(categoryValue); - if (ClearingMemberCategoryD.I.equals(categoryValue)) { + if (ClearingCategory.I.equals(categoryValue)) { EnumMessage error = null; List aList = new ArrayList<>(); List bList = new ArrayList<>(); @@ -118,7 +118,7 @@ public class PaymentInstructionSorter { batchInfo.setFromBankToClearing(bList); result.add(batchInfo); } - } else if (ClearingMemberCategoryD.B.equals(categoryValue)) { + } else if (ClearingCategory.B.equals(categoryValue)) { batchInfo.setInitialOrder(payments); result.add(batchInfo); } else { diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bt_12_2/ReportPA_B.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bt_12_2/ReportPA_B.java index 4d3be05d8..1f3c7ae98 100644 --- a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bt_12_2/ReportPA_B.java +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bt_12_2/ReportPA_B.java @@ -4,7 +4,7 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAsAttribute; import ru.spcex.clearing.reports.reports.ReportId; import ru.spcex.clearing.reports.reports.ReportWithPeriod; -import ru.spcex.platform.enumeration.ClearingMemberCategoryD; +import ru.spcex.platform.enumeration.ClearingCategory; import java.time.LocalDate; import java.time.LocalDateTime; @@ -31,7 +31,7 @@ public class ReportPA_B extends ReportWithPeriod { "Отчет по нетто-позиции участника клиринга в секции МКР (Уполномоченный банк)", startDate, endDate); - this.clearingMemberCategory = ClearingMemberCategoryD.B.getKey(); + this.clearingMemberCategory = ClearingCategory.B.getKey(); } @Override diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bt_12_2/ReportPA_IV.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bt_12_2/ReportPA_IV.java index 4d733ae0c..12d124dc7 100644 --- a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bt_12_2/ReportPA_IV.java +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bt_12_2/ReportPA_IV.java @@ -4,7 +4,7 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAsAttribute; import ru.spcex.clearing.reports.reports.ReportId; import ru.spcex.clearing.reports.reports.ReportWithPeriod; -import ru.spcex.platform.enumeration.ClearingMemberCategoryD; +import ru.spcex.platform.enumeration.ClearingCategory; import java.time.LocalDate; import java.time.LocalDateTime; @@ -33,8 +33,8 @@ public class ReportPA_IV extends ReportWithPeriod { startDate, endDate); this.clearingMemberCategory = "%s,%s".formatted( - ClearingMemberCategoryD.I.getKey(), - ClearingMemberCategoryD.V.getKey() + ClearingCategory.I.getKey(), + ClearingCategory.V.getKey() ); } diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bt_17_1/ReportBR_0420315_P1.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bt_17_1/ReportBR_0420315_P1.java index 70d706c99..67aafde5b 100644 --- a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bt_17_1/ReportBR_0420315_P1.java +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/reports/bt_17_1/ReportBR_0420315_P1.java @@ -5,7 +5,7 @@ import com.thoughtworks.xstream.annotations.XStreamAsAttribute; import ru.spcex.clearing.reports.reports.Destination; import ru.spcex.clearing.reports.reports.ReportId; import ru.spcex.clearing.reports.reports.ReportWithClearingStatus; -import ru.spcex.platform.enumeration.ClearingMemberCategoryD; +import ru.spcex.platform.enumeration.ClearingCategory; import ru.spcex.platform.enumeration.ClearingStatus; import java.time.LocalDate; @@ -37,8 +37,8 @@ public class ReportBR_0420315_P1 extends ReportWithClearingStatus { ClearingStatus.OK.getKey()); this.destination = Destination.BR.getKey(); this.clearingMemberCategory = "%s,%s".formatted( - ClearingMemberCategoryD.I.getKey(), - ClearingMemberCategoryD.V.getKey() + ClearingCategory.I.getKey(), + ClearingCategory.V.getKey() ); } diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportPA_B_Collector.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportPA_B_Collector.java index a5b84606e..8f6fe2bc4 100644 --- a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportPA_B_Collector.java +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportPA_B_Collector.java @@ -6,7 +6,7 @@ import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsAssets; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.reports.reports.bt_12_2.ReportPA_B; import ru.spcex.clearing.reports.services.ReportWithPeriodCollector; -import ru.spcex.platform.enumeration.ClearingMemberCategoryD; +import ru.spcex.platform.enumeration.ClearingCategory; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; @@ -41,7 +41,7 @@ public class ReportPA_B_Collector extends ReportWithPeriodCollector Collection clearingMemberCategories = clearingMemberCategoryImdg.getCollectionObjectsByFieldValues(Map.of( - "clearingMemberCategory", ClearingMemberCategoryD.B.getKey() + "clearingMemberCategory", ClearingCategory.B.getKey() )); Set companyIds = clearingMemberCategories.stream() .map(ClearingMemberCategory::getCompanyId) diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportPA_IV_Collector.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportPA_IV_Collector.java index 627508028..c7bef06e6 100644 --- a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportPA_IV_Collector.java +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportPA_IV_Collector.java @@ -7,7 +7,7 @@ import ru.clearing.platform.dictionary.ClearingStatusDictionary; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.reports.reports.bt_12_2.ReportPA_IV; import ru.spcex.clearing.reports.services.ReportWithPeriodCollector; -import ru.spcex.platform.enumeration.ClearingMemberCategoryD; +import ru.spcex.platform.enumeration.ClearingCategory; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; @@ -45,7 +45,7 @@ public class ReportPA_IV_Collector extends ReportWithPeriodCollector clearingMemberCategories = clearingMemberCategoryImdg.getCollectionObjectsBySQL(clearingMemberCategorySql); diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/ClearingMemberCategoryD.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/MoneyFlowSide.java similarity index 64% rename from platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/ClearingMemberCategoryD.java rename to platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/MoneyFlowSide.java index 883769de0..1b1111295 100644 --- a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/ClearingMemberCategoryD.java +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/MoneyFlowSide.java @@ -2,12 +2,14 @@ package ru.spcex.platform.enumeration; import ru.spcex.platform.utils.enumeration.IEnumKey; -public enum ClearingMemberCategoryD implements IEnumKey { - I("I"), V("V"), B("B"); +public enum MoneyFlowSide implements IEnumKey { + BUY("BUY"), + SELL("SELL"), + ; private final String key; - ClearingMemberCategoryD(String key) { + MoneyFlowSide(String key) { this.key = key; } From 06f53ad40d0344ca0d50739dda1500111f640ea5 Mon Sep 17 00:00:00 2001 From: AKurakin Date: Tue, 31 Jan 2023 16:16:55 +0300 Subject: [PATCH 04/42] =?UTF-8?q?scheduler-service=20=D0=BE=D1=82=D0=BF?= =?UTF-8?q?=D1=80=D0=B0=D0=B2=D0=BA=D0=B0=20=D0=BA=D0=BE=D0=BC=D0=B0=D0=BD?= =?UTF-8?q?=D0=B4=20=D0=B2=20=D0=BE=D1=87=D0=B5=D1=80=D0=B5=D0=B4=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BE=20=D1=80=D0=B0=D1=81=D0=BF=D0=B8=D1=81=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D1=8E=20-=20=D1=80=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D0=BD=D0=B3=20=D0=BA=D0=BE=D0=BC=D0=B0=D0=BD=D0=B4?= =?UTF-8?q?=D1=8B=20=D0=B7=D0=B0=D0=BF=D1=83=D1=81=D0=BA=D0=B0=20(=D1=81?= =?UTF-8?q?=D1=82=D0=B0=D0=BD=D0=B4=D0=B0=D1=80=D1=82=D0=B8=D0=B7=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../request/cud/schedule/LauncherNew.java | 19 ++++------- .../reports/services/QCommandExecutor.java | 33 ++++++++++--------- .../scheduler/service/LauncherSender.java | 15 +++------ .../platform/messaging/domain/Consts.java | 1 + 4 files changed, 29 insertions(+), 39 deletions(-) diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/schedule/LauncherNew.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/schedule/LauncherNew.java index 31ceac638..f5bfe7497 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/schedule/LauncherNew.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/schedule/LauncherNew.java @@ -6,7 +6,6 @@ import io.swagger.annotations.ApiModelProperty; import ru.spcex.clearing.backendapi.domain.actions.IAction; import ru.spcex.clearing.backendapi.errors.BackEndError; import ru.spcex.clearing.platform.messaging.domain.ActionType; -import ru.spcex.clearing.platform.messaging.domain.cud.reports.ReportWithPeriodRequest; import ru.spcex.clearing.platform.messaging.domain.cud.schedule.LauncherCommandRequest; import ru.spcex.platform.enumeration.Task; import ru.spcex.platform.utils.enumeration.EnumMessage; @@ -31,18 +30,12 @@ public class LauncherNew implements IAction { @Override public Object toRequest() { - if (Task.createReport_GREP.equalsByKey(task)) { - ReportWithPeriodRequest reportCommand = new ReportWithPeriodRequest(); - reportCommand.setReportId(task); - return reportCommand; - } else { - LauncherCommandRequest taskRunnerCommandRequest = new LauncherCommandRequest(); - taskRunnerCommandRequest.setTaskName(task); - taskRunnerCommandRequest.setCompanyId(companyId); - taskRunnerCommandRequest.setSecurityId(securityId); - taskRunnerCommandRequest.setUserId(userId); - return taskRunnerCommandRequest; - } + LauncherCommandRequest taskRunnerCommandRequest = new LauncherCommandRequest(); + taskRunnerCommandRequest.setTaskName(task); + taskRunnerCommandRequest.setCompanyId(companyId); + taskRunnerCommandRequest.setSecurityId(securityId); + taskRunnerCommandRequest.setUserId(userId); + return taskRunnerCommandRequest; } @Override diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/QCommandExecutor.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/QCommandExecutor.java index 021bbc884..95436a786 100644 --- a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/QCommandExecutor.java +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/QCommandExecutor.java @@ -8,7 +8,7 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import ru.spcex.clearing.platform.messaging.domain.BaseRequest; -import ru.spcex.clearing.platform.messaging.domain.cud.reports.ReportWithPeriodRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.schedule.LauncherCommandRequest; import ru.spcex.clearing.platform.messaging.service.QueueConsumer; import ru.spcex.clearing.reports.config.element.ReportsServiceSettings; import ru.spcex.platform.enumeration.Task; @@ -40,20 +40,23 @@ public class QCommandExecutor extends QueueConsumer implements InitializingBean @Override public void afterPropertiesSet() { log.info("Init queue listener {}", getClass().getSimpleName()); - callback(ReportWithPeriodRequest.class) + callback(LauncherCommandRequest.class) .setConsumer(this::newReportWithPeriod) .forDestination(Task.createReport_GREP.topic(), callbacks::put); init(); } - private void newReportWithPeriod(BaseRequest reportRequest) { - ReportWithPeriodRequest request = reportRequest.getRequestPayload(); + private void newReportWithPeriod(BaseRequest reportRequest) { + LauncherCommandRequest request = reportRequest.getRequestPayload(); log.info("newReportWithPeriod request received: {}", request); + final String taskName = QUEUE_RUN_REPORT_COMMAND; //request.getTaskName(); - if (StringUtils.isBlank(request.getReportId())) - throw new IllegalStateException("ReportID is empty"); - LocalDate startDate = request.getStartDate(); - LocalDate endDate = request.getEndDate(); +// if (StringUtils.isBlank(request.getReportId())) +// throw new IllegalStateException("ReportID is empty"); +// LocalDate startDate = request.getStartDate(); +// LocalDate endDate = request.getEndDate(); + LocalDate startDate = null; + LocalDate endDate = null; if (startDate == null && endDate == null) { endDate = LocalDate.now(); startDate = LocalDate.of(endDate.getYear(), endDate.getMonth(), 1); @@ -65,18 +68,18 @@ public class QCommandExecutor extends QueueConsumer implements InitializingBean throw new IllegalStateException("StartDate > EndDate"); try { - if (QUEUE_RUN_REPORT_COMMAND.equals(request.getReportId()) - || QUEUE_RUN_DAILY_REPORT_COMMAND.equals(request.getReportId())) { - log.info("Generate all report by command {}", request.getReportId()); - reportsServiceCommand.generateReportAll(request.getReportId(), startDate, endDate); + if (QUEUE_RUN_REPORT_COMMAND.equals(taskName) + || QUEUE_RUN_DAILY_REPORT_COMMAND.equals(taskName)) { + log.info("Generate all report by command {}", taskName); + reportsServiceCommand.generateReportAll(taskName, startDate, endDate); } else { - log.info("Generate single report by command {}", request.getReportId()); - reportsServiceCommand.generateReportById(request.getReportId(), startDate, endDate); + log.info("Generate single report by command {}", taskName); + reportsServiceCommand.generateReportById(taskName, startDate, endDate); } log.debug("successfully processed"); } catch (IOException e) { - log.error("Error create report {}: {}", request.getReportId(), ExceptionUtils.getStackTrace(e)); + log.error("Error create report {}: {}", taskName, ExceptionUtils.getStackTrace(e)); } } diff --git a/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/LauncherSender.java b/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/LauncherSender.java index bbf98c9d5..0f7d385ee 100644 --- a/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/LauncherSender.java +++ b/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/LauncherSender.java @@ -10,7 +10,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import ru.spcex.clearing.platform.messaging.domain.ActionType; import ru.spcex.clearing.platform.messaging.domain.BaseRequest; -import ru.spcex.clearing.platform.messaging.domain.cud.reports.ReportWithPeriodRequest; import ru.spcex.clearing.platform.messaging.domain.cud.schedule.LauncherCommandRequest; import ru.spcex.platform.enumeration.Task; import ru.spcex.platform.imdg.api.ImdgId; @@ -33,16 +32,10 @@ public class LauncherSender { protected BaseRequest makeCmdRequest(Task byTask, Long userId) { Object toRequest; - if (Task.createReport_GREP.equals(byTask)) { // см. ru.spcex.clearing.backendapi.controller.request.cud.schedule.LauncherNew#toRequest - ReportWithPeriodRequest reportCommand = new ReportWithPeriodRequest(); - reportCommand.setReportId(byTask.getKey()); - toRequest = reportCommand; - } else { - LauncherCommandRequest taskRunnerCommandRequest = new LauncherCommandRequest(); - taskRunnerCommandRequest.setTaskName(byTask.getKey()); - taskRunnerCommandRequest.setUserId(userId); - toRequest = taskRunnerCommandRequest; - } + LauncherCommandRequest taskRunnerCommandRequest = new LauncherCommandRequest(); + taskRunnerCommandRequest.setTaskName(byTask.getKey()); + taskRunnerCommandRequest.setUserId(userId); + toRequest = taskRunnerCommandRequest; BaseRequest request = new BaseRequest<>(); request.setId(idGenerator.nextId()); request.setActionType(ActionType.NEW); 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 b4132fa0a..552594f41 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 @@ -57,6 +57,7 @@ public interface Consts { String REGISTRY_COVERED_DEAL_REGISTER_NEW = "registry-covered-deal-register-new"; String REGISTRY_ADMITTED_DEAL_REGISTER_NEW = "registry-admitted-deal-register-new"; + String REGISTRY_DEAL_REGISTER_NEW = "registry-deal-register-new"; String REGISTRY_ORDER_REGISTER_NEW = "registry-order-register-new"; String REGISTRY_CONTRACT_REGISTER_NEW = "registry-contract-register-new"; From 2c7a9934feaeaa5006ed1c6d38a8e28906599048 Mon Sep 17 00:00:00 2001 From: AKurakin Date: Tue, 31 Jan 2023 16:19:12 +0300 Subject: [PATCH 05/42] =?UTF-8?q?clearing-service=20http://jira.mfd.msk:80?= =?UTF-8?q?88/browse/CLS-188=20=D1=87=D0=B0=D1=81=D1=82=D1=8C=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=B4=D0=B5=D0=BB=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/ExecutionDepositComponent.java | 31 +++------ .../src/main/resources/application.properties | 2 +- .../cud/registry/DealRegisterNewRequest.java | 67 +++++++++++++++++++ 3 files changed, 78 insertions(+), 22 deletions(-) create mode 100644 platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/registry/DealRegisterNewRequest.java diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecutionDepositComponent.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecutionDepositComponent.java index bbe554b3a..761141c85 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecutionDepositComponent.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecutionDepositComponent.java @@ -21,7 +21,7 @@ import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.ActionType; import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.Consts; -import ru.spcex.clearing.platform.messaging.domain.cud.registry.CoveredDealRegisterNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.registry.DealRegisterNewRequest; import ru.spcex.clearing.platform.messaging.domain.cud.securitites.MoneyMarketSecurityNewRequest; import ru.spcex.platform.enumeration.Allowed; import ru.spcex.platform.enumeration.Market; @@ -85,8 +85,9 @@ public class ExecutionDepositComponent { /** * Сбрасывать каждый день в 01:00:01 "0 1 0 1 * ?" */ - @Scheduled(cron = "${clearing-service.scheduler.check-s-trade}") + @Scheduled(cron = "0 1 0 1 * ?") public void resetTradingDay() { + log.trace("Recheck today trading day for search STrade. Current state: tradeNum={}, tradeDat={}", tradeNum, tradingDay); Instant today = TimeUtil.localDateToInstant(LocalDate.now()); if (tradingDay == null || !tradingDay.equals(today)) { tradeNum = -1L; @@ -95,8 +96,9 @@ public class ExecutionDepositComponent { log.info("Reset trading day for search STrade: tradeNum={}, tradeDat={}", tradeNum, tradingDay); } + @Scheduled(cron = "${clearing-service.scheduler.check-s-trade}") public void processNewTS() { - Long tradeNum = -1L; // todo уточнить как он обновляется + log.debug("Start check new S_TRADE. Start tradeNum={}", tradeNum); ImdgPredicateBuilder pb = sTradeImdg.predicateBuilder(); ImdgPredicate sql = pb.and(pb.greater("tradeNum", tradeNum), pb.greatEqual("tradeDateTime", tradingDay)); Collection sTrades = sTradeImdg.getCollectionObjectsByPredicate(sql); @@ -166,7 +168,7 @@ public class ExecutionDepositComponent { Long newMaxTradeNum = sTrades.stream().mapToLong(STrade::getTradeNum).max().orElseGet(() -> tradeNum); - log.debug("Next tradeNum is {}", newMaxTradeNum); + log.info("Process completed. Next tradeNum is {}", newMaxTradeNum); } protected void verification(ExecutionDeposit forED) throws ClearingException { @@ -236,26 +238,13 @@ public class ExecutionDepositComponent { } protected void sendNotification(ExecutionDeposit forED) { - final String destination = Consts.REGISTRY_COVERED_DEAL_REGISTER_NEW; - CoveredDealRegisterNewRequest requestPayload = new CoveredDealRegisterNewRequest(); + final String destination = Consts.REGISTRY_DEAL_REGISTER_NEW; + DealRegisterNewRequest requestPayload = new DealRegisterNewRequest(); requestPayload.setExecutionId(forED.getId()); -// requestPayload.setCompanyFullName(forED.getCompanyFullName()); - requestPayload.setTradingDate(forED.getTradingDate()); + requestPayload.setClearingDate(forED.getClearingDate()); requestPayload.setExchangeExecutionId(forED.getExchangeExecutionId()); requestPayload.setExchangeExecutionTime(forED.getExchangeExecutionTime()); - requestPayload.setSecuritySymbol(forED.getSecuritySymbol()); - requestPayload.setSecurityFullName(forED.getSecurityFullName()); -// requestPayload.setSellerFullName(forED.getSellerFullName()); -// requestPayload.setSellerClearingCode(forED.getSellerClearingCode()); -// String requestPayload.setSellerAccount(forED.getAccountId()); -// String requestPayload.setBuyerFullName(forED.getBuyerFullName()); -// requestPayload.setBuyerClearingCode(forED.getBuyerClearingCode()); -// String requestPayload.setBuyerAccount(forED.getBuyerAccount()); -// BigDecimal requestPayload.setAmount(forED.getAmount()); - requestPayload.setId(idGenerator.nextId()); - requestPayload.setCreatedAt(forED.getCreated()); - requestPayload.setUpdatedAt(forED.getUpdated()); - requestPayload.setClearingDate(forED.getClearingDate()); +// requestPayload.setId(idGenerator.nextId()); BaseRequest request = new BaseRequest<>(); request.setId(idGenerator.nextId()); diff --git a/clearing-parent/clearing-service/src/main/resources/application.properties b/clearing-parent/clearing-service/src/main/resources/application.properties index e0908f94a..bb4e61e6b 100644 --- a/clearing-parent/clearing-service/src/main/resources/application.properties +++ b/clearing-parent/clearing-service/src/main/resources/application.properties @@ -20,4 +20,4 @@ clearing-service.kafka-producer.linger-ms=1 clearing-service.kafka-producer.buffer-memory=33554432 clearing-service.scheduler.check-payment-instruction=*/5 * * * * * -clearing-service.scheduler.check-s-trade=0 1 0 1 * ? +clearing-service.scheduler.check-s-trade=0 * 0 1 * ? diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/registry/DealRegisterNewRequest.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/registry/DealRegisterNewRequest.java new file mode 100644 index 000000000..c9edf8b55 --- /dev/null +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/registry/DealRegisterNewRequest.java @@ -0,0 +1,67 @@ +package ru.spcex.clearing.platform.messaging.domain.cud.registry; + + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.math.BigDecimal; +import java.time.Instant; +import java.time.LocalDate; + +public class DealRegisterNewRequest { + + @JsonProperty + public Long executionId; + + @JsonProperty + public Long exchangeExecutionId; + + @JsonProperty + public Instant exchangeExecutionTime; + + @JsonProperty + public Long id; + + @JsonProperty + public LocalDate clearingDate; + + + public Long getExecutionId() { + return executionId; + } + + public void setExecutionId(Long executionId) { + this.executionId = executionId; + } + + public Long getExchangeExecutionId() { + return exchangeExecutionId; + } + + public void setExchangeExecutionId(Long exchangeExecutionId) { + this.exchangeExecutionId = exchangeExecutionId; + } + + public Instant getExchangeExecutionTime() { + return exchangeExecutionTime; + } + + public void setExchangeExecutionTime(Instant exchangeExecutionTime) { + this.exchangeExecutionTime = exchangeExecutionTime; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public LocalDate getClearingDate() { + return clearingDate; + } + + public void setClearingDate(LocalDate clearingDate) { + this.clearingDate = clearingDate; + } +} From 7dd06fcc5166299681dd1e16d26a7db60eb30d85 Mon Sep 17 00:00:00 2001 From: AKurakin Date: Tue, 31 Jan 2023 16:50:13 +0300 Subject: [PATCH 06/42] =?UTF-8?q?scheduler-service=20=D0=BE=D1=82=D0=BF?= =?UTF-8?q?=D1=80=D0=B0=D0=B2=D0=BA=D0=B0=20=D0=BA=D0=BE=D0=BC=D0=B0=D0=BD?= =?UTF-8?q?=D0=B4=20=D0=B2=20=D0=BE=D1=87=D0=B5=D1=80=D0=B5=D0=B4=D0=B8=20?= =?UTF-8?q?-=20=D0=BF=D0=BE=D0=BF=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=BE?= =?UTF-8?q?=D0=B1=D1=91=D1=80=D1=82=D0=BA=D1=83=20launch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ru/spcex/clearing/scheduler/service/LauncherService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/LauncherService.java b/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/LauncherService.java index 7f9e2f44f..aa869d0d4 100644 --- a/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/LauncherService.java +++ b/clearing-parent/scheduler-service/src/main/java/ru/spcex/clearing/scheduler/service/LauncherService.java @@ -58,7 +58,7 @@ public class LauncherService extends QueueConsumer implements InitializingBean { launcher.setUpdated(created); launcherMap.insert(launcher); log.debug("successfully processed, new id {}", launcher.getId()); - kafkaProducer.send(new ProducerRecord<>("launcher-" + launcher.getTask(), req)); + kafkaProducer.send(new ProducerRecord<>("launcher-" + launcher.getTask(), userRequest)); } } From 503710f19b088f45f4af87124ae0f1c902f3e9fb Mon Sep 17 00:00:00 2001 From: AKurakin Date: Tue, 31 Jan 2023 17:05:01 +0300 Subject: [PATCH 07/42] =?UTF-8?q?reports-service=20=D0=BF=D0=BE=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D1=8F=D0=BB=D0=B8=20=D1=82=D0=B8=D0=BF=D1=8B=20?= =?UTF-8?q?=D0=B2=20LiabilitiesClaimsAssets.refundDate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reports/services/ReportWithPeriodCollector.java | 12 ++++++------ .../collector/ReportBR_0420314_P2_Collector.java | 2 +- .../collector/ReportBR_0420317_Collector.java | 2 +- .../services/collector/ReportPA_B_Collector.java | 4 ++-- .../services/collector/ReportPA_IV_Collector.java | 4 ++-- .../services/AbstractReportCollectorTest.java | 8 ++++---- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/ReportWithPeriodCollector.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/ReportWithPeriodCollector.java index e7687ed87..b11179d01 100644 --- a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/ReportWithPeriodCollector.java +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/ReportWithPeriodCollector.java @@ -20,9 +20,9 @@ public abstract class ReportWithPeriodCollector extend LocalDate startDate, LocalDate endDate) { ImdgPredicateBuilder pb = liabilitiesClaimsAssetsImdg.predicateBuilder(); - Instant dateTimeLo = toInstantStartDay(startDate); - Instant dateTimeHi = toInstantStartDay(endDate); - ImdgPredicate p = pb.and(pb.greatEqual("refundDate", dateTimeLo), pb.lessEqual("refundDate", dateTimeHi)); +// Instant dateTimeLo = toInstantStartDay(startDate); +// Instant dateTimeHi = toInstantEndDay(endDate); + ImdgPredicate p = pb.and(pb.greatEqual("refundDate", startDate), pb.lessEqual("refundDate", endDate)); Collection liabilities = liabilitiesClaimsAssetsImdg.getCollectionObjectsByPredicate(p); return liabilities; } @@ -31,9 +31,9 @@ public abstract class ReportWithPeriodCollector extend LocalDate startDate, LocalDate endDate, Long allowClearingStatusId) { ImdgPredicateBuilder pb = liabilitiesClaimsAssetsImdg.predicateBuilder(); - Instant dateTimeLo = toInstantStartDay(startDate); - Instant dateTimeHi = toInstantStartDay(endDate); - ImdgPredicate p = pb.and(pb.greatEqual("refundDate", dateTimeLo), pb.lessEqual("refundDate", dateTimeHi), +// Instant dateTimeLo = toInstantStartDay(startDate); +// Instant dateTimeHi = toInstantEndDay(endDate); + ImdgPredicate p = pb.and(pb.greatEqual("refundDate", startDate), pb.lessEqual("refundDate", endDate), pb.equals("clearingStatus", allowClearingStatusId)); Collection liabilities = liabilitiesClaimsAssetsImdg.getCollectionObjectsByPredicate(p); return liabilities; diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportBR_0420314_P2_Collector.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportBR_0420314_P2_Collector.java index 46bacd498..367d11525 100644 --- a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportBR_0420314_P2_Collector.java +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportBR_0420314_P2_Collector.java @@ -45,7 +45,7 @@ public class ReportBR_0420314_P2_Collector extends ReportWithPeriodCollector searchPaymentInstruction(LocalDate startDate, LocalDate endDate) { ImdgPredicateBuilder pb = paymentInstructionImdg.predicateBuilder(); Instant dateTimeLo = toInstantStartDay(startDate); - Instant dateTimeHi = toInstantStartDay(endDate); + Instant dateTimeHi = toInstantEndDay(endDate); ImdgPredicate p = pb.and(pb.greatEqual("created", dateTimeLo), pb.lessEqual("created", dateTimeHi)); Collection paymentInstructionsAll = paymentInstructionImdg.getCollectionObjectsByPredicate(p); return paymentInstructionsAll; diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportBR_0420317_Collector.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportBR_0420317_Collector.java index 8699ec969..c0d7748b0 100644 --- a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportBR_0420317_Collector.java +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportBR_0420317_Collector.java @@ -35,7 +35,7 @@ public class ReportBR_0420317_Collector extends ReportWithPeriodCollector searchRelation(LocalDate startDate, LocalDate endDate, String service) { ImdgPredicateBuilder pb = relationImdg.predicateBuilder(); Instant dateTimeLo = toInstantStartDay(startDate); - Instant dateTimeHi = toInstantStartDay(endDate); + Instant dateTimeHi = toInstantEndDay(endDate); ImdgPredicate p = pb.and(pb.greatEqual("updated", dateTimeLo), pb.lessEqual("updated", dateTimeHi), pb.equals("service", service)); Collection relations = relationImdg.getCollectionObjectsByPredicate(p); diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportPA_B_Collector.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportPA_B_Collector.java index 8f6fe2bc4..bc373378d 100644 --- a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportPA_B_Collector.java +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportPA_B_Collector.java @@ -49,8 +49,8 @@ public class ReportPA_B_Collector extends ReportWithPeriodCollector ImdgPredicateBuilder builder = liabilitiesClaimsAssetsImdg.predicateBuilder(); ImdgPredicate refundDatePredicate = builder.and( - builder.greatEqual("refundDate", toInstantStartDay(startDate)), - builder.lessEqual("refundDate", toInstantStartDay(endDate)) + builder.greatEqual("refundDate", (startDate)), + builder.lessEqual("refundDate", (endDate)) ); ImdgPredicate companyIdPredicates = builder.in("companyId", companyIds.toArray(new Comparable[0])); ImdgPredicate finalPredicate = builder.and(refundDatePredicate, companyIdPredicates); diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportPA_IV_Collector.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportPA_IV_Collector.java index c7bef06e6..159b72c32 100644 --- a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportPA_IV_Collector.java +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/collector/ReportPA_IV_Collector.java @@ -55,8 +55,8 @@ public class ReportPA_IV_Collector extends ReportWithPeriodCollector Date: Tue, 31 Jan 2023 20:09:27 +0300 Subject: [PATCH 08/42] http://jira.mfd.msk:8088/browse/CLS-189 --- .../clearing/config/ValidationConfig.java | 61 +++++++++++++ .../clearing/error/ClearingErrorInternal.java | 21 +++++ .../ru/spcex/clearing/service/Clearing.java | 47 +++++++++- .../validation/ClrngValidationStored.java | 6 ++ .../ExecutionDepositValidationRule.java | 89 +++++++++++++++++++ 5 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingErrorInternal.java create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ClrngValidationStored.java create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ExecutionDepositValidationRule.java 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 new file mode 100644 index 000000000..f4eb7ac72 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java @@ -0,0 +1,61 @@ +package ru.spcex.clearing.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import ru.clearing.classes.statics.data.company.Company; +import ru.clearing.classes.statics.data.company.relation.Relation; +import ru.clearing.classes.statics.data.execution.ExecutionDeposit; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.service.validation.ClrngValidationStored; +import ru.spcex.clearing.service.validation.ExecutionDepositValidationRule; +import ru.spcex.platform.classes.base.SpcexObjectBase; +import ru.spcex.platform.enumeration.ClearingCategory; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.validation.ImdgValidationContext; +import ru.spcex.platform.utils.validation.IValidator; +import ru.spcex.platform.utils.validation.ValidatorImpl; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; + +@Configuration +public class ValidationConfig { + private final Map> imdgs; + + public ValidationConfig(ImdgProvider imdgProvider) { + this.imdgs = new HashMap<>(); + BiConsumer> addImdg = (s, aClass) -> imdgs.put(s, imdgProvider.getImdg(s, aClass)); + addImdg.accept(IMDGDistributedNames.Map_Relation, Relation.class); + addImdg.accept(IMDGDistributedNames.Map_Company, Company.class); + } + + /** + * чтобы во всех валидаторах был один экземпляр Imdg + */ + private Imdg getImdg(String key) { + return imdgs.get(key); + } + + private final BiConsumer, String> addImdg = (context, s) + -> context.addImdg(s, getImdg(s)); + + @Bean("executionDepositValidator") + public BiFunction executionDepositValidator() { + return (category, execDeposit) -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(execDeposit); + context.storeObject(ClrngValidationStored.categoryPredefined, category); + addImdg.accept(context, IMDGDistributedNames.Map_Relation); + addImdg.accept(context, IMDGDistributedNames.Map_Company); + return new ValidatorImpl<>(context, + ExecutionDepositValidationRule.ClearingIsAllowed, + ExecutionDepositValidationRule.AccountIsNotBlocked, + ExecutionDepositValidationRule.CompanyIsNotBlocked, + ExecutionDepositValidationRule.FinancialObligationSecurity); + }; + } + +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingErrorInternal.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingErrorInternal.java new file mode 100644 index 000000000..dfeee61f9 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingErrorInternal.java @@ -0,0 +1,21 @@ +package ru.spcex.clearing.error; + +import ru.spcex.platform.utils.enumeration.IEnumId; + +public enum ClearingErrorInternal implements IEnumId { + ClearingNotAllowed(1L), + AccountNotActive(2L), + CompanyNotActive(3L), + FinancialObligationNotSatisfied(4L), + ; + private final Long id; + + ClearingErrorInternal(Long id) { + this.id = id; + } + + @Override + public Long getId() { + return id; + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java index 90a4bf630..c46e73787 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java @@ -1,30 +1,44 @@ package ru.spcex.clearing.service; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.execution.ExecutionDeposit; import ru.clearing.classes.statics.data.generated.ClearingMemberCategory; +import ru.spcex.clearing.error.ClearingErrorInternal; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.service.order.ExecutionDepositSorter; +import ru.spcex.platform.enumeration.Allowed; import ru.spcex.platform.enumeration.ClearingCategory; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.utils.enumeration.EnumMessage; +import ru.spcex.platform.utils.validation.IValidator; +import java.time.Instant; import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; +import java.util.Optional; +import java.util.function.BiFunction; @Service public class Clearing { + private final Logger log = LoggerFactory.getLogger(getClass()); private final Imdg executionDepositImdg; private final Imdg clearingCategoryImdg; private final ExecutionDepositSorter sorter; + private final BiFunction validation; @Autowired - public Clearing(ImdgProvider imdgProvider, ExecutionDepositSorter sorter) { + public Clearing(ImdgProvider imdgProvider, + ExecutionDepositSorter sorter, + BiFunction validation) { this.executionDepositImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionDeposit, ExecutionDeposit.class); this.clearingCategoryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class); this.sorter = sorter; + this.validation = validation; } public void startClearing() { @@ -41,6 +55,37 @@ public class Clearing { } private void processSingleCompany(ClearingCategory category, List executionDeposits) { + log.info("Start clearing for category: {}, company: {}", category, executionDeposits.get(0).getCompanyId()); + boolean financialError = false; + for (ExecDepositWCategory execDepositWrapper : executionDeposits) { + ExecutionDeposit execDeposit = execDepositWrapper.getExecutionDeposit(); + if (financialError) { + updateDenied(execDeposit); + continue; + } + IValidator validator = validation.apply(category, execDeposit); + Optional errorMsg = validator.tillFirstError(); + if (errorMsg.isPresent() && !ClearingErrorInternal.FinancialObligationNotSatisfied.equals(errorMsg.get().getSubject())) { + updateDenied(execDeposit); + continue; + } else if (errorMsg.isPresent()) { + financialError = true; + updateDenied(execDeposit); + continue; + } + updateAllowed(execDeposit); + } + } + private void updateDenied(ExecutionDeposit execDeposit) { + execDeposit.setCoverageStatus(Allowed.DENIED.getKey()); + execDeposit.setUpdated(Instant.now()); + executionDepositImdg.update(execDeposit); + } + + private void updateAllowed(ExecutionDeposit execDeposit) { + execDeposit.setCoverageStatus(Allowed.ALLOWED.getKey()); + execDeposit.setUpdated(Instant.now()); + executionDepositImdg.update(execDeposit); } } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ClrngValidationStored.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ClrngValidationStored.java new file mode 100644 index 000000000..27bbb5eec --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ClrngValidationStored.java @@ -0,0 +1,6 @@ +package ru.spcex.clearing.service.validation; + +public enum ClrngValidationStored { + relation, categoryPredefined + ; +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ExecutionDepositValidationRule.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ExecutionDepositValidationRule.java new file mode 100644 index 000000000..b2eaeb6da --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ExecutionDepositValidationRule.java @@ -0,0 +1,89 @@ +package ru.spcex.clearing.service.validation; + +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.relation.Relation; +import ru.clearing.classes.statics.data.execution.ExecutionDeposit; +import ru.spcex.clearing.error.ClearingErrorInternal; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.platform.enumeration.AccountStatus; +import ru.spcex.platform.enumeration.ClearingCategory; +import ru.spcex.platform.enumeration.ServiceStatus; +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; +import ru.spcex.platform.utils.validation.IValidationRule; + +import java.util.Map; +import java.util.Optional; + +public enum ExecutionDepositValidationRule implements IValidationRule> { + ClearingIsAllowed() { + @Override + public Optional validate(ImdgValidationContext context) { + ExecutionDeposit validatedObject = context.getValidatedObject(); + Imdg relationImdg = context.obtainMap(IMDGDistributedNames.Map_Relation, Relation.class); + Relation relation = relationImdg.getSingleObjectByFieldValues(Map.of("consumerId", validatedObject.getCompanyId())); + if (relation == null || !ServiceStatus.Active.equalsByKey(relation.getServiceStatus())) { + return of(ClearingErrorInternal.ClearingNotAllowed); + } + context.storeObject(ClrngValidationStored.relation, relation); + return empty(); + } + }, + AccountIsNotBlocked() { + @Override + public Optional validate(ImdgValidationContext context) { + ExecutionDeposit validatedObject = context.getValidatedObject(); + Imdg accountImdg = context.obtainMap(IMDGDistributedNames.Map_Account, Account.class); + Relation relation = context.getStoredObject(ClrngValidationStored.relation); + Account account = accountImdg.getSingleObjectByFieldValues( + Map.of("id", validatedObject.getAccountId(), "relationId", relation.getId())); + if (account == null || !AccountStatus.ACTIVE.equalsByKey(account.getAccountStatus())) { + return of(ClearingErrorInternal.AccountNotActive); + } + return empty(); + } + }, + CompanyIsNotBlocked() { + @Override + public Optional validate(ImdgValidationContext context) { + ExecutionDeposit validatedObject = context.getValidatedObject(); + Imdg companyImdg = context.obtainMap(IMDGDistributedNames.Map_Company, Company.class); + Company company = companyImdg.getSingleObjectByFieldValues(Map.of("id", validatedObject.getCompanyId())); + if (company == null || !WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus())) { + return of(ClearingErrorInternal.CompanyNotActive); + } + return empty(); + } + }, + FinancialObligationSecurity() { + @Override + public Optional validate(ImdgValidationContext context) { + ClearingCategory category = context.getStoredObject(ClrngValidationStored.categoryPredefined); + if (!category.equals(ClearingCategory.V)) { + return Optional.empty(); + } + ExecutionDeposit validatedObject = context.getValidatedObject(); + Imdg accountBalanceImdg = context.obtainMap(IMDGDistributedNames.Map_AccountBalance, AccountBalance.class); + AccountBalance accountBalance = accountBalanceImdg.getSingleObjectByFieldValues( + Map.of("accountId", validatedObject.getAccountId(), + "companyId", validatedObject.getCompanyId())); + if (accountBalance == null) { + return of(ClearingErrorInternal.FinancialObligationNotSatisfied); + } + //todo ABS + if (validatedObject.getFirstLegAmount().compareTo(accountBalance.getFreeBalanceAmount()) > 0) { + return of(ClearingErrorInternal.FinancialObligationNotSatisfied); + } + return empty(); + } + }; + + @Override + public String ruleName() { + return "Sdf09ValidationRule." + name(); + } +} \ No newline at end of file From 196ec996dff11514e50a692a572a2b6dac07a9ee Mon Sep 17 00:00:00 2001 From: ialbert Date: Wed, 1 Feb 2023 11:10:30 +0300 Subject: [PATCH 09/42] http://jira.mfd.msk:8088/browse/CLS-189 --- .../platform/enumeration/ServiceStatus.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/ServiceStatus.java diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/ServiceStatus.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/ServiceStatus.java new file mode 100644 index 000000000..000fe9999 --- /dev/null +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/ServiceStatus.java @@ -0,0 +1,23 @@ +package ru.spcex.platform.enumeration; + +import ru.spcex.platform.utils.enumeration.IEnumKey; + +public enum ServiceStatus implements IEnumKey { + Active("ACTV"), + Blocked("BLKD"), + Suspended("SSPD"), + Closed("CLOS"), + Reopened("ROPN"), +; + + private final String key; + + ServiceStatus(String key) { + this.key = key; + } + + @Override + public String getKey() { + return key; + } +} From 1f0904227146ffb8be2fc7ab42acc97ffe56b1a6 Mon Sep 17 00:00:00 2001 From: AKurakin Date: Wed, 1 Feb 2023 11:15:31 +0300 Subject: [PATCH 10/42] =?UTF-8?q?clearing-service=20http://jira.mfd.msk:80?= =?UTF-8?q?88/browse/CLS-188=20=D0=B4=D0=BE=D0=B4=D0=B5=D0=BB=D0=BA=D0=B8?= =?UTF-8?q?=20=D0=BF=D0=BE=20=D0=BD=D0=BE=D0=B2=D0=BE=D0=BC=D1=83=20=D0=A2?= =?UTF-8?q?=D0=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../clearing/service/ClearingService.java | 17 +++- .../clearing/service/EventsReceiver.java | 3 + .../service/ExecutionDepositComponent.java | 92 ++++--------------- .../src/main/resources/application.properties | 1 - .../imdg/object/ExecutionDepositMapStore.java | 4 + 5 files changed, 42 insertions(+), 75 deletions(-) diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ClearingService.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ClearingService.java index 7213ef7f6..18079d147 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ClearingService.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ClearingService.java @@ -20,13 +20,16 @@ public class ClearingService implements DisposableBean { private final PaymentUpdateBySdf04 paymentUpdater; private final VerificationResultComponent verificationResultComponent; private final Clearing clearing; + private final ExecutionDepositComponent executionDepositComponent; @Autowired public ClearingService(SdfCreatorBySTLDPayment sdfCreator, PaymentUpdateBySdf04 paymentUpdater, - VerificationResultComponent verificationResultComponent, Clearing clearing) { + VerificationResultComponent verificationResultComponent, Clearing clearing, + ExecutionDepositComponent executionDepositComponent) { this.sdfCreator = sdfCreator; this.paymentUpdater = paymentUpdater; this.verificationResultComponent = verificationResultComponent; + this.executionDepositComponent = executionDepositComponent; this.clearing = clearing; this.executor = Executors.newSingleThreadExecutor(); } @@ -81,4 +84,16 @@ public class ClearingService implements DisposableBean { } }); } + + public void executeSTrade() { + log.info("start STrade check for ExecutionDeposit"); + executor.execute(() -> { + try { + executionDepositComponent.processNewTS(); + } catch (Throwable e) { + log.error("{}", ExceptionUtils.getStackTrace(e)); + } + }); + } + } 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 76e0aba39..66b6c8f47 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 @@ -34,6 +34,9 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean { callback(Object.class) //todo check Object suitable .setConsumer(event -> clearingService.executeClearing()) .forDestination(Task.startOfClearing.topic(), callbacks::put); + callback(Object.class) + .setConsumer(event -> clearingService.executeSTrade()) + .forDestination(Task.getOfTrades.topic(), callbacks::put); init(); } } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecutionDepositComponent.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecutionDepositComponent.java index 761141c85..27daaef00 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecutionDepositComponent.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecutionDepositComponent.java @@ -23,6 +23,7 @@ import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.Consts; import ru.spcex.clearing.platform.messaging.domain.cud.registry.DealRegisterNewRequest; import ru.spcex.clearing.platform.messaging.domain.cud.securitites.MoneyMarketSecurityNewRequest; +import ru.spcex.platform.classes.base.SpcexObjectBase; import ru.spcex.platform.enumeration.Allowed; import ru.spcex.platform.enumeration.Market; import ru.spcex.platform.imdg.api.Imdg; @@ -96,7 +97,6 @@ public class ExecutionDepositComponent { log.info("Reset trading day for search STrade: tradeNum={}, tradeDat={}", tradeNum, tradingDay); } - @Scheduled(cron = "${clearing-service.scheduler.check-s-trade}") public void processNewTS() { log.debug("Start check new S_TRADE. Start tradeNum={}", tradeNum); ImdgPredicateBuilder pb = sTradeImdg.predicateBuilder(); @@ -112,12 +112,13 @@ public class ExecutionDepositComponent { // Выявление новых сделок необходимо выполнить следующие контрольные проверки: // Проверить все инструменты. + Set secCodesOfSecurity; { Set secCodesOfSTrade = sTrades.stream().map(STrade::getSecCode).filter(Objects::nonNull).collect(Collectors.toSet()); log.debug("Verify {} instruments for {} STrade's.", secCodesOfSTrade.size(), sTrades.size()); ImdgPredicate allIn = securityImdg.predicateBuilder().in("securitySymbol", secCodesOfSTrade.toArray(new String[0])); Collection foundSecurities = securityImdg.getCollectionObjectsByPredicate(allIn); - Set secCodesOfSecurity = foundSecurities.stream().map(Security::getSecuritySymbol).filter(Objects::nonNull).collect(Collectors.toSet()); + secCodesOfSecurity = foundSecurities.stream().map(Security::getSecuritySymbol).filter(Objects::nonNull).collect(Collectors.toSet()); if (secCodesOfSecurity.containsAll(secCodesOfSTrade)) { log.debug("All {} Security found by {} secCodes from STrade", secCodesOfSecurity.size(), secCodesOfSTrade.size()); @@ -126,43 +127,41 @@ public class ExecutionDepositComponent { notFoundSymbol.removeAll(secCodesOfSecurity); log.info("Found only {} Security by {} secCodes from STrade. Not found: {}", secCodesOfSecurity.size(), secCodesOfSTrade.size(), notFoundSymbol); - createNewSecurities(notFoundSymbol); - log.info("Stop till they all will be created"); - - auditMessage("В security нет записей с securitySymbol", notFoundSymbol); - return; } } - Long generationId = idGenerator.nextId(); - log.info("generationId = {}", generationId); + LocalDate today = LocalDate.now(); for (STrade trade : sTrades) { - log.trace("Check s_trade[{}].tradeNum={}", trade.getId(), trade.getTradeNum()); + log.trace("Check s_trade[{}].tradeNum={} on date {}", trade.getId(), trade.getTradeNum()); Collection existsEDeposit = executionDepositImdg.getCollectionObjectsByFieldValues(Map.of( "exchangeExecutionId", trade.getTradeNum(), - "exchangeExecutionTime", trade.getTradeDateTime() + "clearingDate", today )); if (existsEDeposit.isEmpty()) { log.trace("S_TRADE[{}] new", trade.getId()); - ExecutionDeposit newED = null; + + // Проверка secCode + if (!secCodesOfSecurity.contains(trade.getSecCode())) { + log.error("Error {}: STrade[{}].secCode={} not found", + ClearingError.RecordNotFound.getId(), trade.getId(), trade.getSecCode()); + continue; + } + + ExecutionDeposit newED; try { - newED = createExecutionDeposit(trade, Allowed.ALLOWED/*todo уточнить момент заполнения*/, generationId); - verification(newED); + newED = createExecutionDeposit(trade, null, null); executionDepositImdg.insert(newED); sendNotification(newED); } catch (ClearingException ce) { auditMessage(ce); } catch (Exception e) { - if (newED != null) { - newED.setCoverageStatus(Allowed.DENIED.getKey()); - } - log.error("When create new ExecutionDeposit by STrade[{}]", trade.getId()); + log.error("When create new ExecutionDeposit by STrade[{}] error: {}", trade.getId(), ExceptionUtils.getStackTrace(e)); } } else { - long[] idToLong = existsEDeposit.stream().mapToLong(ed -> ed.getId()).toArray(); - log.warn("S_TRADE[{}] already has executionDeposit: {}", trade.getId(), Arrays.toString(idToLong)); + long[] idToLong = existsEDeposit.stream().mapToLong(SpcexObjectBase::getId).toArray(); + log.trace("S_TRADE[{}] already has executionDeposit: {}", trade.getId(), Arrays.toString(idToLong)); } } @@ -171,14 +170,6 @@ public class ExecutionDepositComponent { log.info("Process completed. Next tradeNum is {}", newMaxTradeNum); } - protected void verification(ExecutionDeposit forED) throws ClearingException { - /*todo Рассчитанные в КС контрольные суммы (общее количество сделок и суммарный объем заключенных сделок в денежном выражении) - должны совпадать со значениями, рассчитанными Торговой системой: - count(execution[tradingDay]) = count (trade_arqua) - */ - // использовать ли VerificationResultComponent для сверки или здесь код добавить. - - } protected void auditMessage(ClearingException ce) { log.error("AUDIT error code {}: {}", ce.getEnumMsg(), ce.getMessage()); @@ -192,51 +183,6 @@ public class ExecutionDepositComponent { log.error("audit \"clearing-service\", errorText: {}", txt); } - /** - * в очередь kafka для модуля securities-service сообщение о добавлении инструмента с параметром securitySymbol=s_trade.sec_code - * - * @param newSymbolRequest - */ - protected void createNewSecurities(Collection newSymbolRequest) { - final String destination = Consts.DESTINATION_MONEY_MARKET_SECURITY_NEW; - List symbolRequests = new ArrayList<>(newSymbolRequest); // чтобы в случае ошибки отобразить номер в логе - List> sendAll = new ArrayList<>(symbolRequests.size()); - for (String newSymbol : symbolRequests) { - if (newSymbol == null || newSymbol.isEmpty()) { - log.warn("Empty SecuritySumbol"); - } else { - MoneyMarketSecurityNewRequest requestPayload = new MoneyMarketSecurityNewRequest(); - requestPayload.setSecuritySymbol(newSymbol); - - BaseRequest request = new BaseRequest<>(); - request.setId(idGenerator.nextId()); - request.setActionType(ActionType.NEW); - request.setRequestPayload(requestPayload); - -// saveRequestToStorage(destination, request); //сохраняет данные о запросе в хранилище - log.trace("Send to {} new symbol \"{}\" ", destination, newSymbol); - Future send = kafka.send(new ProducerRecord<>(destination, request)); - sendAll.add(send); - } - } - int i = 0; - for (Future future : sendAll) { - try { - future.get(); // get exception - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - String about = i < symbolRequests.size() ? symbolRequests.get(i) : "(out of range i=" + i + ")"; - log.warn("Thread interrupted! On send symbol \"{}\"", about); - throw new RuntimeException(e); - } catch (ExecutionException e) { - String about = i < symbolRequests.size() ? symbolRequests.get(i) : "(out of range i=" + i + ")"; - log.error("Error send message for symbol \"{}\" to {}: {}", destination, - about, ExceptionUtils.getStackTrace(e.getCause() == null ? e : e.getCause())); - } - i++; - } - } - protected void sendNotification(ExecutionDeposit forED) { final String destination = Consts.REGISTRY_DEAL_REGISTER_NEW; DealRegisterNewRequest requestPayload = new DealRegisterNewRequest(); diff --git a/clearing-parent/clearing-service/src/main/resources/application.properties b/clearing-parent/clearing-service/src/main/resources/application.properties index bb4e61e6b..f80985c62 100644 --- a/clearing-parent/clearing-service/src/main/resources/application.properties +++ b/clearing-parent/clearing-service/src/main/resources/application.properties @@ -20,4 +20,3 @@ clearing-service.kafka-producer.linger-ms=1 clearing-service.kafka-producer.buffer-memory=33554432 clearing-service.scheduler.check-payment-instruction=*/5 * * * * * -clearing-service.scheduler.check-s-trade=0 * 0 1 * ? diff --git a/clearing-parent/imdg/src/main/java/ru/spcex/clearing/imdg/object/ExecutionDepositMapStore.java b/clearing-parent/imdg/src/main/java/ru/spcex/clearing/imdg/object/ExecutionDepositMapStore.java index c8a5185dd..ffd05dfb0 100644 --- a/clearing-parent/imdg/src/main/java/ru/spcex/clearing/imdg/object/ExecutionDepositMapStore.java +++ b/clearing-parent/imdg/src/main/java/ru/spcex/clearing/imdg/object/ExecutionDepositMapStore.java @@ -27,6 +27,10 @@ public class ExecutionDepositMapStore extends TemplateMapStore return IMDGDistributedNames.Map_ExecutionDeposit; } + public String[] getIndexingField() { + return new String[]{"exchangeExecutionId"}; + } + @Override public String[] getFields() { return new String[]{"ID", "CREATED_AT", "UPDATED_AT", From f47d3c09147e2fc1b61544483290a5ce33e7117d Mon Sep 17 00:00:00 2001 From: AKurakin Date: Wed, 1 Feb 2023 12:05:03 +0300 Subject: [PATCH 11/42] =?UTF-8?q?clearing-service=20http://jira.mfd.msk:80?= =?UTF-8?q?88/browse/CLS-188=20=D1=83=D0=BF=D1=80=D0=BE=D1=81=D1=82=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=B2=D1=8B=D0=B1=D0=BE=D1=80=D0=BA=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spcex/clearing/service/ExecutionDepositComponent.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecutionDepositComponent.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecutionDepositComponent.java index 27daaef00..f45bca061 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecutionDepositComponent.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecutionDepositComponent.java @@ -98,9 +98,9 @@ public class ExecutionDepositComponent { } public void processNewTS() { - log.debug("Start check new S_TRADE. Start tradeNum={}", tradeNum); + log.debug("Start check new S_TRADE after {}", tradingDay); ImdgPredicateBuilder pb = sTradeImdg.predicateBuilder(); - ImdgPredicate sql = pb.and(pb.greater("tradeNum", tradeNum), pb.greatEqual("tradeDateTime", tradingDay)); + ImdgPredicate sql = pb.greatEqual("tradeDateTime", tradingDay); Collection sTrades = sTradeImdg.getCollectionObjectsByPredicate(sql); log.info("Found {} new s_trade with trade_num>{}", sTrades.size(), tradeNum); @@ -132,7 +132,7 @@ public class ExecutionDepositComponent { LocalDate today = LocalDate.now(); for (STrade trade : sTrades) { - log.trace("Check s_trade[{}].tradeNum={} on date {}", trade.getId(), trade.getTradeNum()); + log.trace("Check s_trade[{}].tradeNum={} on date {}", trade.getId(), trade.getTradeNum(), today); Collection existsEDeposit = executionDepositImdg.getCollectionObjectsByFieldValues(Map.of( "exchangeExecutionId", trade.getTradeNum(), "clearingDate", today From 76bde6941a85f2a3f05fa5ed73fa71c401e5073c Mon Sep 17 00:00:00 2001 From: ialbert Date: Wed, 1 Feb 2023 12:12:26 +0300 Subject: [PATCH 12/42] http://jira.mfd.msk:8088/browse/CLS-189 --- .../ru/spcex/clearing/service/Clearing.java | 9 ++-- .../service/order/ExecutionDepositSorter.java | 46 +++++++++---------- .../spcex/platform/utils/collection/Pair.java | 27 +++++++++++ 3 files changed, 54 insertions(+), 28 deletions(-) create mode 100644 platform-parent/platform-utils/src/main/java/ru/spcex/platform/utils/collection/Pair.java diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java index c46e73787..3406f3383 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java @@ -45,20 +45,19 @@ public class Clearing { //выгружаем ExecutionDeposit с пустым sessionId Collection execDeposits = executionDepositImdg.getCollectionObjectsBySQL("sessionId = null"); //делаем группировку ExecutionDeposit по категории и компании, делаем сортировку - LinkedHashMap>> executionDeposits = sorter.sortExecutionDeposit(execDeposits); + LinkedHashMap>> executionDeposits = sorter.sortExecutionDeposit(execDeposits); executionDeposits.forEach((category, companies) -> { - for (List companyExecDeposits : companies) { + for (List companyExecDeposits : companies) { processSingleCompany(category, companyExecDeposits); } }); } - private void processSingleCompany(ClearingCategory category, List executionDeposits) { + private void processSingleCompany(ClearingCategory category, List executionDeposits) { log.info("Start clearing for category: {}, company: {}", category, executionDeposits.get(0).getCompanyId()); boolean financialError = false; - for (ExecDepositWCategory execDepositWrapper : executionDeposits) { - ExecutionDeposit execDeposit = execDepositWrapper.getExecutionDeposit(); + for (ExecutionDeposit execDeposit : executionDeposits) { if (financialError) { updateDenied(execDeposit); continue; diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/ExecutionDepositSorter.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/ExecutionDepositSorter.java index 21178cd47..954df66c4 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/ExecutionDepositSorter.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/ExecutionDepositSorter.java @@ -3,9 +3,9 @@ package ru.spcex.clearing.service.order; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import ru.clearing.classes.statics.data.execution.ExecutionDeposit; -import ru.spcex.clearing.service.ExecDepositWCategory; import ru.spcex.platform.enumeration.ClearingCategory; import ru.spcex.platform.enumeration.MoneyFlowSide; +import ru.spcex.platform.utils.collection.Pair; import ru.spcex.platform.utils.enumeration.IEnumKey; import java.util.*; @@ -23,7 +23,7 @@ public class ExecutionDepositSorter { this.clearingMemberCategoryProvider = clearingMemberCategoryProvider; } - public LinkedHashMap>> sortExecutionDeposit(CollectionexecDeposits) { + public LinkedHashMap>> sortExecutionDeposit(CollectionexecDeposits) { //отсортировали все записи по категориям // → внутри каждой подгруппы по категориям сортируем по компаниям // → обрабатываем почередно все записи первой компании @@ -32,18 +32,18 @@ public class ExecutionDepositSorter { // начинаем аналогично обработавать все записи второй категории и так далее). //сортируем по категориям - Map> categoryGrouping = execDeposits.stream().map(executionDeposit -> { + Map> categoryGrouping = execDeposits.stream().map(executionDeposit -> { ClearingCategory category = clearingMemberCategoryProvider.apply(executionDeposit.getCompanyId()); - return new ExecDepositWCategory(executionDeposit, category); - }).collect(Collectors.groupingBy(ExecDepositWCategory::getClearingMemberCategory)); + return new Pair<>(category, executionDeposit); + }).collect(Collectors.groupingBy(Pair::getFirst, Collectors.mapping(Pair::getSecond, Collectors.toList()))); //внутри категорий сортируем по компаниям - LinkedHashMap>> byCategoryByCompany = new LinkedHashMap<>(); - Consumer takeByClearingCategoryAnSortByCompaniId = clearingCategory -> { - List wrappers = categoryGrouping.remove(clearingCategory); + LinkedHashMap>> byCategoryByCompany = new LinkedHashMap<>(); + Consumer takeByClearingCategoryAndSortByCompanyId = clearingCategory -> { + List wrappers = categoryGrouping.remove(clearingCategory); if (wrappers != null) { - List> batches = wrappers.stream() - .collect(Collectors.groupingBy(ExecDepositWCategory::getCompanyId)) + List> batches = wrappers.stream() + .collect(Collectors.groupingBy(ExecutionDeposit::getCompanyId)) .entrySet() .stream() .sorted(Map.Entry.comparingByKey()) @@ -53,29 +53,29 @@ public class ExecutionDepositSorter { } }; //кладем в порядке I, V, B - takeByClearingCategoryAnSortByCompaniId.accept(ClearingCategory.I); - takeByClearingCategoryAnSortByCompaniId.accept(ClearingCategory.V); - takeByClearingCategoryAnSortByCompaniId.accept(ClearingCategory.B); + takeByClearingCategoryAndSortByCompanyId.accept(ClearingCategory.I); + takeByClearingCategoryAndSortByCompanyId.accept(ClearingCategory.V); + takeByClearingCategoryAndSortByCompanyId.accept(ClearingCategory.B); //для всех остальных порядок не важен, будут последними - categoryGrouping.keySet().forEach(takeByClearingCategoryAnSortByCompaniId); + categoryGrouping.keySet().forEach(takeByClearingCategoryAndSortByCompanyId); //метод для дополнительной сортировки внутри групп по категории и компании - BiConsumer> additionalSorting = + BiConsumer> additionalSorting = (clearingCategory, comparator) -> byCategoryByCompany .get(clearingCategory) .forEach(singleCompanyBatch -> singleCompanyBatch.sort(comparator)); //применяем дополнительные сортировки //для V сначала Sell, потом Buy, в первую очередь должны обрабатываться новые сделки с наименьшими объемами - additionalSorting.accept(ClearingCategory.V, firstSellThenBuy - .thenComparing(wrapper -> wrapper.getExecutionDeposit().getFirstLegAmount())); + additionalSorting.accept(ClearingCategory.V, + firstSellThenBuy.thenComparing(ExecutionDeposit::getFirstLegAmount)); //для V сначала Buy, потом Sell, exchangeExecutionId - возрастающий - additionalSorting.accept(ClearingCategory.B, firstBuyThenSell - .thenComparing(wrapper -> wrapper.getExecutionDeposit().getExchangeExecutionId())); + additionalSorting.accept(ClearingCategory.B, + firstBuyThenSell.thenComparing(ExecutionDeposit::getExchangeExecutionId)); return byCategoryByCompany; } - public static Comparator firstSellThenBuy = Comparator.comparing(wrapper -> { - MoneyFlowSide side = IEnumKey.getEnumByKey(MoneyFlowSide.class, wrapper.getExecutionDeposit().getSide()); + public static Comparator firstSellThenBuy = Comparator.comparing(wrapper -> { + MoneyFlowSide side = IEnumKey.getEnumByKey(MoneyFlowSide.class, wrapper.getSide()); if (side == null) return Integer.MAX_VALUE; switch (side) { case BUY -> { @@ -90,8 +90,8 @@ public class ExecutionDepositSorter { } }); - public static Comparator firstBuyThenSell = Comparator.comparing(wrapper -> { - MoneyFlowSide side = IEnumKey.getEnumByKey(MoneyFlowSide.class, wrapper.getExecutionDeposit().getSide()); + public static Comparator firstBuyThenSell = Comparator.comparing(wrapper -> { + MoneyFlowSide side = IEnumKey.getEnumByKey(MoneyFlowSide.class, wrapper.getSide()); if (side == null) return Integer.MAX_VALUE; switch (side) { case BUY -> { diff --git a/platform-parent/platform-utils/src/main/java/ru/spcex/platform/utils/collection/Pair.java b/platform-parent/platform-utils/src/main/java/ru/spcex/platform/utils/collection/Pair.java new file mode 100644 index 000000000..3fb512341 --- /dev/null +++ b/platform-parent/platform-utils/src/main/java/ru/spcex/platform/utils/collection/Pair.java @@ -0,0 +1,27 @@ +package ru.spcex.platform.utils.collection; + +public class Pair { + private T1 first; + private T2 second; + + public Pair(T1 first, T2 second) { + this.first = first; + this.second = second; + } + + public T1 getFirst() { + return first; + } + + public void setFirst(T1 first) { + this.first = first; + } + + public T2 getSecond() { + return second; + } + + public void setSecond(T2 second) { + this.second = second; + } +} From 0ffc0a64714216eedde883d42aecfc68366199b8 Mon Sep 17 00:00:00 2001 From: AKurakin Date: Wed, 1 Feb 2023 12:11:53 +0300 Subject: [PATCH 13/42] =?UTF-8?q?clearing-service=20http://jira.mfd.msk:80?= =?UTF-8?q?88/browse/CLS-188=20=D1=83=D0=BF=D1=80=D0=BE=D1=81=D1=82=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BE=D1=82=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D1=83=20Dea?= =?UTF-8?q?lRegisterNewRequest=20(=D1=83=D0=B1=D1=80=D0=B0=D0=BB=20=D0=B4?= =?UTF-8?q?=D0=B0=D1=82=D1=8B=20=D1=8F=D0=B2=D1=8B=208=20=D1=87=D1=82?= =?UTF-8?q?=D0=BE=D0=B1=D1=8B=20=D0=BD=D0=B5=20=D1=81=D1=82=D1=83=D1=87?= =?UTF-8?q?=D0=B0=D0=BB=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B0=D0=BC=D0=B8?= =?UTF-8?q?=20=D1=81=D0=B5=D1=80=D0=B8=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D0=B8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/ExecutionDepositComponent.java | 2 -- .../cud/registry/DealRegisterNewRequest.java | 32 ------------------- 2 files changed, 34 deletions(-) diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecutionDepositComponent.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecutionDepositComponent.java index f45bca061..a97c97046 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecutionDepositComponent.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ExecutionDepositComponent.java @@ -187,9 +187,7 @@ public class ExecutionDepositComponent { final String destination = Consts.REGISTRY_DEAL_REGISTER_NEW; DealRegisterNewRequest requestPayload = new DealRegisterNewRequest(); requestPayload.setExecutionId(forED.getId()); - requestPayload.setClearingDate(forED.getClearingDate()); requestPayload.setExchangeExecutionId(forED.getExchangeExecutionId()); - requestPayload.setExchangeExecutionTime(forED.getExchangeExecutionTime()); // requestPayload.setId(idGenerator.nextId()); BaseRequest request = new BaseRequest<>(); diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/registry/DealRegisterNewRequest.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/registry/DealRegisterNewRequest.java index c9edf8b55..0e37c8711 100644 --- a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/registry/DealRegisterNewRequest.java +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/registry/DealRegisterNewRequest.java @@ -15,15 +15,6 @@ public class DealRegisterNewRequest { @JsonProperty public Long exchangeExecutionId; - @JsonProperty - public Instant exchangeExecutionTime; - - @JsonProperty - public Long id; - - @JsonProperty - public LocalDate clearingDate; - public Long getExecutionId() { return executionId; @@ -41,27 +32,4 @@ public class DealRegisterNewRequest { this.exchangeExecutionId = exchangeExecutionId; } - public Instant getExchangeExecutionTime() { - return exchangeExecutionTime; - } - - public void setExchangeExecutionTime(Instant exchangeExecutionTime) { - this.exchangeExecutionTime = exchangeExecutionTime; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public LocalDate getClearingDate() { - return clearingDate; - } - - public void setClearingDate(LocalDate clearingDate) { - this.clearingDate = clearingDate; - } } From efbc81571745dbde1845d3434380d35614703ad0 Mon Sep 17 00:00:00 2001 From: etreschenkov Date: Wed, 1 Feb 2023 13:25:07 +0300 Subject: [PATCH 14/42] http://jira.mfd.msk:8088/browse/CLS-240 --- .../src/main/resources/meta/meta.xml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) 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 058667e6d..de067158f 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 @@ - + @@ -900,7 +900,7 @@ - + @@ -908,12 +908,12 @@ - + - - - - + + + + @@ -921,8 +921,8 @@ - - + + From e016cc55280b3fd54324e09f73f9dc251f4eb48a Mon Sep 17 00:00:00 2001 From: etreshenkov Date: Wed, 1 Feb 2023 14:02:27 +0300 Subject: [PATCH 15/42] http://jira.mfd.msk:8088/browse/CLS-217 --- .../queue/scheduler/LauncherController.java | 11 +++++------ .../controller/request/cud/schedule/LauncherNew.java | 3 +-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/scheduler/LauncherController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/scheduler/LauncherController.java index f0dcfa17f..fad922cdc 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/scheduler/LauncherController.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/scheduler/LauncherController.java @@ -90,14 +90,13 @@ public class LauncherController extends AbstractQueueController { @ApiOperation(value = "create specific launcher.") @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CudResponse.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)}) - @RequestMapping(value = "/specific/{task-code}", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) + @RequestMapping(value = "/specific", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) @ResponseBody - public CudResponse addSpecific(@ApiParam(value = "Код задания из taskDictionary", required = true, example = "ABLK") - @PathVariable("task-code") String dictionaryName, + public CudResponse addSpecific(@ApiParam(value = "Параметры команды в JSON формате.", required = true) @RequestBody LauncherNew launcherNew) throws ExecutionException, InterruptedException { - AbstractDictionary taskEnum = taskDictionary.getSingleObjectByFieldValues(Map.of("code", dictionaryName)); + AbstractDictionary taskEnum = taskDictionary.getSingleObjectByFieldValues(Map.of("code", launcherNew.getTask())); if (taskEnum == null) { - throw new NotFound404Exception("task dictionary element with code '" + dictionaryName + "'"); + throw new NotFound404Exception("task dictionary element with code '" + launcherNew.getTask() + "'"); } if (!Task.startOfClearing.getKey().equals(taskEnum.getCode())) { throw new IllegalStateException(String.format("Task %s not support request with body", taskEnum.getCode())); @@ -109,7 +108,7 @@ public class LauncherController extends AbstractQueueController { if (user == null) { throw new IllegalStateException("cannot obtain userId from logged in user " + username); } - launcherCommand.setTask(dictionaryName); + launcherCommand.setTask(launcherNew.getTask()); launcherCommand.setUserId(user.getId()); launcherCommand.setCompanyId(launcherNew.getCompanyId()); launcherCommand.setSecurityId(launcherNew.getSecurityId()); diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/schedule/LauncherNew.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/schedule/LauncherNew.java index f5bfe7497..9977df62f 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/schedule/LauncherNew.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/request/cud/schedule/LauncherNew.java @@ -7,7 +7,6 @@ import ru.spcex.clearing.backendapi.domain.actions.IAction; import ru.spcex.clearing.backendapi.errors.BackEndError; import ru.spcex.clearing.platform.messaging.domain.ActionType; import ru.spcex.clearing.platform.messaging.domain.cud.schedule.LauncherCommandRequest; -import ru.spcex.platform.enumeration.Task; import ru.spcex.platform.utils.enumeration.EnumMessage; import java.util.Collection; @@ -24,7 +23,6 @@ public class LauncherNew implements IAction { @ApiModelProperty(value = "Идентификатор инструмента", example = "1000") @JsonProperty private Long securityId; - @JsonIgnore private Long userId; @@ -38,6 +36,7 @@ public class LauncherNew implements IAction { return taskRunnerCommandRequest; } + @ApiModelProperty(hidden = true) @Override public ActionType getActionType() { return ActionType.NEW; From 8fb186f564873d859e1bfc5b18a80d5c797c3906 Mon Sep 17 00:00:00 2001 From: AKurakin Date: Wed, 1 Feb 2023 14:17:54 +0300 Subject: [PATCH 16/42] clearing-service fix NPE --- .../ru/spcex/clearing/service/order/ExecutionDepositSorter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/ExecutionDepositSorter.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/ExecutionDepositSorter.java index 954df66c4..a396f5b90 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/ExecutionDepositSorter.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/ExecutionDepositSorter.java @@ -63,6 +63,7 @@ public class ExecutionDepositSorter { BiConsumer> additionalSorting = (clearingCategory, comparator) -> byCategoryByCompany .get(clearingCategory) + .stream().filter(Objects::nonNull) .forEach(singleCompanyBatch -> singleCompanyBatch.sort(comparator)); //применяем дополнительные сортировки //для V сначала Sell, потом Buy, в первую очередь должны обрабатываться новые сделки с наименьшими объемами From 6b43d3b238245d7b4460b1095f85a2913e5f945e Mon Sep 17 00:00:00 2001 From: AKurakin Date: Wed, 1 Feb 2023 14:48:15 +0300 Subject: [PATCH 17/42] =?UTF-8?q?dbf-exporter=20=D0=B4=D0=BE=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B0=D0=BB=20=D0=BE=D0=BF=D1=86=D0=B8=D0=BE=D0=BD=D0=B0?= =?UTF-8?q?=D0=BB=D1=8C=D0=BD=D1=8B=D0=B9=20KafkaSender,=20=D0=B8=D0=BD?= =?UTF-8?q?=D0=B0=D1=87=D0=B5=20=D0=BD=D0=B5=20=D0=B7=D0=B0=D0=BF=D1=83?= =?UTF-8?q?=D1=81=D0=BA=D0=B0=D0=BB=D1=81=D1=8F=20=D0=B1=D0=B5=D0=B7=20?= =?UTF-8?q?=D0=BD=D0=B5=D0=BE=D0=B1=D1=8F=D0=B7=D0=B0=D1=82=D0=B5=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D1=8B=D1=85=20=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=B5=D0=BA.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../clearing/dbf/exporter/config/KafkaSenderConfig.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/clearing-parent/dbf-exporter/src/main/java/ru/spcex/clearing/dbf/exporter/config/KafkaSenderConfig.java b/clearing-parent/dbf-exporter/src/main/java/ru/spcex/clearing/dbf/exporter/config/KafkaSenderConfig.java index d2397c4a5..2b2319156 100644 --- a/clearing-parent/dbf-exporter/src/main/java/ru/spcex/clearing/dbf/exporter/config/KafkaSenderConfig.java +++ b/clearing-parent/dbf-exporter/src/main/java/ru/spcex/clearing/dbf/exporter/config/KafkaSenderConfig.java @@ -1,6 +1,8 @@ package ru.spcex.clearing.dbf.exporter.config; import org.apache.kafka.clients.producer.Producer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -14,6 +16,7 @@ import ru.spcex.platform.imdg.api.ImdgProvider; //отдельный конфиг для sender чтобы сделать required false @Configuration public class KafkaSenderConfig { + Logger log = LoggerFactory.getLogger(getClass()); private final ImdgProvider imdgProvider; private Producer kafkaProducer; @@ -23,14 +26,15 @@ public class KafkaSenderConfig { this.imdgProvider = imdgProvider; } - @Autowired + @Autowired(required = false) public void setKafkaProducer(Producer kafkaProducer) { this.kafkaProducer = kafkaProducer; } @Bean public KafkaSender kafkaSender() { - if (kafkaProducer == null ||imdgProvider == null) { + if (kafkaProducer == null || imdgProvider == null) { + log.info("Can not create KafkaSender: kafkaProducer={}, imdgProvider={}", kafkaProducer, imdgProvider); return null; } ImdgId imdgIdGenerator = imdgProvider.getImdgIdGenerator(); From 5c143ad47ae28475cc98958c222778252925140a Mon Sep 17 00:00:00 2001 From: etreschenkov Date: Wed, 1 Feb 2023 16:30:37 +0300 Subject: [PATCH 18/42] update meta --- .../backend-api/src/main/resources/meta/meta.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) 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 de067158f..c96d68e05 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 @@ - + @@ -713,8 +713,8 @@ - - + + @@ -752,7 +752,7 @@ - + @@ -907,13 +907,13 @@ - + - - + + From 43b69192e6e68cf74e0f37347357fc62bcffb8a5 Mon Sep 17 00:00:00 2001 From: akurakin Date: Wed, 1 Feb 2023 18:04:27 +0300 Subject: [PATCH 19/42] =?UTF-8?q?clearing-service=20http://jira.mfd.msk:80?= =?UTF-8?q?88/browse/CLS-189=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20PaymentInstruction,=20=D1=87=D0=B0=D1=81=D1=82=D1=8C?= =?UTF-8?q?=202.2.2=20=D0=BF=D0=BE=D0=BB=D0=BE=D0=B2=D0=B8=D0=BD=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ru/spcex/clearing/service/Clearing.java | 18 +- .../order/PaymentInstructionCreator.java | 253 ++++++++++++++++++ .../platform/enumeration/AccountType.java | 2 +- .../platform/enumeration/InOutDirection.java | 2 +- 4 files changed, 268 insertions(+), 7 deletions(-) create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentInstructionCreator.java diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java index 3406f3383..7438161ee 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java @@ -6,9 +6,12 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.execution.ExecutionDeposit; import ru.clearing.classes.statics.data.generated.ClearingMemberCategory; +import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsAssets; +import ru.clearing.classes.statics.data.payment.PaymentInstruction; import ru.spcex.clearing.error.ClearingErrorInternal; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.service.order.ExecutionDepositSorter; +import ru.spcex.clearing.service.order.PaymentInstructionCreator; import ru.spcex.platform.enumeration.Allowed; import ru.spcex.platform.enumeration.ClearingCategory; import ru.spcex.platform.imdg.api.Imdg; @@ -17,10 +20,7 @@ import ru.spcex.platform.utils.enumeration.EnumMessage; import ru.spcex.platform.utils.validation.IValidator; import java.time.Instant; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Optional; +import java.util.*; import java.util.function.BiFunction; @Service @@ -30,13 +30,15 @@ public class Clearing { private final Imdg clearingCategoryImdg; private final ExecutionDepositSorter sorter; private final BiFunction validation; + private final PaymentInstructionCreator paymentInstructionCreator; @Autowired public Clearing(ImdgProvider imdgProvider, - ExecutionDepositSorter sorter, + ExecutionDepositSorter sorter, PaymentInstructionCreator paymentInstructionCreator, BiFunction validation) { this.executionDepositImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionDeposit, ExecutionDeposit.class); this.clearingCategoryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class); + this.paymentInstructionCreator = paymentInstructionCreator; this.sorter = sorter; this.validation = validation; } @@ -50,6 +52,12 @@ public class Clearing { executionDeposits.forEach((category, companies) -> { for (List companyExecDeposits : companies) { processSingleCompany(category, companyExecDeposits); + // todo paymentInstructionCreator +// LiabilitiesClaimsAssets liabilitiesClaimsAssets = null; +// Collection clearingCategory = Collections.singleton(category); +// List newPaymentInstructions = paymentInstructionCreator.createAndSavePaymentInstructions(liabilitiesClaimsAssets, ); + //todo Изменение liabilitiesClaimsAssets по paymentInstruction + // todo Изменение liabilitiesClaimsMoney по paymentInstruction } }); } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentInstructionCreator.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentInstructionCreator.java new file mode 100644 index 000000000..541c0353c --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentInstructionCreator.java @@ -0,0 +1,253 @@ +package ru.spcex.clearing.service.order; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import ru.clearing.classes.statics.data.account.Account; +import ru.clearing.classes.statics.data.company.Company; +import ru.clearing.classes.statics.data.company.CompanySymbols; +import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsAssets; +import ru.clearing.classes.statics.data.payment.PaymentInstruction; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.platform.enumeration.*; +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.utils.time.TimeUtil; + +import java.time.Instant; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; + +@Service +public class PaymentInstructionCreator { + private final Logger log = LoggerFactory.getLogger(getClass()); + + protected final ImdgId idGenerator; + protected final Imdg liabilitiesClaimsAssetsImdg; + protected final Imdg companySymbolsImdg; + protected final Imdg companyImdg; + protected final Imdg accountImdg; + protected final Imdg paymentInstructionImdg; + + protected AtomicLong documentNumberId = new AtomicLong(); // порядковый номер (сквозной по всем компаниям за день + protected LocalDate documentNumberResetAt; + + @Autowired + public PaymentInstructionCreator(ImdgProvider imdgProvider) { + this.liabilitiesClaimsAssetsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_LiabilitiesClaimsAssets, LiabilitiesClaimsAssets.class); + this.companySymbolsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CompanySymbols, CompanySymbols.class); + this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class); + this.accountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class); + this.paymentInstructionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_PaymentInstruction, PaymentInstruction.class); + this.idGenerator = imdgProvider.getImdgIdGenerator(); + } + + // 2.2.2 + public List createAndSavePaymentInstructions(LiabilitiesClaimsAssets liabilitiesClaimsAssets, + Collection clearingCategory) { + List newPaymentInstructions = createPaymentInstructions(liabilitiesClaimsAssets, clearingCategory); + log.debug("Created {} PaymentInstruction by LiabilitiesClaimsAssets[{}]", + newPaymentInstructions.size(), liabilitiesClaimsAssets.getId()); + for (PaymentInstruction instruction : newPaymentInstructions) { + paymentInstructionImdg.insert(instruction); + } + return newPaymentInstructions; + } + + /** + * Создаёт и сохраняет + * + * @param liabilitiesClaimsAssets + * @param clearingCategory + * @return + */ + protected List createPaymentInstructions(LiabilitiesClaimsAssets liabilitiesClaimsAssets, + Collection clearingCategory) { + List newPaymentInstructions = new ArrayList<>(); + int count; + if (clearingCategory.contains(ClearingCategory.I)) { + count = 2; + } else if (clearingCategory.contains(ClearingCategory.V) || clearingCategory.contains(ClearingCategory.B)) { + count = 1; + } else { + count = 0; + } + Instant now = Instant.now(); + + // I + if (clearingCategory.contains(ClearingCategory.I)) { + PaymentInstruction payment1 = new PaymentInstruction(); + PaymentInstruction payment2 = new PaymentInstruction(); + + payment1.setId(idGenerator.nextId()); + payment1.setCreated(now); + payment1.setClearingDate(TimeUtil.toLocalDate(now)); + payment2.setId(idGenerator.nextId()); + payment2.setCreated(now); + payment2.setClearingDate(TimeUtil.toLocalDate(now)); + + payment1.setSenderId(liabilitiesClaimsAssets.getCompanyId()); + payment2.setSenderId(1L); // СПВБ + + payment1.setAddresseeId(1L); // СПВБ + String sqlLCA = String.format("securityId = %s and companyId <> %s", + liabilitiesClaimsAssets.getSecurityId(), liabilitiesClaimsAssets.getCompanyId()); + LiabilitiesClaimsAssets counterLiabilitiesClaimsAssets = liabilitiesClaimsAssetsImdg.getSingleObjectBySQL(sqlLCA); + if (counterLiabilitiesClaimsAssets == null) { + log.warn("Counter LiabilitiesClaimsAssets not found for : {}", sqlLCA); + } else { + payment2.setAddresseeId(counterLiabilitiesClaimsAssets.getCompanyId()); + } + + String symbol1 = selectSymbolValue(payment1.getAddresseeId(), CompanySymbol.BIC); + if (symbol1 == null) { + log.warn("CompanySymbols BIC not found for companyId={}", payment1.getAddresseeId()); + } else { + payment1.setAdresseeBic(symbol1); + } + String symbol2 = selectSymbolValue(payment2.getAddresseeId(), CompanySymbol.BIC); + if (symbol2 == null) { + log.warn("CompanySymbols BIC not found for companyId={}", payment2.getAddresseeId()); + } else { + payment2.setAdresseeBic(symbol2); + } + + Company companyPRC = companyImdg.getSingleObjectByID(2L); // 2 "НКО АО ПРЦ" + String companyPRCName = null; + if (companyPRC == null) { + log.warn("Company.id=2 not found"); + } else { + companyPRCName = companyPRC.getShortName(); + } + payment1.setPayeeBankName(companyPRCName); + payment2.setPayeeBankName(companyPRCName); + + String symbolPRC = selectSymbolValue(2L, CompanySymbol.BIC); // 2 "НКО АО ПРЦ" + payment1.setPayeeBic(symbolPRC); + payment2.setPayeeBic(symbolPRC); + + payment1.setAddresseeBankName(companyPRCName); + payment2.setAddresseeBankName(companyPRCName); + + payment1.setPaymentDate(TimeUtil.localDateToInstant(liabilitiesClaimsAssets.getSettlementDate())); + payment2.setPaymentDate(TimeUtil.localDateToInstant(liabilitiesClaimsAssets.getSettlementDate())); + + payment1.setPaymentPurpose("Размещение депозита " + liabilitiesClaimsAssets.getContract()); + payment2.setPaymentPurpose("Размещение депозита " + liabilitiesClaimsAssets.getContract()); + + payment1.setSettlementDate(liabilitiesClaimsAssets.getSettlementDate()); + payment2.setSettlementDate(liabilitiesClaimsAssets.getSettlementDate()); + + Long amount = liabilitiesClaimsAssets.getLiabilitiesQuantity() == null ? null : liabilitiesClaimsAssets.getLiabilitiesQuantity().abs().longValue(); + payment1.setCreditLegAmount(amount); + payment2.setCreditLegAmount(amount); + payment1.setDebitLegAmount(amount); + payment2.setDebitLegAmount(amount); + + payment1.setCreditLegAccountId(liabilitiesClaimsAssets.getAccountId()); + String accSql = String.format("companyId = %s AND accountType=TRAN AND accountStatus=ACTV AND processingSign=ALWD", + payment2.getSenderId()); + Account anotherAcc = accountImdg.getSingleObjectBySQL(accSql); + if (anotherAcc == null) { + log.warn("Account not found: {}", accSql); + } else { + payment2.setCreditLegAccountId(anotherAcc.getId()); + } + + payment1.setCreditCsAccount(null); + payment2.setCreditCsAccount(null); + + { + Account acc1 = accountImdg.getSingleObjectByID(payment1.getCreditLegAccountId()); + if (acc1 != null) { + payment1.setCreditLegAccount(acc1.getAccount()); + } + Account acc2 = accountImdg.getSingleObjectByID(payment2.getCreditLegAccountId()); + if (acc2 != null) { + payment1.setCreditLegAccount(acc2.getAccount()); + } + } + + { + Account acc1 = selectAccount(payment1.getAddresseeId(), AccountType.Tran, Status.Active, Allowed.ALLOWED); + if (acc1 != null) { + payment1.setDebitLegAccountId(acc1.getId()); + payment1.setDebitLegAccount(acc1.getAccount()); + } + Account acc2 = selectAccount(payment2.getAddresseeId(), AccountType.Clrn, Status.Active, Allowed.ALLOWED); + if (acc2 != null) { + payment2.setDebitLegAccountId(acc2.getId()); + payment2.setDebitLegAccount(acc2.getAccount()); + } + } + + payment1.setDebitCsAccount(null); + payment2.setDebitCsAccount(null); + +// payment1.setDebitLegDirection(InOutDirection.out.getKey()); +// payment2.setDebitLegDirection(InOutDirection.out.getKey()); +// payment1.setCreditLegDirection(InOutDirection.in.getKey()); +// payment2.setCreditLegDirection(InOutDirection.in.getKey()); + + payment1.setCreditLegCurrencyCode(liabilitiesClaimsAssets.getCurrency()); + payment2.setCreditLegCurrencyCode(liabilitiesClaimsAssets.getCurrency()); + payment1.setDebitLegCurrencyCode(liabilitiesClaimsAssets.getCurrency()); + payment2.setDebitLegCurrencyCode(liabilitiesClaimsAssets.getCurrency()); + + payment1.setTransactionStatus(TransactionStatus.stld.getKey()); + payment2.setTransactionStatus(TransactionStatus.stld.getKey()); + + + payment1.setDocumentNumber(nextDocumentNumber(liabilitiesClaimsAssets, payment1)); + payment2.setDocumentNumber(nextDocumentNumber(liabilitiesClaimsAssets, payment2)); + + newPaymentInstructions.add(payment1); + newPaymentInstructions.add(payment2); + } + //todo сочетания типов??? Другие типы + return newPaymentInstructions; + } + + protected String nextDocumentNumber(LiabilitiesClaimsAssets liabilitiesClaimsAssets, PaymentInstruction paymentInstruction) { + if (documentNumberResetAt == null || documentNumberResetAt.isBefore(LocalDate.now())) { + documentNumberId.set(0); + documentNumberResetAt = LocalDate.now(); + } + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ddMMyy"); + String num = String.format("%s/%s/%s/", + liabilitiesClaimsAssets.getContract(), formatter.format(paymentInstruction.getPaymentDate()), + paymentInstruction.getSenderId(), documentNumberId.incrementAndGet() + ); + return num; + } + + protected String selectSymbolValue(Long companyId, CompanySymbol symbol) { + CompanySymbols cSymbol = companySymbolsImdg.getSingleObjectByFieldValues(Map.of( + "companyId", companyId, + "companySymbol", symbol.getKey())); + if (cSymbol == null) { + return null; + } else { + return cSymbol.getCompanySymbolValue(); + } + } + + protected Account selectAccount(Long companyId, AccountType accountType, Status accountStatus, Allowed processingSign) { + Account account = accountImdg.getSingleObjectByFieldValues(Map.of( + "companyId", companyId, + "accountType", accountType.getKey(), + "accountStatus", accountStatus.getKey(), + "processingSign", processingSign.getKey() + )); + return account; + } + + +} diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/AccountType.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/AccountType.java index fa04d58a6..7c9d342b3 100644 --- a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/AccountType.java +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/AccountType.java @@ -3,7 +3,7 @@ package ru.spcex.platform.enumeration; import ru.spcex.platform.utils.enumeration.IEnumKey; public enum AccountType implements IEnumKey { - Clrn("CLRN"), Bank("BANK"), Info("INFO"); + Clrn("CLRN"), Bank("BANK"), Info("INFO"), Tran("TRAN"); private final String key; diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/InOutDirection.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/InOutDirection.java index ec91a9dbf..7cb6e0665 100644 --- a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/InOutDirection.java +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/InOutDirection.java @@ -3,7 +3,7 @@ package ru.spcex.platform.enumeration; import ru.spcex.platform.utils.enumeration.IEnumKey; public enum InOutDirection implements IEnumKey { - in("IN"); + in("IN"), out("OUT"); private final String key; From 5f41508df3a5727332cf84fdaf1d63f1dd3d8839 Mon Sep 17 00:00:00 2001 From: akurakin Date: Wed, 1 Feb 2023 20:13:43 +0300 Subject: [PATCH 20/42] =?UTF-8?q?clearing-service=20http://jira.mfd.msk:80?= =?UTF-8?q?88/browse/CLS-189=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20PaymentInstruction,=20=D1=87=D0=B0=D1=81=D1=82=D1=8C?= =?UTF-8?q?=202.2.2=20=D0=B4=D0=BE=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D0=BD=D0=BE=D1=81=D1=82=D1=8C=D1=8E,=20=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D0=BB=D0=BE=D1=81=D1=8C=202.2.2.1=20=D0=B8?= =?UTF-8?q?=202.2.2.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- clearing-parent/clearing-service/pom.xml | 4 + .../order/PaymentInstructionCreator.java | 211 ++++++++++++++++-- .../order/PaymentInstructionCreatorTest.java | 29 +++ .../platform/enumeration/AccountType.java | 2 +- 4 files changed, 224 insertions(+), 22 deletions(-) create mode 100644 clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/order/PaymentInstructionCreatorTest.java diff --git a/clearing-parent/clearing-service/pom.xml b/clearing-parent/clearing-service/pom.xml index aa206dcf4..1d7d1fd1a 100644 --- a/clearing-parent/clearing-service/pom.xml +++ b/clearing-parent/clearing-service/pom.xml @@ -51,6 +51,10 @@ assertj-core test + + org.mockito + mockito-core + diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentInstructionCreator.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentInstructionCreator.java index 541c0353c..950e3c7a3 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentInstructionCreator.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentInstructionCreator.java @@ -27,6 +27,9 @@ import java.util.concurrent.atomic.AtomicLong; @Service public class PaymentInstructionCreator { + protected static final Long SPVB_ID = 1L; // СПВБ + protected static final Long PRC_ID = 2L; // 2 "НКО АО ПРЦ" + private final Logger log = LoggerFactory.getLogger(getClass()); protected final ImdgId idGenerator; @@ -71,18 +74,11 @@ public class PaymentInstructionCreator { protected List createPaymentInstructions(LiabilitiesClaimsAssets liabilitiesClaimsAssets, Collection clearingCategory) { List newPaymentInstructions = new ArrayList<>(); - int count; - if (clearingCategory.contains(ClearingCategory.I)) { - count = 2; - } else if (clearingCategory.contains(ClearingCategory.V) || clearingCategory.contains(ClearingCategory.B)) { - count = 1; - } else { - count = 0; - } Instant now = Instant.now(); // I if (clearingCategory.contains(ClearingCategory.I)) { + log.debug("By liabilitiesClaimsAssets[{}] create for category I 1 record", liabilitiesClaimsAssets.getId()); PaymentInstruction payment1 = new PaymentInstruction(); PaymentInstruction payment2 = new PaymentInstruction(); @@ -94,9 +90,9 @@ public class PaymentInstructionCreator { payment2.setClearingDate(TimeUtil.toLocalDate(now)); payment1.setSenderId(liabilitiesClaimsAssets.getCompanyId()); - payment2.setSenderId(1L); // СПВБ + payment2.setSenderId(SPVB_ID); // СПВБ - payment1.setAddresseeId(1L); // СПВБ + payment1.setAddresseeId(SPVB_ID); // СПВБ String sqlLCA = String.format("securityId = %s and companyId <> %s", liabilitiesClaimsAssets.getSecurityId(), liabilitiesClaimsAssets.getCompanyId()); LiabilitiesClaimsAssets counterLiabilitiesClaimsAssets = liabilitiesClaimsAssetsImdg.getSingleObjectBySQL(sqlLCA); @@ -119,7 +115,7 @@ public class PaymentInstructionCreator { payment2.setAdresseeBic(symbol2); } - Company companyPRC = companyImdg.getSingleObjectByID(2L); // 2 "НКО АО ПРЦ" + Company companyPRC = companyImdg.getSingleObjectByID(PRC_ID); // 2 "НКО АО ПРЦ" String companyPRCName = null; if (companyPRC == null) { log.warn("Company.id=2 not found"); @@ -129,7 +125,7 @@ public class PaymentInstructionCreator { payment1.setPayeeBankName(companyPRCName); payment2.setPayeeBankName(companyPRCName); - String symbolPRC = selectSymbolValue(2L, CompanySymbol.BIC); // 2 "НКО АО ПРЦ" + String symbolPRC = selectSymbolValue(PRC_ID, CompanySymbol.BIC); // 2 "НКО АО ПРЦ" payment1.setPayeeBic(symbolPRC); payment2.setPayeeBic(symbolPRC); @@ -191,10 +187,10 @@ public class PaymentInstructionCreator { payment1.setDebitCsAccount(null); payment2.setDebitCsAccount(null); -// payment1.setDebitLegDirection(InOutDirection.out.getKey()); -// payment2.setDebitLegDirection(InOutDirection.out.getKey()); -// payment1.setCreditLegDirection(InOutDirection.in.getKey()); -// payment2.setCreditLegDirection(InOutDirection.in.getKey()); +// payment1.setCreditLegDirection(InOutDirection.out.getKey()); +// payment2.setCreditLegDirection(InOutDirection.out.getKey()); +// payment1.setDebitLegDirection(InOutDirection.in.getKey()); +// payment2.setDebitLegDirection(InOutDirection.in.getKey()); payment1.setCreditLegCurrencyCode(liabilitiesClaimsAssets.getCurrency()); payment2.setCreditLegCurrencyCode(liabilitiesClaimsAssets.getCurrency()); @@ -210,18 +206,191 @@ public class PaymentInstructionCreator { newPaymentInstructions.add(payment1); newPaymentInstructions.add(payment2); + } else { + // V / B + if (clearingCategory.contains(ClearingCategory.V)) { + log.debug("By liabilitiesClaimsAssets[{}] create for category V 1 record", liabilitiesClaimsAssets.getId()); + PaymentInstruction payment1 = new PaymentInstruction(); + payment1.setId(idGenerator.nextId()); + payment1.setCreated(now); + payment1.setClearingDate(TimeUtil.toLocalDate(now)); + + payment1.setSenderId(SPVB_ID); // СПВБ + + String sqlLCA = String.format("securityId = %s and companyId <> %s", + liabilitiesClaimsAssets.getSecurityId(), liabilitiesClaimsAssets.getCompanyId()); + LiabilitiesClaimsAssets counterLiabilitiesClaimsAssets = liabilitiesClaimsAssetsImdg.getSingleObjectBySQL(sqlLCA); + if (counterLiabilitiesClaimsAssets == null) { + log.warn("Counter LiabilitiesClaimsAssets not found for : {}", sqlLCA); + } else { + payment1.setAddresseeId(counterLiabilitiesClaimsAssets.getCompanyId()); + } + + String symbol1 = selectSymbolValue(payment1.getAddresseeId(), CompanySymbol.BIC); + if (symbol1 == null) { + log.warn("CompanySymbols BIC not found for companyId={}", payment1.getAddresseeId()); + } else { + payment1.setAdresseeBic(symbol1); + } + + Company companyPRC = companyImdg.getSingleObjectByID(PRC_ID); // 2 "НКО АО ПРЦ" + String companyPRCName = null; + if (companyPRC == null) { + log.warn("Company.id=2 not found"); + } else { + companyPRCName = companyPRC.getShortName(); + } + payment1.setPayeeBankName(companyPRCName); + + String symbolPRC = selectSymbolValue(PRC_ID, CompanySymbol.BIC); // 2 "НКО АО ПРЦ" + payment1.setPayeeBic(symbolPRC); + + payment1.setAddresseeBankName(companyPRCName); + + payment1.setPaymentDate(TimeUtil.localDateToInstant(liabilitiesClaimsAssets.getSettlementDate())); + + payment1.setPaymentPurpose("Размещение депозита " + liabilitiesClaimsAssets.getContract()); + + payment1.setSettlementDate(liabilitiesClaimsAssets.getSettlementDate()); + + Long amount = liabilitiesClaimsAssets.getLiabilitiesQuantity() == null ? null : liabilitiesClaimsAssets.getLiabilitiesQuantity().abs().longValue(); + payment1.setCreditLegAmount(amount); + payment1.setDebitLegAmount(amount); + + { + String accSql = String.format("companyId = %s AND accountType=ANLT AND accountStatus=ACTV AND processingSign=ALWD", + payment1.getSenderId()); + Account acc1 = accountImdg.getSingleObjectBySQL(accSql); + if (acc1 == null) { + log.warn("Account not found: {}", accSql); + } else { + payment1.setCreditLegAccountId(acc1.getId()); + payment1.setCreditLegAccount(acc1.getAccount()); + } + } + + payment1.setCreditCsAccount(null); + + { + Account acc1 = selectAccount(payment1.getAddresseeId(), AccountType.Corr, Status.Active, Allowed.ALLOWED); + if (acc1 != null) { + payment1.setDebitLegAccountId(acc1.getId()); + payment1.setDebitLegAccount(acc1.getAccount()); + } + } + + payment1.setDebitCsAccount(null); + +// payment1.setCreditLegDirection(InOutDirection.out.getKey()); +// payment1.setDebitLegDirection(InOutDirection.in.getKey()); + + payment1.setCreditLegCurrencyCode(liabilitiesClaimsAssets.getCurrency()); + payment1.setDebitLegCurrencyCode(liabilitiesClaimsAssets.getCurrency()); + + payment1.setTransactionStatus(TransactionStatus.stld.getKey()); + + + payment1.setDocumentNumber(nextDocumentNumber(liabilitiesClaimsAssets, payment1)); + + newPaymentInstructions.add(payment1); + } else // Для V,B только 1 PaymentInstruction + if (clearingCategory.contains(ClearingCategory.B)) { + log.debug("By liabilitiesClaimsAssets[{}] create for category B 1 record", liabilitiesClaimsAssets.getId()); + PaymentInstruction payment1 = new PaymentInstruction(); + payment1.setId(idGenerator.nextId()); + payment1.setCreated(now); + payment1.setClearingDate(TimeUtil.toLocalDate(now)); + + payment1.setSenderId(liabilitiesClaimsAssets.getCompanyId()); + + payment1.setAddresseeId(SPVB_ID); // СПВБ + + String symbol1 = selectSymbolValue(payment1.getAddresseeId(), CompanySymbol.BIC); + if (symbol1 == null) { + log.warn("CompanySymbols BIC not found for companyId={}", payment1.getAddresseeId()); + } else { + payment1.setAdresseeBic(symbol1); + } + + Company companyPRC = companyImdg.getSingleObjectByID(PRC_ID); // 2 "НКО АО ПРЦ" + String companyPRCName = null; + if (companyPRC == null) { + log.warn("Company.id=2 not found"); + } else { + companyPRCName = companyPRC.getShortName(); + } + payment1.setPayeeBankName(companyPRCName); + + String symbolPRC = selectSymbolValue(PRC_ID, CompanySymbol.BIC); // 2 "НКО АО ПРЦ" + payment1.setPayeeBic(symbolPRC); + + payment1.setAddresseeBankName(companyPRCName); + + payment1.setPaymentDate(TimeUtil.localDateToInstant(liabilitiesClaimsAssets.getSettlementDate())); + + payment1.setPaymentPurpose("Размещение депозита " + liabilitiesClaimsAssets.getContract()); + + payment1.setSettlementDate(liabilitiesClaimsAssets.getSettlementDate()); + + Long amount = liabilitiesClaimsAssets.getLiabilitiesQuantity() == null ? null : liabilitiesClaimsAssets.getLiabilitiesQuantity().abs().longValue(); + payment1.setCreditLegAmount(amount); + payment1.setDebitLegAmount(amount); + + { + String accSql = String.format("companyId = %s AND accountType=ANLT AND accountStatus=ACTV AND processingSign=ALWD", + payment1.getSenderId()); + Account acc1 = accountImdg.getSingleObjectBySQL(accSql); + if (acc1 == null) { + log.warn("Account not found: {}", accSql); + } else { + payment1.setCreditLegAccountId(acc1.getId()); + payment1.setCreditLegAccount(acc1.getAccount()); + } + } + + payment1.setCreditCsAccount(null); + + { + Account acc1 = selectAccount(payment1.getAddresseeId(), AccountType.Corr, Status.Active, Allowed.ALLOWED); + if (acc1 != null) { + payment1.setDebitLegAccountId(acc1.getId()); + payment1.setDebitLegAccount(acc1.getAccount()); + } + } + + payment1.setDebitCsAccount(null); + +// payment1.setCreditLegDirection(InOutDirection.out.getKey()); +// payment1.setDebitLegDirection(InOutDirection.in.getKey()); + + payment1.setCreditLegCurrencyCode(liabilitiesClaimsAssets.getCurrency()); + payment1.setDebitLegCurrencyCode(liabilitiesClaimsAssets.getCurrency()); + + payment1.setTransactionStatus(TransactionStatus.stld.getKey()); + + + payment1.setDocumentNumber(nextDocumentNumber(liabilitiesClaimsAssets, payment1)); + + newPaymentInstructions.add(payment1); + } } - //todo сочетания типов??? Другие типы return newPaymentInstructions; } protected String nextDocumentNumber(LiabilitiesClaimsAssets liabilitiesClaimsAssets, PaymentInstruction paymentInstruction) { - if (documentNumberResetAt == null || documentNumberResetAt.isBefore(LocalDate.now())) { - documentNumberId.set(0); - documentNumberResetAt = LocalDate.now(); + LocalDate nowD = LocalDate.now(); + if (documentNumberResetAt == null || documentNumberResetAt.isBefore(nowD)) synchronized (this){ + long oldNum = documentNumberId.get(); // reset optimistic + if (oldNum > 0) { + while (!documentNumberId.compareAndSet(oldNum, 0)) { + oldNum = documentNumberId.get(); + if (oldNum < 2) break; + } + } + documentNumberResetAt = nowD; } DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ddMMyy"); - String num = String.format("%s/%s/%s/", + String num = String.format("%s/%s/%s/%s", liabilitiesClaimsAssets.getContract(), formatter.format(paymentInstruction.getPaymentDate()), paymentInstruction.getSenderId(), documentNumberId.incrementAndGet() ); diff --git a/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/order/PaymentInstructionCreatorTest.java b/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/order/PaymentInstructionCreatorTest.java new file mode 100644 index 000000000..6e4c63700 --- /dev/null +++ b/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/order/PaymentInstructionCreatorTest.java @@ -0,0 +1,29 @@ +package ru.spcex.clearing.service.order; + +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsAssets; +import ru.clearing.classes.statics.data.payment.PaymentInstruction; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.utils.time.TimeUtil; + +import java.time.LocalDate; + +import static org.junit.jupiter.api.Assertions.*; + +class PaymentInstructionCreatorTest { + + @Test + void nextDocumentNumber() { + ImdgProvider nullImdg = Mockito.mock(ImdgProvider.class); + PaymentInstructionCreator instance = new PaymentInstructionCreator(nullImdg); + LiabilitiesClaimsAssets liabilitiesClaimsAssets = new LiabilitiesClaimsAssets(); + liabilitiesClaimsAssets.setContract("contract"); + PaymentInstruction paymentInstruction = new PaymentInstruction(); + paymentInstruction.setPaymentDate(TimeUtil.localDateToInstant(LocalDate.of(2023,1,4))); + paymentInstruction.setSenderId(1234L); + assertEquals("contract/230104/1234/1", instance.nextDocumentNumber(liabilitiesClaimsAssets, paymentInstruction)); + assertEquals("contract/230104/1234/2", instance.nextDocumentNumber(liabilitiesClaimsAssets, paymentInstruction)); + assertEquals("contract/230104/1234/3", instance.nextDocumentNumber(liabilitiesClaimsAssets, paymentInstruction)); + } +} \ No newline at end of file diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/AccountType.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/AccountType.java index 7c9d342b3..43d0ceebc 100644 --- a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/AccountType.java +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/AccountType.java @@ -3,7 +3,7 @@ package ru.spcex.platform.enumeration; import ru.spcex.platform.utils.enumeration.IEnumKey; public enum AccountType implements IEnumKey { - Clrn("CLRN"), Bank("BANK"), Info("INFO"), Tran("TRAN"); + Clrn("CLRN"), Bank("BANK"), Info("INFO"), Tran("TRAN"), Corr("CORR"); private final String key; From 1debfd81da971fa862618ec43fef17cb9de0eb8c Mon Sep 17 00:00:00 2001 From: AKurakin Date: Wed, 1 Feb 2023 20:06:23 +0300 Subject: [PATCH 21/42] =?UTF-8?q?clearing-service=20http://jira.mfd.msk:80?= =?UTF-8?q?88/browse/CLS-189=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20PaymentInstruction...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/order/PaymentInstructionCreator.java | 9 +++++---- .../service/order/PaymentInstructionCreatorTest.java | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentInstructionCreator.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentInstructionCreator.java index 950e3c7a3..94761ff50 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentInstructionCreator.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentInstructionCreator.java @@ -29,6 +29,7 @@ import java.util.concurrent.atomic.AtomicLong; public class PaymentInstructionCreator { protected static final Long SPVB_ID = 1L; // СПВБ protected static final Long PRC_ID = 2L; // 2 "НКО АО ПРЦ" + private static final DateTimeFormatter DATE_FORMATTER_ddMMyy = DateTimeFormatter.ofPattern("ddMMyy"); private final Logger log = LoggerFactory.getLogger(getClass()); @@ -39,7 +40,7 @@ public class PaymentInstructionCreator { protected final Imdg accountImdg; protected final Imdg paymentInstructionImdg; - protected AtomicLong documentNumberId = new AtomicLong(); // порядковый номер (сквозной по всем компаниям за день + protected AtomicLong documentNumberId = new AtomicLong(0L); // порядковый номер (сквозной по всем компаниям за день protected LocalDate documentNumberResetAt; @Autowired @@ -379,7 +380,7 @@ public class PaymentInstructionCreator { protected String nextDocumentNumber(LiabilitiesClaimsAssets liabilitiesClaimsAssets, PaymentInstruction paymentInstruction) { LocalDate nowD = LocalDate.now(); - if (documentNumberResetAt == null || documentNumberResetAt.isBefore(nowD)) synchronized (this){ + if (documentNumberResetAt == null || documentNumberResetAt.isBefore(nowD)) synchronized (this) { long oldNum = documentNumberId.get(); // reset optimistic if (oldNum > 0) { while (!documentNumberId.compareAndSet(oldNum, 0)) { @@ -389,9 +390,9 @@ public class PaymentInstructionCreator { } documentNumberResetAt = nowD; } - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ddMMyy"); + String paymentDate = DATE_FORMATTER_ddMMyy.format(TimeUtil.toLocalDate(paymentInstruction.getPaymentDate())); String num = String.format("%s/%s/%s/%s", - liabilitiesClaimsAssets.getContract(), formatter.format(paymentInstruction.getPaymentDate()), + liabilitiesClaimsAssets.getContract(), paymentDate, paymentInstruction.getSenderId(), documentNumberId.incrementAndGet() ); return num; diff --git a/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/order/PaymentInstructionCreatorTest.java b/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/order/PaymentInstructionCreatorTest.java index 6e4c63700..f5a632ab1 100644 --- a/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/order/PaymentInstructionCreatorTest.java +++ b/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/order/PaymentInstructionCreatorTest.java @@ -22,8 +22,8 @@ class PaymentInstructionCreatorTest { PaymentInstruction paymentInstruction = new PaymentInstruction(); paymentInstruction.setPaymentDate(TimeUtil.localDateToInstant(LocalDate.of(2023,1,4))); paymentInstruction.setSenderId(1234L); - assertEquals("contract/230104/1234/1", instance.nextDocumentNumber(liabilitiesClaimsAssets, paymentInstruction)); - assertEquals("contract/230104/1234/2", instance.nextDocumentNumber(liabilitiesClaimsAssets, paymentInstruction)); - assertEquals("contract/230104/1234/3", instance.nextDocumentNumber(liabilitiesClaimsAssets, paymentInstruction)); + assertEquals("contract/040123/1234/1", instance.nextDocumentNumber(liabilitiesClaimsAssets, paymentInstruction)); + assertEquals("contract/040123/1234/2", instance.nextDocumentNumber(liabilitiesClaimsAssets, paymentInstruction)); + assertEquals("contract/040123/1234/3", instance.nextDocumentNumber(liabilitiesClaimsAssets, paymentInstruction)); } } \ No newline at end of file From 75c4e7aeae6662bcfe22ea81d400abef563bdd94 Mon Sep 17 00:00:00 2001 From: ialbert Date: Wed, 1 Feb 2023 20:52:25 +0300 Subject: [PATCH 22/42] http://jira.mfd.msk:8088/browse/CLS-189 --- .../service/AccountBalanceService.java | 91 +++++++++++++++++++ .../balance/service/StatementService.java | 12 ++- .../ru/spcex/clearing/service/Clearing.java | 59 ++++++++++-- .../platform/enumeration/AccountType.java | 2 +- .../platform/messaging/domain/Consts.java | 1 + .../AccountBalanceClearingRequest.java | 38 ++++++++ 6 files changed, 194 insertions(+), 9 deletions(-) create mode 100644 platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/balance/AccountBalanceClearingRequest.java diff --git a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java index daa2280dc..4825ffb64 100644 --- a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java +++ b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java @@ -5,13 +5,18 @@ import org.springframework.stereotype.Component; 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.generated.ClearingMemberCategory; import ru.spcex.clearing.balance.validation.AccountBalanceValidation; import ru.spcex.clearing.balance.validation.ValidationStored; import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.cud.balance.AccountBalanceClearingRequest; +import ru.spcex.platform.enumeration.AccountType; import ru.spcex.platform.enumeration.BalanceAccountType; +import ru.spcex.platform.enumeration.ClearingCategory; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.utils.enumeration.EnumMessage; +import ru.spcex.platform.utils.enumeration.IEnumKey; import ru.spcex.platform.utils.validation.IValidator; import java.math.BigDecimal; @@ -26,12 +31,14 @@ public class AccountBalanceService { private final ImdgProvider imdgProvider; private final Imdg accountBalanceImdg; private final Function validationFactory; + private final Imdg clearingCategoryImdg; public AccountBalanceService(ImdgProvider imdgProvider, @Qualifier("accountBalanceValidator") Function validationFactory) { this.imdgProvider = imdgProvider; this.validationFactory = validationFactory; this.accountBalanceImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_AccountBalance, AccountBalance.class); + this.clearingCategoryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class); } public AccountResult createAccountBalance(Long addresseeId, Long accountId, BigDecimal amount, @@ -85,4 +92,88 @@ public class AccountBalanceService { if (b == null) return a; return a.add(b); } + + public void updateAccountBalanceByClearing(AccountBalanceClearingRequest req) { + ClearingCategory category = getClearingCategoryByCompanyId(req.getCompanyId()); + if (category.equals(ClearingCategory.I)) { + updateAccountCategoryIClrn(req.getAccountId(), req.getCompanyId(), req.getFirstLegAmount()); + updateAccountCategoryITran(req.getFirstLegAmount()); + } else if (category.equals(ClearingCategory.V)) { + updateAccountCategoryVInfo(req.getAccountId(), req.getCompanyId(), req.getFirstLegAmount()); + updateAccountCategoryVAnlt(req.getFirstLegAmount()); + } else if (category.equals(ClearingCategory.B)) { + updateAccountCategoryBClrn(req.getAccountId(), req.getCompanyId(), req.getFirstLegAmount()); + } + //todo send message success to Kafka + } + + private ClearingCategory getClearingCategoryByCompanyId(Long companyId) { + ClearingMemberCategory category = clearingCategoryImdg.getSingleObjectByFieldValues( + Map.of("companyId", companyId)); + return IEnumKey.getEnumByKey(ClearingCategory.class, + category.getClearingMemberCategory()); + } + + private void updateAccountCategoryIClrn(Long accountId, Long companyId, BigDecimal firstLegAmount) { + AccountBalance accountBalance = loadAccountBalance(accountId, companyId, AccountType.Clrn); + BigDecimal previousFreeBalanceAmount = accountBalance.getFreeBalanceAmount(); + BigDecimal resultFreeBalanceAmount = previousFreeBalanceAmount.subtract(firstLegAmount); + accountBalance.setFreeBalanceAmount(resultFreeBalanceAmount); + accountBalance.setChangeBalanceAmount(resultFreeBalanceAmount); + accountBalance.setBalanceAmount(resultFreeBalanceAmount); + accountBalance.setUpdated(Instant.now()); + accountBalanceImdg.update(accountBalance); + } + + private void updateAccountCategoryITran(BigDecimal firstLegAmount) { + AccountBalance accountBalance = loadAccountBalance(AccountType.Tran); + BigDecimal freeBalanceAmount = accountBalance.getFreeBalanceAmount(); + accountBalance.setFreeBalanceAmount(freeBalanceAmount.add(firstLegAmount.abs())); + accountBalance.setUpdated(Instant.now()); + accountBalanceImdg.update(accountBalance); + } + + private void updateAccountCategoryVInfo(Long accountId, Long companyId, BigDecimal firstLegAmount) { + AccountBalance accountBalance = loadAccountBalance(accountId, companyId, AccountType.Info); + BigDecimal previousFreeBalanceAmount = accountBalance.getFreeBalanceAmount(); + BigDecimal resultFreeBalanceAmount = previousFreeBalanceAmount.subtract(firstLegAmount); + accountBalance.setFreeBalanceAmount(resultFreeBalanceAmount); + accountBalance.setChangeBalanceAmount(resultFreeBalanceAmount); + accountBalance.setBalanceAmount(resultFreeBalanceAmount); + accountBalance.setUpdated(Instant.now()); + accountBalanceImdg.update(accountBalance); + } + + private void updateAccountCategoryVAnlt(BigDecimal firstLegAmount) { + AccountBalance accountBalance = loadAccountBalance(AccountType.Anlt); + BigDecimal previousFreeBalanceAmount = accountBalance.getFreeBalanceAmount(); + BigDecimal resultFreeBalanceAmount = previousFreeBalanceAmount.subtract(firstLegAmount); + accountBalance.setFreeBalanceAmount(resultFreeBalanceAmount); + accountBalance.setChangeBalanceAmount(resultFreeBalanceAmount); + accountBalance.setBalanceAmount(resultFreeBalanceAmount); + accountBalance.setUpdated(Instant.now()); + accountBalanceImdg.update(accountBalance); + } + + private void updateAccountCategoryBClrn(Long accountId, Long companyId, BigDecimal firstLegAmount) { + AccountBalance accountBalance = loadAccountBalance(accountId, companyId, AccountType.Clrn); + BigDecimal freeBalanceAmount = accountBalance.getFreeBalanceAmount(); + accountBalance.setDebitAmount(plus(freeBalanceAmount, firstLegAmount.abs())); + accountBalance.setUpdated(Instant.now()); + accountBalanceImdg.update(accountBalance); + } + + private AccountBalance loadAccountBalance(Long accountId, Long companyId, AccountType type) { + return accountBalanceImdg.getSingleObjectByFieldValues( + Map.of("accountId", accountId, "companyId", companyId, + "accountType", type.getKey()) + ); + } + + private AccountBalance loadAccountBalance(AccountType type) { + return accountBalanceImdg.getSingleObjectByFieldValues( + Map.of("companyId", 1L, + "accountType", type.getKey()) + ); + } } 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 1cc0e0575..9bedcb348 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 @@ -15,6 +15,7 @@ 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.service.QueueConsumer; @@ -38,14 +39,16 @@ public class StatementService extends QueueConsumer implements InitializingBean 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) { + @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; @@ -59,9 +62,16 @@ public class StatementService extends QueueConsumer implements InitializingBean 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); init(); } + private void accountBalanceClearingUpdate(BaseRequest updateAccBalanceReq) { + accountBalanceService.updateAccountBalanceByClearing(updateAccBalanceReq.getRequestPayload()); + } + private void process(BaseRequest systemRequest) { StatementRequest statementRequest = systemRequest.getRequestPayload(); Collection sdfGroup; diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java index 3406f3383..d852259b0 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java @@ -12,15 +12,13 @@ import ru.spcex.clearing.service.order.ExecutionDepositSorter; import ru.spcex.platform.enumeration.Allowed; import ru.spcex.platform.enumeration.ClearingCategory; 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.utils.enumeration.EnumMessage; import ru.spcex.platform.utils.validation.IValidator; import java.time.Instant; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Optional; +import java.util.*; import java.util.function.BiFunction; @Service @@ -30,6 +28,13 @@ public class Clearing { private final Imdg clearingCategoryImdg; private final ExecutionDepositSorter sorter; private final BiFunction validation; + private final ImdgId idProvider; + //при прохождении по выгруженным ExecutionDeposit, ошибочные статусы проставляются для + //контр сделок. В таком случае, в коллекции хранятся не синхронизированные с IMDG ExecutionDeposit + //для которых статус должен быть DENIED + //************ !!! NOT THREAD SAFE !!! ************ + private final Set deniedIds = new HashSet<>(); + private Long clearingSessionId; @Autowired public Clearing(ImdgProvider imdgProvider, @@ -37,11 +42,13 @@ public class Clearing { BiFunction validation) { this.executionDepositImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionDeposit, ExecutionDeposit.class); this.clearingCategoryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class); + this.idProvider = imdgProvider.getImdgIdGenerator(); this.sorter = sorter; this.validation = validation; } public void startClearing() { + clearingSessionId = idProvider.nextId(); //выгружаем ExecutionDeposit с пустым sessionId Collection execDeposits = executionDepositImdg.getCollectionObjectsBySQL("sessionId = null"); //делаем группировку ExecutionDeposit по категории и компании, делаем сортировку @@ -49,15 +56,29 @@ public class Clearing { executionDeposits.forEach((category, companies) -> { for (List companyExecDeposits : companies) { - processSingleCompany(category, companyExecDeposits); + runChecksSetStatus(category, companyExecDeposits); + } + }); + executionDeposits.forEach((category, companies) -> { + for (List companyExecDeposits : companies) { + processAllowedExecutionDeposit(category, companyExecDeposits); } }); } - private void processSingleCompany(ClearingCategory category, List executionDeposits) { - log.info("Start clearing for category: {}, company: {}", category, executionDeposits.get(0).getCompanyId()); + //кладем в порядке I инициатор, V внутренний, B банк (ответная категория) + //получается I -> B; V -> B + // + //1) ТОЛЬКО ДЛЯ V: если DENIED по любым причинам то для всех следующих сделок этой компании DENIED + //2) DENIED сделка всегда встречная сделка тоже делается DENIED + //3) DENIED может быть для сделки которая уже прошла обработку и стала ALLOWED + private void runChecksSetStatus(ClearingCategory category, List executionDeposits) { + log.info("setting statuses for category: {}, company: {}", category, executionDeposits.get(0).getCompanyId()); boolean financialError = false; for (ExecutionDeposit execDeposit : executionDeposits) { + if (deniedIds.contains(execDeposit.getId())) { + continue; + } if (financialError) { updateDenied(execDeposit); continue; @@ -80,6 +101,17 @@ public class Clearing { execDeposit.setCoverageStatus(Allowed.DENIED.getKey()); execDeposit.setUpdated(Instant.now()); executionDepositImdg.update(execDeposit); + //также необходимо установить статус DEND встречной сделке контрагента этой компании, которая выбирается из executionDeposit по ключу: + //securityId И чтобы сделка была компании категории clearingMemberCategory.clearingMemberCategory ≠ той категории, сделка которой обрабатывается в настоящий момент. + ExecutionDeposit matchedExecDeposit = executionDepositImdg.getSingleObjectBySQL( + "securityId = " + execDeposit.getSecurityId() + + " AND companyId != " + execDeposit.getCompanyId()); + if (matchedExecDeposit != null) { + matchedExecDeposit.setCoverageStatus(Allowed.DENIED.getKey()); + matchedExecDeposit.setUpdated(Instant.now()); + executionDepositImdg.update(matchedExecDeposit); + deniedIds.add(matchedExecDeposit.getId()); + } } private void updateAllowed(ExecutionDeposit execDeposit) { @@ -87,4 +119,17 @@ public class Clearing { execDeposit.setUpdated(Instant.now()); executionDepositImdg.update(execDeposit); } + + private void processAllowedExecutionDeposit(ClearingCategory category, List executionDeposits) { + log.info("running clearing for category: {}, company: {}", category, executionDeposits.get(0).getCompanyId()); + for (ExecutionDeposit execDeposit : executionDeposits) { + if (deniedIds.contains(execDeposit.getId())) { + continue; + } + if (!Allowed.ALLOWED.getKey().equals(execDeposit.getCoverageStatus())) { + continue; + } + + } + } } diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/AccountType.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/AccountType.java index fa04d58a6..0cff3a8e3 100644 --- a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/AccountType.java +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/AccountType.java @@ -3,7 +3,7 @@ package ru.spcex.platform.enumeration; import ru.spcex.platform.utils.enumeration.IEnumKey; public enum AccountType implements IEnumKey { - Clrn("CLRN"), Bank("BANK"), Info("INFO"); + Clrn("CLRN"), Bank("BANK"), Info("INFO"), Tran("TRAN"), Anlt("ANLT"); private final String key; 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 552594f41..fd95ea1ad 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 @@ -50,6 +50,7 @@ public interface Consts { String EXPORT_PROCESS = "export-process"; String ACCOUNT_NEW = "account-new"; String BALANCE_ACCOUNT_NEW = "balance-account-new"; + String BALANCE_ACCOUNT_UPDATE = "balance-account-update"; String LAUNCHER_NEW = "launcher-new"; String NOTIFICATION_NEW = "notification-new"; diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/balance/AccountBalanceClearingRequest.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/balance/AccountBalanceClearingRequest.java new file mode 100644 index 000000000..9748adff5 --- /dev/null +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/balance/AccountBalanceClearingRequest.java @@ -0,0 +1,38 @@ +package ru.spcex.clearing.platform.messaging.domain.cud.balance; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.math.BigDecimal; + +public class AccountBalanceClearingRequest { + @JsonProperty + private Long accountId; + @JsonProperty + private Long companyId; + @JsonProperty + private BigDecimal firstLegAmount; + + public Long getAccountId() { + return accountId; + } + + public void setAccountId(Long accountId) { + this.accountId = accountId; + } + + public Long getCompanyId() { + return companyId; + } + + public void setCompanyId(Long companyId) { + this.companyId = companyId; + } + + public BigDecimal getFirstLegAmount() { + return firstLegAmount; + } + + public void setFirstLegAmount(BigDecimal firstLegAmount) { + this.firstLegAmount = firstLegAmount; + } +} \ No newline at end of file From 8e787597131e3336f9610f912151c34079702521 Mon Sep 17 00:00:00 2001 From: ialbert Date: Thu, 2 Feb 2023 14:08:27 +0300 Subject: [PATCH 23/42] http://jira.mfd.msk:8088/browse/CLS-189 --- .../clearing/balance/config/KafkaConfig.java | 25 ++++++++++++++- .../balance/config/KafkaSenderConfig.java | 31 ------------------- .../service/SdfCreatorBySTLDPayment.java | 4 +-- .../PaymentInstructionCreator.java | 2 +- .../{order => builder}/Sdf03Builder.java | 2 +- .../{order => builder}/Sdf11Builder.java | 2 +- .../PaymentInstructionCreatorTest.java | 4 +-- 7 files changed, 31 insertions(+), 39 deletions(-) delete mode 100644 clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/config/KafkaSenderConfig.java rename clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/{order => builder}/PaymentInstructionCreator.java (99%) rename clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/{order => builder}/Sdf03Builder.java (98%) rename clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/{order => builder}/Sdf11Builder.java (98%) rename clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/{order => builder}/PaymentInstructionCreatorTest.java (92%) diff --git a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/config/KafkaConfig.java b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/config/KafkaConfig.java index d1c48b183..1e14bcf54 100644 --- a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/config/KafkaConfig.java +++ b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/config/KafkaConfig.java @@ -3,13 +3,20 @@ package ru.spcex.clearing.balance.config; import org.apache.kafka.clients.consumer.Consumer; import org.apache.kafka.clients.producer.Producer; 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.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; import ru.spcex.clearing.balance.config.element.BalanceServiceSettings; +import ru.spcex.clearing.imdg.IMDGDistributedNames; 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 { @@ -21,8 +28,24 @@ public class KafkaConfig { } @Autowired - @Bean + @Bean("kafkaProducer") public Producer createProducer(BalanceServiceSettings settings) { return KafkaProducerFactory.producer(settings.getKafkaProducer()); } + + @Autowired + @Bean + public KafkaSender kafkaSender(@Qualifier("kafkaProducer") Producer kafkaProducer, + ImdgProvider imdgProvider) { + ImdgId imdgIdGenerator = imdgProvider.getImdgIdGenerator(); + return KafkaSender + .setup() + .producer(kafkaProducer) + .idGenerator(imdgIdGenerator::nextId) + .imdgProvider(s -> { + Imdg imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_RequestInfo, RequestInfo.class); + return imdg::insert; + }) + .build(); + } } diff --git a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/config/KafkaSenderConfig.java b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/config/KafkaSenderConfig.java deleted file mode 100644 index a32e3bc5e..000000000 --- a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/config/KafkaSenderConfig.java +++ /dev/null @@ -1,31 +0,0 @@ -package ru.spcex.clearing.balance.config; - -import org.apache.kafka.clients.producer.Producer; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import ru.spcex.clearing.imdg.IMDGDistributedNames; -import ru.spcex.clearing.platform.messaging.service.RequestInfo; -import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; -import ru.spcex.platform.imdg.api.Imdg; -import ru.spcex.platform.imdg.api.ImdgId; -import ru.spcex.platform.imdg.api.ImdgProvider; - -@Configuration -public class KafkaSenderConfig { - - @Autowired - @Bean - public KafkaSender kafkaSender(Producer kafkaProducer, ImdgProvider imdgProvider) { - ImdgId imdgIdGenerator = imdgProvider.getImdgIdGenerator(); - return KafkaSender - .setup() - .producer(kafkaProducer) - .idGenerator(imdgIdGenerator::nextId) - .imdgProvider(s -> { - Imdg imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_RequestInfo, RequestInfo.class); - return imdg::insert; - }) - .build(); - } -} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/SdfCreatorBySTLDPayment.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/SdfCreatorBySTLDPayment.java index 9d1f6bd25..cc1b8a607 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/SdfCreatorBySTLDPayment.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/SdfCreatorBySTLDPayment.java @@ -11,10 +11,10 @@ import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.Consts; import ru.spcex.clearing.platform.messaging.domain.cud.clearing.SdfClearingRequest; import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; +import ru.spcex.clearing.service.builder.Sdf03Builder; +import ru.spcex.clearing.service.builder.Sdf11Builder; import ru.spcex.clearing.service.order.PaymentBatchInfo; import ru.spcex.clearing.service.order.PaymentInstructionSorter; -import ru.spcex.clearing.service.order.Sdf03Builder; -import ru.spcex.clearing.service.order.Sdf11Builder; import ru.spcex.platform.enumeration.TransactionStatus; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgId; diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentInstructionCreator.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionCreator.java similarity index 99% rename from clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentInstructionCreator.java rename to clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionCreator.java index 94761ff50..e0dba4ea3 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentInstructionCreator.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionCreator.java @@ -1,4 +1,4 @@ -package ru.spcex.clearing.service.order; +package ru.spcex.clearing.service.builder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/Sdf03Builder.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/Sdf03Builder.java similarity index 98% rename from clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/Sdf03Builder.java rename to clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/Sdf03Builder.java index d91755610..628619fd0 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/Sdf03Builder.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/Sdf03Builder.java @@ -1,4 +1,4 @@ -package ru.spcex.clearing.service.order; +package ru.spcex.clearing.service.builder; import ru.clearing.classes.statics.data.payment.PaymentInstruction; import ru.clearing.classes.statics.data.sdf.SDf03; diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/Sdf11Builder.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/Sdf11Builder.java similarity index 98% rename from clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/Sdf11Builder.java rename to clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/Sdf11Builder.java index c609b133e..6818a776a 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/Sdf11Builder.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/Sdf11Builder.java @@ -1,4 +1,4 @@ -package ru.spcex.clearing.service.order; +package ru.spcex.clearing.service.builder; import ru.clearing.classes.statics.data.payment.PaymentInstruction; import ru.clearing.classes.statics.data.sdf.SDf11; diff --git a/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/order/PaymentInstructionCreatorTest.java b/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/builder/PaymentInstructionCreatorTest.java similarity index 92% rename from clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/order/PaymentInstructionCreatorTest.java rename to clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/builder/PaymentInstructionCreatorTest.java index f5a632ab1..3013ee2d9 100644 --- a/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/order/PaymentInstructionCreatorTest.java +++ b/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/builder/PaymentInstructionCreatorTest.java @@ -1,4 +1,4 @@ -package ru.spcex.clearing.service.order; +package ru.spcex.clearing.service.builder; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -9,7 +9,7 @@ import ru.spcex.platform.utils.time.TimeUtil; import java.time.LocalDate; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; class PaymentInstructionCreatorTest { From 68c74360d5a7412dd61578d746d83fa00e69023b Mon Sep 17 00:00:00 2001 From: AKurakin Date: Thu, 2 Feb 2023 14:22:48 +0300 Subject: [PATCH 24/42] =?UTF-8?q?balance-service=20=D0=BF=D0=BE=D0=BF?= =?UTF-8?q?=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=20=D1=8E=D0=BD=D0=B8=D1=82=D1=82?= =?UTF-8?q?=D0=B5=D1=81=D1=82=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=208e7875971?= =?UTF-8?q?31e3336f9610f912151c34079702521?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../balance/config/KafkaTestConfig.java | 23 +++++++++++++++++++ .../balance/service/AbstractServiceTest.java | 1 - 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/clearing-parent/balance-service/src/test/java/ru/spcex/clearing/balance/config/KafkaTestConfig.java b/clearing-parent/balance-service/src/test/java/ru/spcex/clearing/balance/config/KafkaTestConfig.java index b56fef2b1..962b45615 100644 --- a/clearing-parent/balance-service/src/test/java/ru/spcex/clearing/balance/config/KafkaTestConfig.java +++ b/clearing-parent/balance-service/src/test/java/ru/spcex/clearing/balance/config/KafkaTestConfig.java @@ -5,9 +5,16 @@ import org.apache.kafka.clients.consumer.OffsetResetStrategy; import org.apache.kafka.clients.producer.MockProducer; import org.apache.kafka.clients.producer.Producer; import org.apache.kafka.common.serialization.StringSerializer; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.serialization.JsonSerializer; +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 KafkaTestConfig { @@ -21,4 +28,20 @@ public class KafkaTestConfig { public Producer createTestProducer() { return new MockProducer<>(true, new StringSerializer(), new JsonSerializer()); } + + + @Autowired + @Bean + public KafkaSender kafkaSender(Producer kafkaProducer, ImdgProvider imdgProvider) { + ImdgId imdgIdGenerator = imdgProvider.getImdgIdGenerator(); + return KafkaSender + .setup() + .producer(kafkaProducer) + .idGenerator(imdgIdGenerator::nextId) + .imdgProvider(s -> { + Imdg imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_RequestInfo, RequestInfo.class); + return imdg::insert; + }) + .build(); + } } diff --git a/clearing-parent/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 1b1aad983..06739ae92 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 @@ -42,7 +42,6 @@ import static ru.spcex.clearing.balance.utils.MatcherFactory.usingIgnoringFields ValidationConfig.class, SdfExecutorsConfig.class, BalanceImdgTestConfig.class, - KafkaSenderConfig.class, KafkaTestConfig.class}) public abstract class AbstractServiceTest { protected static final MatcherFactory.Matcher ACCOUNT_BALANCE_MATCHER = usingIgnoringFieldsComparator("created", "updated", "clearingDate", "id"); From 118ad70db00faa647d251087291666c1d73fd93b Mon Sep 17 00:00:00 2001 From: AKurakin Date: Thu, 2 Feb 2023 14:31:17 +0300 Subject: [PATCH 25/42] =?UTF-8?q?clearing-service=20http://jira.mfd.msk:80?= =?UTF-8?q?88/browse/CLS-189=20=D0=B4=D0=BE=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB?= =?UTF-8?q?=202.2.2.2,=20=D0=BE=D1=81=D1=82=D0=B0=D0=BB=D0=BE=D1=81=D1=8C?= =?UTF-8?q?=20=D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D0=BD=D0=B8=D1=82=D1=8C=20(?= =?UTF-8?q?=D0=B2=D1=8B=D0=B7=D0=B2=D0=B0=D1=82=D1=8C)=202.2.2=20=D0=B8=20?= =?UTF-8?q?=D0=B4=D0=BE=D0=BF=D0=B8=D1=81=D0=B0=D1=82=D1=8C=20=D0=BD=D0=B0?= =?UTF-8?q?=D1=87=D0=B0=D0=BB=D0=BE.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ru/spcex/clearing/service/Clearing.java | 2 +- .../builder/PaymentInstructionCreator.java | 122 +++++++++++++++++- 2 files changed, 122 insertions(+), 2 deletions(-) diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java index ade3a551f..935866921 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java @@ -11,7 +11,7 @@ import ru.clearing.classes.statics.data.payment.PaymentInstruction; import ru.spcex.clearing.error.ClearingErrorInternal; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.service.order.ExecutionDepositSorter; -import ru.spcex.clearing.service.order.PaymentInstructionCreator; +import ru.spcex.clearing.service.builder.PaymentInstructionCreator; import ru.spcex.platform.enumeration.Allowed; import ru.spcex.platform.enumeration.ClearingCategory; import ru.spcex.platform.imdg.api.Imdg; diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionCreator.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionCreator.java index e0dba4ea3..dccab61c4 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionCreator.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionCreator.java @@ -8,14 +8,17 @@ import ru.clearing.classes.statics.data.account.Account; import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.company.CompanySymbols; import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsAssets; +import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsMoney; import ru.clearing.classes.statics.data.payment.PaymentInstruction; import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.platform.classes.base.SpcexObjectBase; import ru.spcex.platform.enumeration.*; 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.utils.time.TimeUtil; +import java.math.BigDecimal; import java.time.Instant; import java.time.LocalDate; import java.time.format.DateTimeFormatter; @@ -24,7 +27,15 @@ import java.util.Collection; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; +/* +todo использовать так: + paymentInstructionCreator.createAndSavePaymentInstructions() + paymentInstructionCreator.updateLiabilitiesClaimsAssetsByPaymentInstruction(); + paymentInstructionCreator.updateLiabilitiesClaimsMoneyByPaymentInstruction(); + + */ @Service public class PaymentInstructionCreator { protected static final Long SPVB_ID = 1L; // СПВБ @@ -39,6 +50,7 @@ public class PaymentInstructionCreator { protected final Imdg companyImdg; protected final Imdg accountImdg; protected final Imdg paymentInstructionImdg; + protected final Imdg liabilitiesClaimsMoneyImdg; protected AtomicLong documentNumberId = new AtomicLong(0L); // порядковый номер (сквозной по всем компаниям за день protected LocalDate documentNumberResetAt; @@ -50,10 +62,14 @@ public class PaymentInstructionCreator { this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class); this.accountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class); this.paymentInstructionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_PaymentInstruction, PaymentInstruction.class); + this.liabilitiesClaimsMoneyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_LiabilitiesClaimsMoney, LiabilitiesClaimsMoney.class); this.idGenerator = imdgProvider.getImdgIdGenerator(); } - // 2.2.2 + /** + * 2.2.2. Выполнить Создание paymentInstruction по liabilitiesClaimsAssets + * @return Созданные PaymentInstruction, может быть несколько. Они уже сохранены в IMDG. + */ public List createAndSavePaymentInstructions(LiabilitiesClaimsAssets liabilitiesClaimsAssets, Collection clearingCategory) { List newPaymentInstructions = createPaymentInstructions(liabilitiesClaimsAssets, clearingCategory); @@ -420,4 +436,108 @@ public class PaymentInstructionCreator { } + /** + * 2.2.2.1. Выполнить Изменение liabilitiesClaimsAssets по paymentInstruction. + */ + public LiabilitiesClaimsAssets updateLiabilitiesClaimsAssetsByPaymentInstruction(LiabilitiesClaimsAssets liabilitiesClaimsAssets, + List paymentInstructions, + Collection clearingCategory) { + Long lId = liabilitiesClaimsAssets.getId(); + log.debug("Update LiabilitiesClaimsAssets[{}] by paymentInstructions {}", lId, paymentInstructions.stream().map(SpcexObjectBase::getId).collect(Collectors.toList())); + liabilitiesClaimsAssets = liabilitiesClaimsAssetsImdg.getSingleObjectByID(lId); // update data for update + if (liabilitiesClaimsAssets == null) { + throw new RuntimeException("IMDG not contains liabilitiesClaimsAssets.id=" + lId); + } + + updateFieldLiabilitiesClaimsAssetsByPayment(liabilitiesClaimsAssets, paymentInstructions, clearingCategory); + + liabilitiesClaimsAssetsImdg.update(liabilitiesClaimsAssets); + return liabilitiesClaimsAssets; + } + + protected void updateFieldLiabilitiesClaimsAssetsByPayment(LiabilitiesClaimsAssets liabilitiesClaimsAssets, + List paymentInstructions, + Collection clearingCategory) { + + PaymentInstruction paymentIAny=paymentInstructions.iterator().next(); + + if (clearingCategory.contains(ClearingCategory.I) || clearingCategory.contains(ClearingCategory.V)) { + BigDecimal amount = paymentIAny.getCreditLegAmount() == null ? BigDecimal.ZERO : new BigDecimal((Long)paymentIAny.getCreditLegAmount()); +// При обновлении (по paymentInstruction и категория I и счет CLRN):=liabilitiesClaimsAssets.liabilitiesQuantity - paymentInstruction.creditLeg_amount +// При обновлении (по paymentInstruction и категория V и счет INFO):=liabilitiesClaimsAssets.liabilitiesQuantity - paymentInstruction.creditLeg_amount + amount = liabilitiesClaimsAssets.getLiabilitiesQuantity().subtract(amount); + liabilitiesClaimsAssets.setLiabilitiesQuantity(amount); + } + if (clearingCategory.contains(ClearingCategory.B)) { + BigDecimal amount = paymentIAny.getCreditLegAmount() == null ? BigDecimal.ZERO : new BigDecimal((Long)paymentIAny.getCreditLegAmount()); + // При обновлении (по paymentInstruction и категория B и счет CLRN): из paymentInstruction.creditLeg_amount + liabilitiesClaimsAssets.setLiabilitiesQuantity(amount); + } + + if (clearingCategory.contains(ClearingCategory.I) || clearingCategory.contains(ClearingCategory.V)) { + BigDecimal amount = new BigDecimal((Long)paymentIAny.getDebitLegAmount()); + liabilitiesClaimsAssets.setClaimsQuantity(amount); + } + if (clearingCategory.contains(ClearingCategory.B)) { + BigDecimal amount = new BigDecimal((Long)paymentIAny.getDebitLegAmount()); + amount = liabilitiesClaimsAssets.getClaimsQuantity().subtract(amount); + liabilitiesClaimsAssets.setClaimsQuantity(amount); + } + +// //на базе успешного/неуспешного изменения по paymentInstruction +// if (TransactionStatus.fail.equalsByKey(paymentIAny.getTransactionStatus())) { +// liabilitiesClaimsAssets.setClearingStatus(ClearingStatus.FAIL.getKey()); +// } else if (TransactionStatus.ok.equalsByKey(paymentIAny.getTransactionStatus())) { +// liabilitiesClaimsAssets.setClearingStatus(ClearingStatus.OK.getKey()); +// } + + liabilitiesClaimsAssets.setUpdated(Instant.now()); + } + + + /** + * 2.2.2.2. Выполнить Изменение liabilitiesClaimsMoney по paymentInstruction. + */ + public LiabilitiesClaimsMoney updateLiabilitiesClaimsMoneyByPaymentInstruction(LiabilitiesClaimsAssets liabilitiesClaimsAssets, + List paymentInstructions, + Collection clearingCategory) { + Long lmId = liabilitiesClaimsAssets.getLiabilitiesClaimsMoneyId(); + log.debug("Update LiabilitiesClaimsMoney[{}] by paymentInstructions {}", lmId, paymentInstructions.stream().map(SpcexObjectBase::getId).collect(Collectors.toList())); + LiabilitiesClaimsMoney liabilitiesClaimsMoney = liabilitiesClaimsMoneyImdg.getSingleObjectByID(lmId); // update data for update + if (liabilitiesClaimsAssets == null) { + throw new RuntimeException("IMDG not found LiabilitiesClaimsMoney.id=" + lmId); + } + + updateFieldLiabilitiesClaimsMoneyByPayment(liabilitiesClaimsMoney, liabilitiesClaimsAssets, paymentInstructions, clearingCategory); + + liabilitiesClaimsMoneyImdg.update(liabilitiesClaimsMoney); + return liabilitiesClaimsMoney; + } + + protected boolean updateFieldLiabilitiesClaimsMoneyByPayment(LiabilitiesClaimsMoney liabilitiesClaimsMoney, + LiabilitiesClaimsAssets liabilitiesClaimsAssets, + List paymentInstructions, + Collection clearingCategory) { + boolean modified = false; + boolean isFirstLeg = true; // todo уточню ТЗ и допишу. + + PaymentInstruction paymentIAny=paymentInstructions.iterator().next(); + + if ((clearingCategory.contains(ClearingCategory.I) || clearingCategory.contains(ClearingCategory.V)) && isFirstLeg) { + BigDecimal amount = liabilitiesClaimsMoney.getLiabilitiesAmount().subtract(new BigDecimal((Long)paymentIAny.getCreditLegAmount())); + liabilitiesClaimsMoney.setLiabilitiesAmount(amount); + modified = true; + } + + if ((clearingCategory.contains(ClearingCategory.B)) && isFirstLeg) { + BigDecimal amount = liabilitiesClaimsMoney.getClaimsAmount().subtract(new BigDecimal((Long)paymentIAny.getDebitLegAmount())); + liabilitiesClaimsMoney.setClaimsAmount(amount); + modified = true; + } + + if (modified) { + liabilitiesClaimsMoney.setUpdated(Instant.now()); + } + return modified; + } } From 560ffc160af9483f2c16537c86ac4898868cd35a Mon Sep 17 00:00:00 2001 From: AKurakin Date: Thu, 2 Feb 2023 15:33:59 +0300 Subject: [PATCH 26/42] =?UTF-8?q?clearing-service=20http://jira.mfd.msk:80?= =?UTF-8?q?88/browse/CLS-189=20=D0=B4=D0=BE=D0=B4=D0=B5=D0=BB=D0=BA=D0=B8?= =?UTF-8?q?=202.2.2.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../builder/PaymentInstructionCreator.java | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionCreator.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionCreator.java index dccab61c4..8cff462fe 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionCreator.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionCreator.java @@ -22,10 +22,7 @@ import java.math.BigDecimal; import java.time.Instant; import java.time.LocalDate; import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Collectors; @@ -507,29 +504,38 @@ public class PaymentInstructionCreator { if (liabilitiesClaimsAssets == null) { throw new RuntimeException("IMDG not found LiabilitiesClaimsMoney.id=" + lmId); } - - updateFieldLiabilitiesClaimsMoneyByPayment(liabilitiesClaimsMoney, liabilitiesClaimsAssets, paymentInstructions, clearingCategory); + if (!Objects.equals(liabilitiesClaimsMoney.getSettlementDate(), liabilitiesClaimsAssets.getSettlementDate())) { + log.warn("Date not match: LiabilitiesClaimsMoney[{}].settlementDate={} and LiabilitiesClaimsAssets[{}].settlementDate={}. It is first leg?", + liabilitiesClaimsMoney.getId(), liabilitiesClaimsMoney.getSettlementDate(), liabilitiesClaimsAssets.getId(), liabilitiesClaimsAssets.getSettlementDate() + ); + } + updateFieldLiabilitiesClaimsMoneyByPayment(liabilitiesClaimsMoney, paymentInstructions, clearingCategory); liabilitiesClaimsMoneyImdg.update(liabilitiesClaimsMoney); return liabilitiesClaimsMoney; } + /** + * Обновление liabilitiesClaimsMoney первой ноги по liabilitiesClaimsAssets + * @param liabilitiesClaimsMoney обновить этот объект + * @param paymentInstructions + * @param clearingCategory + * @return были внесены изменения в liabilitiesClaimsMoney + */ protected boolean updateFieldLiabilitiesClaimsMoneyByPayment(LiabilitiesClaimsMoney liabilitiesClaimsMoney, - LiabilitiesClaimsAssets liabilitiesClaimsAssets, List paymentInstructions, Collection clearingCategory) { boolean modified = false; - boolean isFirstLeg = true; // todo уточню ТЗ и допишу. PaymentInstruction paymentIAny=paymentInstructions.iterator().next(); - if ((clearingCategory.contains(ClearingCategory.I) || clearingCategory.contains(ClearingCategory.V)) && isFirstLeg) { + if ((clearingCategory.contains(ClearingCategory.I) || clearingCategory.contains(ClearingCategory.V))) { BigDecimal amount = liabilitiesClaimsMoney.getLiabilitiesAmount().subtract(new BigDecimal((Long)paymentIAny.getCreditLegAmount())); liabilitiesClaimsMoney.setLiabilitiesAmount(amount); modified = true; } - if ((clearingCategory.contains(ClearingCategory.B)) && isFirstLeg) { + if ((clearingCategory.contains(ClearingCategory.B))) { BigDecimal amount = liabilitiesClaimsMoney.getClaimsAmount().subtract(new BigDecimal((Long)paymentIAny.getDebitLegAmount())); liabilitiesClaimsMoney.setClaimsAmount(amount); modified = true; From 21d5fd00045100c73e59b0bedd89d6def4c6ab9c Mon Sep 17 00:00:00 2001 From: ialbert Date: Thu, 2 Feb 2023 15:44:35 +0300 Subject: [PATCH 27/42] http://jira.mfd.msk:8088/browse/CLS-189 --- .../service/AccountBalanceService.java | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java index 4825ffb64..5be5d136b 100644 --- a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java +++ b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java @@ -104,7 +104,6 @@ public class AccountBalanceService { } else if (category.equals(ClearingCategory.B)) { updateAccountCategoryBClrn(req.getAccountId(), req.getCompanyId(), req.getFirstLegAmount()); } - //todo send message success to Kafka } private ClearingCategory getClearingCategoryByCompanyId(Long companyId) { @@ -117,18 +116,19 @@ public class AccountBalanceService { private void updateAccountCategoryIClrn(Long accountId, Long companyId, BigDecimal firstLegAmount) { AccountBalance accountBalance = loadAccountBalance(accountId, companyId, AccountType.Clrn); BigDecimal previousFreeBalanceAmount = accountBalance.getFreeBalanceAmount(); - BigDecimal resultFreeBalanceAmount = previousFreeBalanceAmount.subtract(firstLegAmount); - accountBalance.setFreeBalanceAmount(resultFreeBalanceAmount); - accountBalance.setChangeBalanceAmount(resultFreeBalanceAmount); - accountBalance.setBalanceAmount(resultFreeBalanceAmount); + BigDecimal previousChangeBalanceAmount = accountBalance.getChangeBalanceAmount(); + BigDecimal previousBalanceAmount = accountBalance.getBalanceAmount(); + accountBalance.setFreeBalanceAmount(previousFreeBalanceAmount.subtract(firstLegAmount)); + accountBalance.setChangeBalanceAmount(previousChangeBalanceAmount.subtract(firstLegAmount)); + accountBalance.setBalanceAmount(previousBalanceAmount.subtract(firstLegAmount)); accountBalance.setUpdated(Instant.now()); accountBalanceImdg.update(accountBalance); } private void updateAccountCategoryITran(BigDecimal firstLegAmount) { AccountBalance accountBalance = loadAccountBalance(AccountType.Tran); - BigDecimal freeBalanceAmount = accountBalance.getFreeBalanceAmount(); - accountBalance.setFreeBalanceAmount(freeBalanceAmount.add(firstLegAmount.abs())); + BigDecimal previousDebitAmount = accountBalance.getDebitAmount(); + accountBalance.setDebitAmount(previousDebitAmount.add(firstLegAmount.abs())); accountBalance.setUpdated(Instant.now()); accountBalanceImdg.update(accountBalance); } @@ -136,10 +136,11 @@ public class AccountBalanceService { private void updateAccountCategoryVInfo(Long accountId, Long companyId, BigDecimal firstLegAmount) { AccountBalance accountBalance = loadAccountBalance(accountId, companyId, AccountType.Info); BigDecimal previousFreeBalanceAmount = accountBalance.getFreeBalanceAmount(); - BigDecimal resultFreeBalanceAmount = previousFreeBalanceAmount.subtract(firstLegAmount); - accountBalance.setFreeBalanceAmount(resultFreeBalanceAmount); - accountBalance.setChangeBalanceAmount(resultFreeBalanceAmount); - accountBalance.setBalanceAmount(resultFreeBalanceAmount); + BigDecimal changeBalanceAmount = accountBalance.getChangeBalanceAmount(); + BigDecimal balanceAmount = accountBalance.getBalanceAmount(); + accountBalance.setFreeBalanceAmount(previousFreeBalanceAmount.subtract(firstLegAmount)); + accountBalance.setChangeBalanceAmount(changeBalanceAmount.subtract(firstLegAmount)); + accountBalance.setBalanceAmount(balanceAmount.subtract(firstLegAmount)); accountBalance.setUpdated(Instant.now()); accountBalanceImdg.update(accountBalance); } @@ -147,18 +148,19 @@ public class AccountBalanceService { private void updateAccountCategoryVAnlt(BigDecimal firstLegAmount) { AccountBalance accountBalance = loadAccountBalance(AccountType.Anlt); BigDecimal previousFreeBalanceAmount = accountBalance.getFreeBalanceAmount(); - BigDecimal resultFreeBalanceAmount = previousFreeBalanceAmount.subtract(firstLegAmount); - accountBalance.setFreeBalanceAmount(resultFreeBalanceAmount); - accountBalance.setChangeBalanceAmount(resultFreeBalanceAmount); - accountBalance.setBalanceAmount(resultFreeBalanceAmount); + BigDecimal previousChangeBalanceAmount = accountBalance.getChangeBalanceAmount(); + BigDecimal previousBalanceAmount = accountBalance.getBalanceAmount(); + accountBalance.setFreeBalanceAmount(previousFreeBalanceAmount.subtract(firstLegAmount)); + accountBalance.setChangeBalanceAmount(previousChangeBalanceAmount.subtract(firstLegAmount)); + accountBalance.setBalanceAmount(previousBalanceAmount.subtract(firstLegAmount)); accountBalance.setUpdated(Instant.now()); accountBalanceImdg.update(accountBalance); } private void updateAccountCategoryBClrn(Long accountId, Long companyId, BigDecimal firstLegAmount) { AccountBalance accountBalance = loadAccountBalance(accountId, companyId, AccountType.Clrn); - BigDecimal freeBalanceAmount = accountBalance.getFreeBalanceAmount(); - accountBalance.setDebitAmount(plus(freeBalanceAmount, firstLegAmount.abs())); + BigDecimal debitAmount = accountBalance.getDebitAmount(); + accountBalance.setDebitAmount(plus(debitAmount, firstLegAmount.abs())); accountBalance.setUpdated(Instant.now()); accountBalanceImdg.update(accountBalance); } From 36ac6256d6d545894adbc78c97a2e7ca5c5c90ef Mon Sep 17 00:00:00 2001 From: AKurakin Date: Thu, 2 Feb 2023 15:48:12 +0300 Subject: [PATCH 28/42] =?UTF-8?q?=D0=BF=D0=BE=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BD=D0=B5=D0=BA=D0=BE=D1=82=D0=BE=D1=80=D1=8B?= =?UTF-8?q?=D0=B5=20=D0=BC=D0=B5=D0=BB=D0=BA=D0=B8=D0=B5=20=D0=B1=D0=B0?= =?UTF-8?q?=D0=B3=D0=B8,=20=D0=BD=D0=B0=D0=B9=D0=B4=D0=B5=D0=BD=D0=BD?= =?UTF-8?q?=D1=8B=D0=B5=20Sonar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../clearing/service/builder/PaymentInstructionCreator.java | 2 +- .../imdg/services/AbstractHazelcastLifecycleSupport.java | 3 +++ .../clearing/reports/services/AbstractReportCollector.java | 2 +- .../securities/service/cud/MoneyMarketSecurityService.java | 1 - .../imdg/iml/hazelcast/service/HazelcastServiceBase.java | 1 + .../platform/imdg/iml/hazelcast/util/HazelcastHelper.java | 2 ++ .../clearing/platform/messaging/service/QueueConsumer.java | 3 +++ .../platform/messaging/service/sender/KafkaSender.java | 3 +++ 8 files changed, 14 insertions(+), 3 deletions(-) diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionCreator.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionCreator.java index 8cff462fe..7a8fafd86 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionCreator.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionCreator.java @@ -501,7 +501,7 @@ public class PaymentInstructionCreator { Long lmId = liabilitiesClaimsAssets.getLiabilitiesClaimsMoneyId(); log.debug("Update LiabilitiesClaimsMoney[{}] by paymentInstructions {}", lmId, paymentInstructions.stream().map(SpcexObjectBase::getId).collect(Collectors.toList())); LiabilitiesClaimsMoney liabilitiesClaimsMoney = liabilitiesClaimsMoneyImdg.getSingleObjectByID(lmId); // update data for update - if (liabilitiesClaimsAssets == null) { + if (liabilitiesClaimsMoney == null) { throw new RuntimeException("IMDG not found LiabilitiesClaimsMoney.id=" + lmId); } if (!Objects.equals(liabilitiesClaimsMoney.getSettlementDate(), liabilitiesClaimsAssets.getSettlementDate())) { diff --git a/clearing-parent/imdg/src/main/java/ru/spcex/clearing/imdg/services/AbstractHazelcastLifecycleSupport.java b/clearing-parent/imdg/src/main/java/ru/spcex/clearing/imdg/services/AbstractHazelcastLifecycleSupport.java index 8b9ea7df8..8b26a9649 100644 --- a/clearing-parent/imdg/src/main/java/ru/spcex/clearing/imdg/services/AbstractHazelcastLifecycleSupport.java +++ b/clearing-parent/imdg/src/main/java/ru/spcex/clearing/imdg/services/AbstractHazelcastLifecycleSupport.java @@ -109,6 +109,9 @@ public abstract class AbstractHazelcastLifecycleSupport implements InitializingB } } catch (InterruptedException | ExecutionException e) { + if (e instanceof InterruptedException) { + Thread.currentThread().interrupt(); + } throw new RuntimeException("MapStore multithreaded not complete.", e); } diff --git a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/AbstractReportCollector.java b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/AbstractReportCollector.java index 6ae81d529..f6276c2cc 100644 --- a/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/AbstractReportCollector.java +++ b/clearing-parent/reports-service/src/main/java/ru/spcex/clearing/reports/services/AbstractReportCollector.java @@ -72,7 +72,7 @@ public abstract class AbstractReportCollector { */ protected String toString(Double val) { if (val == null) return ""; - return String.format(Locale.US, "%.2f", val.doubleValue()); + return String.format(Locale.US, "%.2f", val); } /** 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 37b92222a..ccf129c68 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 @@ -187,7 +187,6 @@ public class MoneyMarketSecurityService extends QueueConsumer implements Initial } MoneyMarketSecurity mms = validator.getStored(Stored.PresentById); mms.setWorkflowStatus(ru.spcex.platform.enumeration.Status.Blocked.getKey()); - Instant.now(); mms.setUpdated(Instant.now()); moneyMarketSecurityMap.update(mms); Listing listing = listingImdg.getSingleObjectByFieldValues(Map.of("securityId", mms.getId())); diff --git a/platform-parent/platform-imdg-api-hazelcast-impl/src/main/java/ru/spcex/platform/imdg/iml/hazelcast/service/HazelcastServiceBase.java b/platform-parent/platform-imdg-api-hazelcast-impl/src/main/java/ru/spcex/platform/imdg/iml/hazelcast/service/HazelcastServiceBase.java index 1ee90ea9c..c515841f7 100644 --- a/platform-parent/platform-imdg-api-hazelcast-impl/src/main/java/ru/spcex/platform/imdg/iml/hazelcast/service/HazelcastServiceBase.java +++ b/platform-parent/platform-imdg-api-hazelcast-impl/src/main/java/ru/spcex/platform/imdg/iml/hazelcast/service/HazelcastServiceBase.java @@ -262,6 +262,7 @@ public abstract class HazelcastServiceBase lock.wait(); } } catch (InterruptedException e) { + Thread.currentThread().interrupt(); log.error(ExceptionUtils.getStackTrace(e)); } } diff --git a/platform-parent/platform-imdg-api-hazelcast-impl/src/main/java/ru/spcex/platform/imdg/iml/hazelcast/util/HazelcastHelper.java b/platform-parent/platform-imdg-api-hazelcast-impl/src/main/java/ru/spcex/platform/imdg/iml/hazelcast/util/HazelcastHelper.java index 3b5579484..5898d2a40 100644 --- a/platform-parent/platform-imdg-api-hazelcast-impl/src/main/java/ru/spcex/platform/imdg/iml/hazelcast/util/HazelcastHelper.java +++ b/platform-parent/platform-imdg-api-hazelcast-impl/src/main/java/ru/spcex/platform/imdg/iml/hazelcast/util/HazelcastHelper.java @@ -84,12 +84,14 @@ public final class HazelcastHelper { log.info("Hazelcast: TextErrorService done"); done = true; } catch (InterruptedException e) { + Thread.currentThread().interrupt(); throw new RuntimeException("Thread interrupted when waiting storage ready.", e); } catch (Exception e) { log.info(String.format("Waiting Hazelcast: %s -> %s", e.getClass().getSimpleName(), e.getMessage())); try { Thread.sleep(100); } catch (InterruptedException ignored) { + Thread.currentThread().interrupt(); throw new RuntimeException("Thread interrupted.", e); } } diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/service/QueueConsumer.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/service/QueueConsumer.java index 8fffd91e8..dcb73fd07 100644 --- a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/service/QueueConsumer.java +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/service/QueueConsumer.java @@ -127,6 +127,9 @@ public class QueueConsumer implements AutoCloseable { send = producer.send(new ProducerRecord<>(Consts.REQUEST_INFO_UPDATE, req)); send.get(); } catch (Exception e) { + if (e instanceof InterruptedException) { + Thread.currentThread().interrupt(); + } log.error(ExceptionUtils.getStackTrace(e)); } }); diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/service/sender/KafkaSender.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/service/sender/KafkaSender.java index 8bb67b5ec..6b321bc90 100644 --- a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/service/sender/KafkaSender.java +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/service/sender/KafkaSender.java @@ -45,6 +45,9 @@ public class KafkaSender { try { send.get(); } catch (InterruptedException | ExecutionException e) { + if (e instanceof InterruptedException) { + Thread.currentThread().interrupt(); + } log.error(ExceptionUtils.getStackTrace(e)); return null; } From 5a772d40a3db610084c10c283039a0923e479177 Mon Sep 17 00:00:00 2001 From: ialbert Date: Thu, 2 Feb 2023 16:14:06 +0300 Subject: [PATCH 29/42] http://jira.mfd.msk:8088/browse/CLS-189 --- .../balance/service/StatementService.java | 4 ++ .../ru/spcex/clearing/service/Clearing.java | 48 +++++++++++-- .../clearing/service/ClearingService.java | 10 +++ .../clearing/service/EventsReceiver.java | 4 ++ .../LiabilitiesClaimsAssetsCreator.java | 69 +++++++++++++++++++ .../platform/messaging/domain/Consts.java | 1 + .../domain/cud/common/CommonIdRequest.java | 17 +++++ 7 files changed, 149 insertions(+), 4 deletions(-) create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/LiabilitiesClaimsAssetsCreator.java create mode 100644 platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/common/CommonIdRequest.java 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 9bedcb348..71d790c18 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 @@ -18,6 +18,7 @@ import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountSdfR 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; @@ -70,6 +71,9 @@ public class StatementService extends QueueConsumer implements InitializingBean private void accountBalanceClearingUpdate(BaseRequest updateAccBalanceReq) { accountBalanceService.updateAccountBalanceByClearing(updateAccBalanceReq.getRequestPayload()); + CommonIdRequest commonIdRequest = new CommonIdRequest(); + commonIdRequest.setId(updateAccBalanceReq.getId()); + kafkaReqProducer.sendRequestToQueue(Consts.CONTINUE_CLEARING, commonIdRequest); } private void process(BaseRequest systemRequest) { diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java index 935866921..4e2136cc0 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java @@ -7,17 +7,21 @@ import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.execution.ExecutionDeposit; import ru.clearing.classes.statics.data.generated.ClearingMemberCategory; import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsAssets; -import ru.clearing.classes.statics.data.payment.PaymentInstruction; import ru.spcex.clearing.error.ClearingErrorInternal; import ru.spcex.clearing.imdg.IMDGDistributedNames; -import ru.spcex.clearing.service.order.ExecutionDepositSorter; +import ru.spcex.clearing.platform.messaging.domain.Consts; +import ru.spcex.clearing.platform.messaging.domain.cud.balance.AccountBalanceClearingRequest; +import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; +import ru.spcex.clearing.service.builder.LiabilitiesClaimsAssetsCreator; import ru.spcex.clearing.service.builder.PaymentInstructionCreator; +import ru.spcex.clearing.service.order.ExecutionDepositSorter; import ru.spcex.platform.enumeration.Allowed; import ru.spcex.platform.enumeration.ClearingCategory; 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.utils.enumeration.EnumMessage; +import ru.spcex.platform.utils.log.ExceptionUtils; import ru.spcex.platform.utils.validation.IValidator; import java.time.Instant; @@ -28,11 +32,15 @@ import java.util.function.BiFunction; public class Clearing { private final Logger log = LoggerFactory.getLogger(getClass()); private final Imdg executionDepositImdg; + private final Imdg liabilitiesClaimsAssetsImdg; private final Imdg clearingCategoryImdg; private final ExecutionDepositSorter sorter; private final BiFunction validation; private final PaymentInstructionCreator paymentInstructionCreator; private final ImdgId idProvider; + private final KafkaSender kafka; + private final LiabilitiesClaimsAssetsCreator lbltsClmsAssetsCreator; + private Long lastAccBalanceResponseId = 0L; //при прохождении по выгруженным ExecutionDeposit, ошибочные статусы проставляются для //контр сделок. В таком случае, в коллекции хранятся не синхронизированные с IMDG ExecutionDeposit //для которых статус должен быть DENIED @@ -43,13 +51,16 @@ public class Clearing { @Autowired public Clearing(ImdgProvider imdgProvider, ExecutionDepositSorter sorter, PaymentInstructionCreator paymentInstructionCreator, - BiFunction validation) { + BiFunction validation, KafkaSender kafka, LiabilitiesClaimsAssetsCreator liabilitiesClaimsAssetsCreator) { this.executionDepositImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionDeposit, ExecutionDeposit.class); this.clearingCategoryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class); + this.liabilitiesClaimsAssetsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_LiabilitiesClaimsAssets, LiabilitiesClaimsAssets.class); this.paymentInstructionCreator = paymentInstructionCreator; this.idProvider = imdgProvider.getImdgIdGenerator(); this.sorter = sorter; this.validation = validation; + this.kafka = kafka; + this.lbltsClmsAssetsCreator = liabilitiesClaimsAssetsCreator; } public void startClearing() { @@ -134,7 +145,36 @@ public class Clearing { if (!Allowed.ALLOWED.getKey().equals(execDeposit.getCoverageStatus())) { continue; } - + //send request to kafka, wait for a reply + synchronized (this) { + AccountBalanceClearingRequest request = new AccountBalanceClearingRequest(); + request.setAccountId(execDeposit.getAccountId()); + request.setCompanyId(execDeposit.getCompanyId()); + request.setFirstLegAmount(execDeposit.getFirstLegAmount()); + Long sentRequestId = kafka.sendRequestToQueue(Consts.BALANCE_ACCOUNT_UPDATE, request); + try { + wait(5000); + //todo check that request Id was processed succesfully + //если на этом месте произошла ошибка - непонятно как обрабатывать + //т.к. этом может быть уже вторая часть сделки, для первой accountBalance уже был обновлен + //либо вне зависимости от того какая часть сделки, accountBalance на самом деле мог быть + //обновлен, и была проблема была с сетью/недоступностью кафки etc. + } catch (InterruptedException e) { + log.error(ExceptionUtils.getStackTrace(e)); + } + if (!Objects.equals(lastAccBalanceResponseId, sentRequestId)) { + log.error("FATAL: last response from AccountBalance update from Kafka ID was {}, but sent ID was {}", + lastAccBalanceResponseId, + sentRequestId); + continue; + } + } + LiabilitiesClaimsAssets liabilitiesClaimsAssets = lbltsClmsAssetsCreator.createLiabilitiesClaimsAssets(category, execDeposit); + liabilitiesClaimsAssetsImdg.insert(liabilitiesClaimsAssets); } } + + public void setLastAccBalanceResponseId(Long lastAccBalanceResponseId) { + this.lastAccBalanceResponseId = lastAccBalanceResponseId; + } } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ClearingService.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ClearingService.java index 18079d147..0dc6ac3b9 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ClearingService.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/ClearingService.java @@ -6,6 +6,8 @@ import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.stereotype.Service; +import ru.spcex.clearing.platform.messaging.domain.BaseRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonIdRequest; import ru.spcex.platform.utils.log.ExceptionUtils; import java.util.concurrent.ExecutorService; @@ -85,6 +87,14 @@ public class ClearingService implements DisposableBean { }); } + public void continueClearing(BaseRequest event) { + synchronized (clearing) { + CommonIdRequest requestPayload = event.getRequestPayload(); + clearing.setLastAccBalanceResponseId(requestPayload.getId()); + clearing.notifyAll(); + } + } + public void executeSTrade() { log.info("start STrade check for ExecutionDeposit"); executor.execute(() -> { 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 66b6c8f47..9eb639b9c 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 @@ -5,6 +5,7 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.stereotype.Service; import ru.spcex.clearing.platform.messaging.domain.Consts; 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.platform.enumeration.Task; @@ -34,6 +35,9 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean { callback(Object.class) //todo check Object suitable .setConsumer(event -> clearingService.executeClearing()) .forDestination(Task.startOfClearing.topic(), callbacks::put); + callback(CommonIdRequest.class) + .setConsumer(clearingService::continueClearing) + .forDestination(Consts.CONTINUE_CLEARING, 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/builder/LiabilitiesClaimsAssetsCreator.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/LiabilitiesClaimsAssetsCreator.java new file mode 100644 index 000000000..cf4bcd74b --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/LiabilitiesClaimsAssetsCreator.java @@ -0,0 +1,69 @@ +package ru.spcex.clearing.service.builder; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import ru.clearing.classes.statics.data.account.Account; +import ru.clearing.classes.statics.data.company.Company; +import ru.clearing.classes.statics.data.execution.ExecutionDeposit; +import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsAssets; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.platform.enumeration.AccountType; +import ru.spcex.platform.enumeration.ClearingCategory; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.utils.enumeration.IEnumKey; + +import java.time.Instant; +import java.time.LocalDate; + +@Component +public class LiabilitiesClaimsAssetsCreator { + private final Imdg accountImdg; + private final Imdg companyImdg; + + @Autowired + public LiabilitiesClaimsAssetsCreator(ImdgProvider imdgProvider) { + this.accountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class); + this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class); + } + + + public LiabilitiesClaimsAssets createLiabilitiesClaimsAssets(ClearingCategory category, ExecutionDeposit executionDeposit) { + LiabilitiesClaimsAssets liabilitiesClaimsAssets = new LiabilitiesClaimsAssets(); + liabilitiesClaimsAssets.setCompanyId(executionDeposit.getCompanyId()); + liabilitiesClaimsAssets.setAccountId(executionDeposit.getAccountId()); + Account account = accountImdg.getSingleObjectByID(executionDeposit.getAccountId()); + liabilitiesClaimsAssets.setAccountType(account.getAccountType()); + liabilitiesClaimsAssets.setAccount(account.getAccount()); + AccountType accType = IEnumKey.getEnumByKey(AccountType.class, account.getAccountType()); + boolean iClrn = ClearingCategory.I.equals(category) && AccountType.Clrn.equals(accType); + boolean vInfo = ClearingCategory.V.equals(category) && AccountType.Info.equals(accType); + boolean bClrn = ClearingCategory.B.equals(category) && AccountType.Clrn.equals(accType); + + if (iClrn || vInfo) { + liabilitiesClaimsAssets.setLiabilitiesQuantity(executionDeposit.getFirstLegAmount()); + } + if (bClrn) { + liabilitiesClaimsAssets.setClaimsQuantity(executionDeposit.getSecondLegAmount()); + } + liabilitiesClaimsAssets.setCurrency(executionDeposit.getSettlementCurrency()); + liabilitiesClaimsAssets.setSettlementDate(executionDeposit.getFirstLegSettlementDate()); + liabilitiesClaimsAssets.setTradingDate(executionDeposit.getTradingDate()); + liabilitiesClaimsAssets.setRefundDate(executionDeposit.getSecondLegSettlementDate()); + liabilitiesClaimsAssets.setPrice(executionDeposit.getPrice()); + liabilitiesClaimsAssets.setSecurityId(executionDeposit.getSecurityId()); + Company company = companyImdg.getSingleObjectByID(executionDeposit.getCompanyId()); + liabilitiesClaimsAssets.setTradingCode(company.getTradingCode()); + liabilitiesClaimsAssets.setClearingCode(company.getClearingCode()); + liabilitiesClaimsAssets.setShortName(company.getShortName()); + liabilitiesClaimsAssets.setContract(executionDeposit.getSecuritySymbol()); + liabilitiesClaimsAssets.setFullName(company.getFullName()); + //todo liabilitiesClaimsAssets.setLiabilitiesClaimsMoneyId(company.getFullName()); + //fixme liabilitiesClaimsAssets.setClearingStatus(); + //todo liabilitiesClaimsAssets.setPaymentId(); + //todo liabilitiesClaimsAssets.setRefundPaymentId(); + liabilitiesClaimsAssets.setCreated(Instant.now()); + liabilitiesClaimsAssets.setClearingDate(LocalDate.now()); + return liabilitiesClaimsAssets; + } +} 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 fd95ea1ad..97ed7998a 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 @@ -51,6 +51,7 @@ public interface Consts { String ACCOUNT_NEW = "account-new"; String BALANCE_ACCOUNT_NEW = "balance-account-new"; String BALANCE_ACCOUNT_UPDATE = "balance-account-update"; + String CONTINUE_CLEARING = "continue-clearing"; String LAUNCHER_NEW = "launcher-new"; String NOTIFICATION_NEW = "notification-new"; diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/common/CommonIdRequest.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/common/CommonIdRequest.java new file mode 100644 index 000000000..57c9ea6fd --- /dev/null +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/common/CommonIdRequest.java @@ -0,0 +1,17 @@ +package ru.spcex.clearing.platform.messaging.domain.cud.common; + +import com.fasterxml.jackson.annotation.JsonProperty; +import ru.spcex.platform.classes.base.interfaces.WithId; + +public class CommonIdRequest implements WithId { + @JsonProperty + public Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } +} From 09a58a95ce16e2f2b966a92f031c1fbcc94be8f3 Mon Sep 17 00:00:00 2001 From: ialbert Date: Thu, 2 Feb 2023 16:31:38 +0300 Subject: [PATCH 30/42] http://jira.mfd.msk:8088/browse/CLS-189 added logging --- .../main/java/ru/spcex/clearing/service/Clearing.java | 11 +++++++++++ .../ru/spcex/platform/utils/enumeration/IEnumId.java | 8 ++++++++ 2 files changed, 19 insertions(+) diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java index 4e2136cc0..a1ed035cf 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java @@ -93,23 +93,28 @@ public class Clearing { boolean financialError = false; for (ExecutionDeposit execDeposit : executionDeposits) { if (deniedIds.contains(execDeposit.getId())) { + log.trace("executionDeposit {} was already denied", execDeposit.getId()); continue; } if (financialError) { + log.trace("executionDeposit {} FinancialObligationNotSatisfied was present earlier for this company; setting DENIED status", execDeposit.getId()); updateDenied(execDeposit); continue; } IValidator validator = validation.apply(category, execDeposit); Optional errorMsg = validator.tillFirstError(); if (errorMsg.isPresent() && !ClearingErrorInternal.FinancialObligationNotSatisfied.equals(errorMsg.get().getSubject())) { + log.trace("executionDeposit {} setting DENIED status: {}", execDeposit.getId(), errorMsg.get().getSubject().nameOrId()); updateDenied(execDeposit); continue; } else if (errorMsg.isPresent()) { + log.trace("executionDeposit {} setting DENIED status: {}", execDeposit.getId(), errorMsg.get().getSubject().nameOrId()); financialError = true; updateDenied(execDeposit); continue; } updateAllowed(execDeposit); + log.trace("executionDeposit {} was updated ALLOWED", execDeposit.getId()); } } @@ -117,6 +122,7 @@ public class Clearing { execDeposit.setCoverageStatus(Allowed.DENIED.getKey()); execDeposit.setUpdated(Instant.now()); executionDepositImdg.update(execDeposit); + log.trace("executionDeposit {} was updated DENIED", execDeposit.getId()); //также необходимо установить статус DEND встречной сделке контрагента этой компании, которая выбирается из executionDeposit по ключу: //securityId И чтобы сделка была компании категории clearingMemberCategory.clearingMemberCategory ≠ той категории, сделка которой обрабатывается в настоящий момент. ExecutionDeposit matchedExecDeposit = executionDepositImdg.getSingleObjectBySQL( @@ -126,6 +132,7 @@ public class Clearing { matchedExecDeposit.setCoverageStatus(Allowed.DENIED.getKey()); matchedExecDeposit.setUpdated(Instant.now()); executionDepositImdg.update(matchedExecDeposit); + log.trace("executionDeposit {} matching executionDeposit {} was updated DENIED", execDeposit.getId(), matchedExecDeposit.getId()); deniedIds.add(matchedExecDeposit.getId()); } } @@ -140,9 +147,11 @@ public class Clearing { log.info("running clearing for category: {}, company: {}", category, executionDeposits.get(0).getCompanyId()); for (ExecutionDeposit execDeposit : executionDeposits) { if (deniedIds.contains(execDeposit.getId())) { + log.trace("Skipping processing executionDeposit {} was denied as matching", execDeposit.getId()); continue; } if (!Allowed.ALLOWED.getKey().equals(execDeposit.getCoverageStatus())) { + log.trace("Skipping processing executionDeposit {} was denied", execDeposit.getId()); continue; } //send request to kafka, wait for a reply @@ -152,6 +161,7 @@ public class Clearing { request.setCompanyId(execDeposit.getCompanyId()); request.setFirstLegAmount(execDeposit.getFirstLegAmount()); Long sentRequestId = kafka.sendRequestToQueue(Consts.BALANCE_ACCOUNT_UPDATE, request); + log.trace("sent request to kafka, requestId: {}", sentRequestId); try { wait(5000); //todo check that request Id was processed succesfully @@ -171,6 +181,7 @@ public class Clearing { } LiabilitiesClaimsAssets liabilitiesClaimsAssets = lbltsClmsAssetsCreator.createLiabilitiesClaimsAssets(category, execDeposit); liabilitiesClaimsAssetsImdg.insert(liabilitiesClaimsAssets); + log.trace("LiabilitiesClaimsAssets {} was created", liabilitiesClaimsAssets.getId()); } } diff --git a/platform-parent/platform-utils/src/main/java/ru/spcex/platform/utils/enumeration/IEnumId.java b/platform-parent/platform-utils/src/main/java/ru/spcex/platform/utils/enumeration/IEnumId.java index 10859b6a4..f2a161277 100644 --- a/platform-parent/platform-utils/src/main/java/ru/spcex/platform/utils/enumeration/IEnumId.java +++ b/platform-parent/platform-utils/src/main/java/ru/spcex/platform/utils/enumeration/IEnumId.java @@ -61,4 +61,12 @@ public interface IEnumId extends Serializable { default boolean equalsById(Long id) { return id != null && getId().equals(id); } + + default String nameOrId() { + try { + return ((Enum) this).name(); + } catch (ClassCastException e) { + return getId().toString(); + } + } } From 2b11d25ac2d4642b7f04f3c450b67597d9279d2e Mon Sep 17 00:00:00 2001 From: ialbert Date: Thu, 2 Feb 2023 16:44:19 +0300 Subject: [PATCH 31/42] http://jira.mfd.msk:8088/browse/CLS-189 added logging --- .../clearing/balance/service/AccountBalanceService.java | 8 ++++++++ .../spcex/clearing/balance/service/StatementService.java | 6 +++++- .../clearing-service/src/main/resources/logback.xml | 5 +++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java index 5be5d136b..cade521e2 100644 --- a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java +++ b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java @@ -1,5 +1,7 @@ package ru.spcex.clearing.balance.service; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import ru.clearing.classes.statics.data.account.Account; @@ -28,6 +30,7 @@ import java.util.function.Function; @Component public class AccountBalanceService { + private final Logger log = LoggerFactory.getLogger(getClass()); private final ImdgProvider imdgProvider; private final Imdg accountBalanceImdg; private final Function validationFactory; @@ -122,6 +125,7 @@ public class AccountBalanceService { accountBalance.setChangeBalanceAmount(previousChangeBalanceAmount.subtract(firstLegAmount)); accountBalance.setBalanceAmount(previousBalanceAmount.subtract(firstLegAmount)); accountBalance.setUpdated(Instant.now()); + log.trace("updateAccountCategoryIClrn: {}", accountBalance.getId()); accountBalanceImdg.update(accountBalance); } @@ -130,6 +134,7 @@ public class AccountBalanceService { BigDecimal previousDebitAmount = accountBalance.getDebitAmount(); accountBalance.setDebitAmount(previousDebitAmount.add(firstLegAmount.abs())); accountBalance.setUpdated(Instant.now()); + log.trace("updateAccountCategoryITran: {}", accountBalance.getId()); accountBalanceImdg.update(accountBalance); } @@ -142,6 +147,7 @@ public class AccountBalanceService { accountBalance.setChangeBalanceAmount(changeBalanceAmount.subtract(firstLegAmount)); accountBalance.setBalanceAmount(balanceAmount.subtract(firstLegAmount)); accountBalance.setUpdated(Instant.now()); + log.trace("updateAccountCategoryVInfo: {}", accountBalance.getId()); accountBalanceImdg.update(accountBalance); } @@ -154,6 +160,7 @@ public class AccountBalanceService { accountBalance.setChangeBalanceAmount(previousChangeBalanceAmount.subtract(firstLegAmount)); accountBalance.setBalanceAmount(previousBalanceAmount.subtract(firstLegAmount)); accountBalance.setUpdated(Instant.now()); + log.trace("updateAccountCategoryVAnlt: {}", accountBalance.getId()); accountBalanceImdg.update(accountBalance); } @@ -162,6 +169,7 @@ public class AccountBalanceService { BigDecimal debitAmount = accountBalance.getDebitAmount(); accountBalance.setDebitAmount(plus(debitAmount, firstLegAmount.abs())); accountBalance.setUpdated(Instant.now()); + log.trace("updateAccountCategoryBClrn: {}", accountBalance.getId()"); accountBalanceImdg.update(accountBalance); } 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 71d790c18..8c44b9ce4 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 @@ -70,7 +70,11 @@ public class StatementService extends QueueConsumer implements InitializingBean } private void accountBalanceClearingUpdate(BaseRequest updateAccBalanceReq) { - accountBalanceService.updateAccountBalanceByClearing(updateAccBalanceReq.getRequestPayload()); + AccountBalanceClearingRequest payload = updateAccBalanceReq.getRequestPayload(); + log.debug("updating account balance for clearing baseRequest.id = {}; accountId = {}, companyId = {}, firstLegAmount = {}", updateAccBalanceReq.getId() + payload.getAccountId(), payload.getCompanyId(), payload.getFirstLegAmount() + ); + accountBalanceService.updateAccountBalanceByClearing(payload); CommonIdRequest commonIdRequest = new CommonIdRequest(); commonIdRequest.setId(updateAccBalanceReq.getId()); kafkaReqProducer.sendRequestToQueue(Consts.CONTINUE_CLEARING, commonIdRequest); diff --git a/clearing-parent/clearing-service/src/main/resources/logback.xml b/clearing-parent/clearing-service/src/main/resources/logback.xml index f96f82942..e2702c011 100644 --- a/clearing-parent/clearing-service/src/main/resources/logback.xml +++ b/clearing-parent/clearing-service/src/main/resources/logback.xml @@ -34,4 +34,9 @@ + + + + + \ No newline at end of file From 89059e8b46636bdb60ace4253a434bec185fb17f Mon Sep 17 00:00:00 2001 From: ialbert Date: Thu, 2 Feb 2023 16:45:24 +0300 Subject: [PATCH 32/42] http://jira.mfd.msk:8088/browse/CLS-189 added logging --- .../clearing/balance/service/AccountBalanceService.java | 2 +- .../ru/spcex/clearing/balance/service/StatementService.java | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java index cade521e2..20b358cdc 100644 --- a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java +++ b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java @@ -169,7 +169,7 @@ public class AccountBalanceService { BigDecimal debitAmount = accountBalance.getDebitAmount(); accountBalance.setDebitAmount(plus(debitAmount, firstLegAmount.abs())); accountBalance.setUpdated(Instant.now()); - log.trace("updateAccountCategoryBClrn: {}", accountBalance.getId()"); + log.trace("updateAccountCategoryBClrn: {}", accountBalance.getId()); accountBalanceImdg.update(accountBalance); } 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 8c44b9ce4..37495b876 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 @@ -71,9 +71,8 @@ public class StatementService extends QueueConsumer implements InitializingBean private void accountBalanceClearingUpdate(BaseRequest updateAccBalanceReq) { AccountBalanceClearingRequest payload = updateAccBalanceReq.getRequestPayload(); - log.debug("updating account balance for clearing baseRequest.id = {}; accountId = {}, companyId = {}, firstLegAmount = {}", updateAccBalanceReq.getId() - payload.getAccountId(), payload.getCompanyId(), payload.getFirstLegAmount() - ); + log.debug("updating account balance for clearing baseRequest.id = {}; accountId = {}, companyId = {}, firstLegAmount = {}", updateAccBalanceReq.getId(), + payload.getAccountId(), payload.getCompanyId(), payload.getFirstLegAmount()); accountBalanceService.updateAccountBalanceByClearing(payload); CommonIdRequest commonIdRequest = new CommonIdRequest(); commonIdRequest.setId(updateAccBalanceReq.getId()); From c77444c4df78c3bcf0b6a9324530905c0531d579 Mon Sep 17 00:00:00 2001 From: ialbert Date: Thu, 2 Feb 2023 16:52:10 +0300 Subject: [PATCH 33/42] http://jira.mfd.msk:8088/browse/CLS-189 added logging --- .../src/main/java/ru/spcex/clearing/service/Clearing.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java index a1ed035cf..4381680ea 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java @@ -65,8 +65,10 @@ public class Clearing { public void startClearing() { clearingSessionId = idProvider.nextId(); + log.info("startClearing clearingSessionId = {}. loading ExecutionDeposits", clearingSessionId); //выгружаем ExecutionDeposit с пустым sessionId Collection execDeposits = executionDepositImdg.getCollectionObjectsBySQL("sessionId = null"); + log.info("loaded {} ExecutionDeposits", execDeposits.size()); //делаем группировку ExecutionDeposit по категории и компании, делаем сортировку LinkedHashMap>> executionDeposits = sorter.sortExecutionDeposit(execDeposits); From 894fdf76257c750f7f3925898c9f9fb99d6f3dda Mon Sep 17 00:00:00 2001 From: ialbert Date: Thu, 2 Feb 2023 17:05:12 +0300 Subject: [PATCH 34/42] http://jira.mfd.msk:8088/browse/CLS-189 updated distr pom.xml added clearing-service --- z-distr/pom.xml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/z-distr/pom.xml b/z-distr/pom.xml index 0a1d961e8..2414ad7fb 100644 --- a/z-distr/pom.xml +++ b/z-distr/pom.xml @@ -248,6 +248,25 @@ + + copy-clearing-service-bin + prepare-package + + copy + + + + + ${folder_root_clearing-service}/target/clearing-service.jar + ${folder.clearing.distr.modules}/clearing-service/clearing-service.jar + + + ${folder_root_clearing-service}/src/main/resources/application.properties + ${folder.clearing.distr.modules}/clearing-service/application.properties + + + + copy-scheduler-service-bin prepare-package From 01c22e449d1844cd2f1385296166de700c2527dd Mon Sep 17 00:00:00 2001 From: ialbert Date: Thu, 2 Feb 2023 17:40:53 +0300 Subject: [PATCH 35/42] http://jira.mfd.msk:8088/browse/CLS-189 NLP fix --- .../clearing/service/order/ExecutionDepositSorter.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/ExecutionDepositSorter.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/ExecutionDepositSorter.java index a396f5b90..4a17cba7e 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/ExecutionDepositSorter.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/ExecutionDepositSorter.java @@ -61,10 +61,12 @@ public class ExecutionDepositSorter { //метод для дополнительной сортировки внутри групп по категории и компании BiConsumer> additionalSorting = - (clearingCategory, comparator) -> byCategoryByCompany - .get(clearingCategory) - .stream().filter(Objects::nonNull) - .forEach(singleCompanyBatch -> singleCompanyBatch.sort(comparator)); + (clearingCategory, comparator) -> { + List> allExecDepositsForCategory = byCategoryByCompany.get(clearingCategory); + if (allExecDepositsForCategory != null) { + allExecDepositsForCategory.forEach(singleCompanyBatch -> singleCompanyBatch.sort(comparator)); + } + }; //применяем дополнительные сортировки //для V сначала Sell, потом Buy, в первую очередь должны обрабатываться новые сделки с наименьшими объемами additionalSorting.accept(ClearingCategory.V, From b448d6b208edb8187460dcb2c7662b1568c0d157 Mon Sep 17 00:00:00 2001 From: ialbert Date: Thu, 2 Feb 2023 18:02:53 +0300 Subject: [PATCH 36/42] http://jira.mfd.msk:8088/browse/CLS-189 bug fix --- .../main/java/ru/spcex/clearing/config/ValidationConfig.java | 2 ++ pom.xml | 1 + 2 files changed, 3 insertions(+) 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 f4eb7ac72..1815dc2af 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 @@ -50,6 +50,8 @@ public class ValidationConfig { context.storeObject(ClrngValidationStored.categoryPredefined, category); addImdg.accept(context, IMDGDistributedNames.Map_Relation); addImdg.accept(context, IMDGDistributedNames.Map_Company); + addImdg.accept(context, IMDGDistributedNames.Map_Account); + addImdg.accept(context, IMDGDistributedNames.Map_AccountBalance); return new ValidatorImpl<>(context, ExecutionDepositValidationRule.ClearingIsAllowed, ExecutionDepositValidationRule.AccountIsNotBlocked, diff --git a/pom.xml b/pom.xml index 3474338bf..6a001e386 100644 --- a/pom.xml +++ b/pom.xml @@ -40,6 +40,7 @@ ${folder_root_clearing}/clearing-parent/account-service ${folder_root_clearing}/clearing-parent/balance-service ${folder_root_clearing}/clearing-parent/company-service + ${folder_root_clearing}/clearing-parent/clearing-service ${folder_root_clearing}/clearing-parent/reports-service ${folder_root_clearing}/clearing-parent/utility-service ${folder_root_clearing}/clearing-parent/scheduler-service From af192d5a32bd4ca03a8efb4a50d382812111a65f Mon Sep 17 00:00:00 2001 From: ialbert Date: Fri, 3 Feb 2023 11:21:13 +0300 Subject: [PATCH 37/42] http://jira.mfd.msk:8088/browse/CLS-189 bug fix --- .../main/java/ru/spcex/clearing/config/ValidationConfig.java | 2 ++ 1 file changed, 2 insertions(+) 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 1815dc2af..f420c0839 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 @@ -30,6 +30,8 @@ public class ValidationConfig { BiConsumer> addImdg = (s, aClass) -> imdgs.put(s, imdgProvider.getImdg(s, aClass)); addImdg.accept(IMDGDistributedNames.Map_Relation, Relation.class); addImdg.accept(IMDGDistributedNames.Map_Company, Company.class); + addImdg.accept(IMDGDistributedNames.Map_Account, Company.class); + addImdg.accept(IMDGDistributedNames.Map_AccountBalance, Company.class); } /** From c38fa5c0bfd9e0e3144bab14d2b78576be336a9f Mon Sep 17 00:00:00 2001 From: etreshenkov Date: Fri, 3 Feb 2023 12:19:34 +0300 Subject: [PATCH 38/42] http://jira.mfd.msk:8088/browse/CLS-217 --- .../controller/queue/scheduler/LauncherController.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/scheduler/LauncherController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/scheduler/LauncherController.java index fad922cdc..1163100a5 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/scheduler/LauncherController.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/scheduler/LauncherController.java @@ -31,7 +31,6 @@ import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.utils.enumeration.EnumMessage; import ru.spcex.platform.utils.enumeration.IMessageResolver; -import java.time.Instant; import java.util.Collection; import java.util.Map; import java.util.concurrent.ExecutionException; @@ -115,14 +114,6 @@ public class LauncherController extends AbstractQueueController { return processRequest(Consts.LAUNCHER_NEW, launcherCommand); } - private void saveLauncher(String taskCode, Long userId) { - Launcher launcherCommandHistory = new Launcher(); - launcherCommandHistory.setTask(taskCode); - launcherCommandHistory.setSenderId(userId); - launcherCommandHistory.setCreated(Instant.now()); - launcherImdg.insert(launcherCommandHistory); - } - @Autowired private IMessageResolver errorResolver; From da5d08e1d8bb8fac68e8eed2d304da9c44d9afdb Mon Sep 17 00:00:00 2001 From: ialbert Date: Fri, 3 Feb 2023 13:39:53 +0300 Subject: [PATCH 39/42] http://jira.mfd.msk:8088/browse/CLS-189 account balance bug fix NLPs --- .../service/AccountBalanceService.java | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java index 20b358cdc..c74026395 100644 --- a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java +++ b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java @@ -98,6 +98,7 @@ public class AccountBalanceService { public void updateAccountBalanceByClearing(AccountBalanceClearingRequest req) { ClearingCategory category = getClearingCategoryByCompanyId(req.getCompanyId()); + req.setFirstLegAmount(safeBD(req.getFirstLegAmount())); if (category.equals(ClearingCategory.I)) { updateAccountCategoryIClrn(req.getAccountId(), req.getCompanyId(), req.getFirstLegAmount()); updateAccountCategoryITran(req.getFirstLegAmount()); @@ -118,9 +119,10 @@ public class AccountBalanceService { private void updateAccountCategoryIClrn(Long accountId, Long companyId, BigDecimal firstLegAmount) { AccountBalance accountBalance = loadAccountBalance(accountId, companyId, AccountType.Clrn); - BigDecimal previousFreeBalanceAmount = accountBalance.getFreeBalanceAmount(); - BigDecimal previousChangeBalanceAmount = accountBalance.getChangeBalanceAmount(); - BigDecimal previousBalanceAmount = accountBalance.getBalanceAmount(); + log.trace("updating AccountBalance {} I CLRN", accountBalance.getId()); + BigDecimal previousFreeBalanceAmount = safeBD(accountBalance.getFreeBalanceAmount()); + BigDecimal previousChangeBalanceAmount = safeBD(accountBalance.getChangeBalanceAmount()); + BigDecimal previousBalanceAmount = safeBD(accountBalance.getBalanceAmount()); accountBalance.setFreeBalanceAmount(previousFreeBalanceAmount.subtract(firstLegAmount)); accountBalance.setChangeBalanceAmount(previousChangeBalanceAmount.subtract(firstLegAmount)); accountBalance.setBalanceAmount(previousBalanceAmount.subtract(firstLegAmount)); @@ -131,7 +133,8 @@ public class AccountBalanceService { private void updateAccountCategoryITran(BigDecimal firstLegAmount) { AccountBalance accountBalance = loadAccountBalance(AccountType.Tran); - BigDecimal previousDebitAmount = accountBalance.getDebitAmount(); + log.trace("updating AccountBalance {} I TRAN", accountBalance.getId()); + BigDecimal previousDebitAmount = safeBD(accountBalance.getDebitAmount()); accountBalance.setDebitAmount(previousDebitAmount.add(firstLegAmount.abs())); accountBalance.setUpdated(Instant.now()); log.trace("updateAccountCategoryITran: {}", accountBalance.getId()); @@ -140,9 +143,10 @@ public class AccountBalanceService { private void updateAccountCategoryVInfo(Long accountId, Long companyId, BigDecimal firstLegAmount) { AccountBalance accountBalance = loadAccountBalance(accountId, companyId, AccountType.Info); - BigDecimal previousFreeBalanceAmount = accountBalance.getFreeBalanceAmount(); - BigDecimal changeBalanceAmount = accountBalance.getChangeBalanceAmount(); - BigDecimal balanceAmount = accountBalance.getBalanceAmount(); + log.trace("updating AccountBalance {} V INFO", accountBalance.getId()); + BigDecimal previousFreeBalanceAmount = safeBD(accountBalance.getFreeBalanceAmount()); + BigDecimal changeBalanceAmount = safeBD(accountBalance.getChangeBalanceAmount()); + BigDecimal balanceAmount = safeBD(accountBalance.getBalanceAmount()); accountBalance.setFreeBalanceAmount(previousFreeBalanceAmount.subtract(firstLegAmount)); accountBalance.setChangeBalanceAmount(changeBalanceAmount.subtract(firstLegAmount)); accountBalance.setBalanceAmount(balanceAmount.subtract(firstLegAmount)); @@ -153,9 +157,10 @@ public class AccountBalanceService { private void updateAccountCategoryVAnlt(BigDecimal firstLegAmount) { AccountBalance accountBalance = loadAccountBalance(AccountType.Anlt); - BigDecimal previousFreeBalanceAmount = accountBalance.getFreeBalanceAmount(); - BigDecimal previousChangeBalanceAmount = accountBalance.getChangeBalanceAmount(); - BigDecimal previousBalanceAmount = accountBalance.getBalanceAmount(); + log.trace("updating AccountBalance {} V ANLT", accountBalance.getId()); + BigDecimal previousFreeBalanceAmount = safeBD(accountBalance.getFreeBalanceAmount()); + BigDecimal previousChangeBalanceAmount = safeBD(accountBalance.getChangeBalanceAmount()); + BigDecimal previousBalanceAmount = safeBD(accountBalance.getBalanceAmount()); accountBalance.setFreeBalanceAmount(previousFreeBalanceAmount.subtract(firstLegAmount)); accountBalance.setChangeBalanceAmount(previousChangeBalanceAmount.subtract(firstLegAmount)); accountBalance.setBalanceAmount(previousBalanceAmount.subtract(firstLegAmount)); @@ -166,7 +171,8 @@ public class AccountBalanceService { private void updateAccountCategoryBClrn(Long accountId, Long companyId, BigDecimal firstLegAmount) { AccountBalance accountBalance = loadAccountBalance(accountId, companyId, AccountType.Clrn); - BigDecimal debitAmount = accountBalance.getDebitAmount(); + log.trace("updating AccountBalance {} B CLRN", accountBalance.getId()); + BigDecimal debitAmount = safeBD(accountBalance.getDebitAmount()); accountBalance.setDebitAmount(plus(debitAmount, firstLegAmount.abs())); accountBalance.setUpdated(Instant.now()); log.trace("updateAccountCategoryBClrn: {}", accountBalance.getId()); @@ -186,4 +192,8 @@ public class AccountBalanceService { "accountType", type.getKey()) ); } + + private BigDecimal safeBD(BigDecimal bd) { + return bd == null ? BigDecimal.ZERO : bd; + } } From 12511a48e95cb38971e082944779375075092f8b Mon Sep 17 00:00:00 2001 From: ialbert Date: Fri, 3 Feb 2023 16:26:07 +0300 Subject: [PATCH 40/42] http://jira.mfd.msk:8088/browse/CLS-189 --- .../service/AccountBalanceService.java | 29 +++-- .../ru/spcex/clearing/service/Clearing.java | 42 ++++++- .../LiabilitiesClaimsAssetsCreator.java | 7 ++ .../LiabilitiesClaimsMoneyCreator.java | 104 ++++++++++++++++++ .../platform/utils/number/BigDecimalUtil.java | 5 + 5 files changed, 165 insertions(+), 22 deletions(-) create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/LiabilitiesClaimsMoneyCreator.java diff --git a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java index c74026395..087df3786 100644 --- a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java +++ b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/AccountBalanceService.java @@ -19,6 +19,7 @@ import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.utils.enumeration.EnumMessage; import ru.spcex.platform.utils.enumeration.IEnumKey; +import ru.spcex.platform.utils.number.BigDecimalUtil; import ru.spcex.platform.utils.validation.IValidator; import java.math.BigDecimal; @@ -98,7 +99,7 @@ public class AccountBalanceService { public void updateAccountBalanceByClearing(AccountBalanceClearingRequest req) { ClearingCategory category = getClearingCategoryByCompanyId(req.getCompanyId()); - req.setFirstLegAmount(safeBD(req.getFirstLegAmount())); + req.setFirstLegAmount(BigDecimalUtil.safeBD(req.getFirstLegAmount())); if (category.equals(ClearingCategory.I)) { updateAccountCategoryIClrn(req.getAccountId(), req.getCompanyId(), req.getFirstLegAmount()); updateAccountCategoryITran(req.getFirstLegAmount()); @@ -120,9 +121,9 @@ public class AccountBalanceService { private void updateAccountCategoryIClrn(Long accountId, Long companyId, BigDecimal firstLegAmount) { AccountBalance accountBalance = loadAccountBalance(accountId, companyId, AccountType.Clrn); log.trace("updating AccountBalance {} I CLRN", accountBalance.getId()); - BigDecimal previousFreeBalanceAmount = safeBD(accountBalance.getFreeBalanceAmount()); - BigDecimal previousChangeBalanceAmount = safeBD(accountBalance.getChangeBalanceAmount()); - BigDecimal previousBalanceAmount = safeBD(accountBalance.getBalanceAmount()); + BigDecimal previousFreeBalanceAmount = BigDecimalUtil.safeBD(accountBalance.getFreeBalanceAmount()); + BigDecimal previousChangeBalanceAmount = BigDecimalUtil.safeBD(accountBalance.getChangeBalanceAmount()); + BigDecimal previousBalanceAmount = BigDecimalUtil.safeBD(accountBalance.getBalanceAmount()); accountBalance.setFreeBalanceAmount(previousFreeBalanceAmount.subtract(firstLegAmount)); accountBalance.setChangeBalanceAmount(previousChangeBalanceAmount.subtract(firstLegAmount)); accountBalance.setBalanceAmount(previousBalanceAmount.subtract(firstLegAmount)); @@ -134,7 +135,7 @@ public class AccountBalanceService { private void updateAccountCategoryITran(BigDecimal firstLegAmount) { AccountBalance accountBalance = loadAccountBalance(AccountType.Tran); log.trace("updating AccountBalance {} I TRAN", accountBalance.getId()); - BigDecimal previousDebitAmount = safeBD(accountBalance.getDebitAmount()); + BigDecimal previousDebitAmount = BigDecimalUtil.safeBD(accountBalance.getDebitAmount()); accountBalance.setDebitAmount(previousDebitAmount.add(firstLegAmount.abs())); accountBalance.setUpdated(Instant.now()); log.trace("updateAccountCategoryITran: {}", accountBalance.getId()); @@ -144,9 +145,9 @@ public class AccountBalanceService { private void updateAccountCategoryVInfo(Long accountId, Long companyId, BigDecimal firstLegAmount) { AccountBalance accountBalance = loadAccountBalance(accountId, companyId, AccountType.Info); log.trace("updating AccountBalance {} V INFO", accountBalance.getId()); - BigDecimal previousFreeBalanceAmount = safeBD(accountBalance.getFreeBalanceAmount()); - BigDecimal changeBalanceAmount = safeBD(accountBalance.getChangeBalanceAmount()); - BigDecimal balanceAmount = safeBD(accountBalance.getBalanceAmount()); + BigDecimal previousFreeBalanceAmount = BigDecimalUtil.safeBD(accountBalance.getFreeBalanceAmount()); + BigDecimal changeBalanceAmount = BigDecimalUtil.safeBD(accountBalance.getChangeBalanceAmount()); + BigDecimal balanceAmount = BigDecimalUtil.safeBD(accountBalance.getBalanceAmount()); accountBalance.setFreeBalanceAmount(previousFreeBalanceAmount.subtract(firstLegAmount)); accountBalance.setChangeBalanceAmount(changeBalanceAmount.subtract(firstLegAmount)); accountBalance.setBalanceAmount(balanceAmount.subtract(firstLegAmount)); @@ -158,9 +159,9 @@ public class AccountBalanceService { private void updateAccountCategoryVAnlt(BigDecimal firstLegAmount) { AccountBalance accountBalance = loadAccountBalance(AccountType.Anlt); log.trace("updating AccountBalance {} V ANLT", accountBalance.getId()); - BigDecimal previousFreeBalanceAmount = safeBD(accountBalance.getFreeBalanceAmount()); - BigDecimal previousChangeBalanceAmount = safeBD(accountBalance.getChangeBalanceAmount()); - BigDecimal previousBalanceAmount = safeBD(accountBalance.getBalanceAmount()); + BigDecimal previousFreeBalanceAmount = BigDecimalUtil.safeBD(accountBalance.getFreeBalanceAmount()); + BigDecimal previousChangeBalanceAmount = BigDecimalUtil.safeBD(accountBalance.getChangeBalanceAmount()); + BigDecimal previousBalanceAmount = BigDecimalUtil.safeBD(accountBalance.getBalanceAmount()); accountBalance.setFreeBalanceAmount(previousFreeBalanceAmount.subtract(firstLegAmount)); accountBalance.setChangeBalanceAmount(previousChangeBalanceAmount.subtract(firstLegAmount)); accountBalance.setBalanceAmount(previousBalanceAmount.subtract(firstLegAmount)); @@ -172,7 +173,7 @@ public class AccountBalanceService { private void updateAccountCategoryBClrn(Long accountId, Long companyId, BigDecimal firstLegAmount) { AccountBalance accountBalance = loadAccountBalance(accountId, companyId, AccountType.Clrn); log.trace("updating AccountBalance {} B CLRN", accountBalance.getId()); - BigDecimal debitAmount = safeBD(accountBalance.getDebitAmount()); + BigDecimal debitAmount = BigDecimalUtil.safeBD(accountBalance.getDebitAmount()); accountBalance.setDebitAmount(plus(debitAmount, firstLegAmount.abs())); accountBalance.setUpdated(Instant.now()); log.trace("updateAccountCategoryBClrn: {}", accountBalance.getId()); @@ -192,8 +193,4 @@ public class AccountBalanceService { "accountType", type.getKey()) ); } - - private BigDecimal safeBD(BigDecimal bd) { - return bd == null ? BigDecimal.ZERO : bd; - } } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java index 4381680ea..a061ed233 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java @@ -7,12 +7,14 @@ import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.execution.ExecutionDeposit; import ru.clearing.classes.statics.data.generated.ClearingMemberCategory; import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsAssets; +import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsMoney; import ru.spcex.clearing.error.ClearingErrorInternal; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.Consts; import ru.spcex.clearing.platform.messaging.domain.cud.balance.AccountBalanceClearingRequest; import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; import ru.spcex.clearing.service.builder.LiabilitiesClaimsAssetsCreator; +import ru.spcex.clearing.service.builder.LiabilitiesClaimsMoneyCreator; import ru.spcex.clearing.service.builder.PaymentInstructionCreator; import ru.spcex.clearing.service.order.ExecutionDepositSorter; import ru.spcex.platform.enumeration.Allowed; @@ -33,6 +35,7 @@ public class Clearing { private final Logger log = LoggerFactory.getLogger(getClass()); private final Imdg executionDepositImdg; private final Imdg liabilitiesClaimsAssetsImdg; + private final Imdg liabilitiesClaimsMoneyImdg; private final Imdg clearingCategoryImdg; private final ExecutionDepositSorter sorter; private final BiFunction validation; @@ -40,6 +43,8 @@ public class Clearing { private final ImdgId idProvider; private final KafkaSender kafka; private final LiabilitiesClaimsAssetsCreator lbltsClmsAssetsCreator; + private final LiabilitiesClaimsMoneyCreator lbltsClmsMoneyCreator; + private Long lastAccBalanceResponseId = 0L; //при прохождении по выгруженным ExecutionDeposit, ошибочные статусы проставляются для //контр сделок. В таком случае, в коллекции хранятся не синхронизированные с IMDG ExecutionDeposit @@ -51,16 +56,18 @@ public class Clearing { @Autowired public Clearing(ImdgProvider imdgProvider, ExecutionDepositSorter sorter, PaymentInstructionCreator paymentInstructionCreator, - BiFunction validation, KafkaSender kafka, LiabilitiesClaimsAssetsCreator liabilitiesClaimsAssetsCreator) { + BiFunction validation, KafkaSender kafka, LiabilitiesClaimsAssetsCreator liabilitiesClaimsAssetsCreator, LiabilitiesClaimsMoneyCreator lbltsClmsMoneyCreator) { this.executionDepositImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionDeposit, ExecutionDeposit.class); this.clearingCategoryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class); this.liabilitiesClaimsAssetsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_LiabilitiesClaimsAssets, LiabilitiesClaimsAssets.class); + this.liabilitiesClaimsMoneyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_LiabilitiesClaimsMoney, LiabilitiesClaimsMoney.class); this.paymentInstructionCreator = paymentInstructionCreator; this.idProvider = imdgProvider.getImdgIdGenerator(); this.sorter = sorter; this.validation = validation; this.kafka = kafka; this.lbltsClmsAssetsCreator = liabilitiesClaimsAssetsCreator; + this.lbltsClmsMoneyCreator = lbltsClmsMoneyCreator; } public void startClearing() { @@ -165,8 +172,7 @@ public class Clearing { Long sentRequestId = kafka.sendRequestToQueue(Consts.BALANCE_ACCOUNT_UPDATE, request); log.trace("sent request to kafka, requestId: {}", sentRequestId); try { - wait(5000); - //todo check that request Id was processed succesfully + wait(10000); //если на этом месте произошла ошибка - непонятно как обрабатывать //т.к. этом может быть уже вторая часть сделки, для первой accountBalance уже был обновлен //либо вне зависимости от того какая часть сделки, accountBalance на самом деле мог быть @@ -181,9 +187,33 @@ public class Clearing { continue; } } - LiabilitiesClaimsAssets liabilitiesClaimsAssets = lbltsClmsAssetsCreator.createLiabilitiesClaimsAssets(category, execDeposit); - liabilitiesClaimsAssetsImdg.insert(liabilitiesClaimsAssets); - log.trace("LiabilitiesClaimsAssets {} was created", liabilitiesClaimsAssets.getId()); + LiabilitiesClaimsAssets lca = lbltsClmsAssetsCreator.createLiabilitiesClaimsAssets(category, execDeposit); + liabilitiesClaimsAssetsImdg.insert(lca); + log.trace("LiabilitiesClaimsAssets {} was created", lca.getId()); + Optional lcmFirstLegFound = lbltsClmsMoneyCreator.searchLcmBySettlementDate(lca.getAccountId(), lca.getCompanyId(), lca.getSettlementDate()); + var wrapperFirstLegCreated = new Object() {LiabilitiesClaimsMoney firstLegCreated;}; + lcmFirstLegFound.ifPresentOrElse(lcm -> { + log.trace("LiabilitiesClaimsMoney first leg {} was found", lcm.getId()); + lbltsClmsMoneyCreator.updateFirstLegLcm(lcm, lca, category); + liabilitiesClaimsMoneyImdg.update(lcm); + }, () -> { + LiabilitiesClaimsMoney lcmFirstLeg = lbltsClmsMoneyCreator.createFirstLegLcm(lca, category); + liabilitiesClaimsMoneyImdg.insert(lcmFirstLeg); + log.trace("LiabilitiesClaimsMoney first leg {} was created", lcmFirstLeg.getId()); + wrapperFirstLegCreated.firstLegCreated = lcmFirstLeg; + }); + Optional lcmSecondLegFound = lbltsClmsMoneyCreator.searchLcmByRefundDate(lca.getAccountId(), lca.getCompanyId(), lca.getRefundDate()); + lcmSecondLegFound.ifPresentOrElse(lcm -> { + log.trace("LiabilitiesClaimsMoney second leg {} was found", lcm.getId()); + lbltsClmsMoneyCreator.updateSecondLegLcm(lcm, lca, category); + liabilitiesClaimsMoneyImdg.update(lcm); + }, () -> { + LiabilitiesClaimsMoney lcmSecondLeg = lbltsClmsMoneyCreator.createSecondLegLcm(lca, category); + liabilitiesClaimsMoneyImdg.insert(lcmSecondLeg); + log.trace("LiabilitiesClaimsMoney second leg {} was created", lcmSecondLeg.getId()); + }); + lbltsClmsAssetsCreator.updateLca(lca, lcmFirstLegFound.orElse(wrapperFirstLegCreated.firstLegCreated)); + liabilitiesClaimsAssetsImdg.update(lca); } } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/LiabilitiesClaimsAssetsCreator.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/LiabilitiesClaimsAssetsCreator.java index cf4bcd74b..85876ea63 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/LiabilitiesClaimsAssetsCreator.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/LiabilitiesClaimsAssetsCreator.java @@ -6,6 +6,7 @@ import ru.clearing.classes.statics.data.account.Account; import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.execution.ExecutionDeposit; import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsAssets; +import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsMoney; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.platform.enumeration.AccountType; import ru.spcex.platform.enumeration.ClearingCategory; @@ -66,4 +67,10 @@ public class LiabilitiesClaimsAssetsCreator { liabilitiesClaimsAssets.setClearingDate(LocalDate.now()); return liabilitiesClaimsAssets; } + + public void updateLca(LiabilitiesClaimsAssets lca, + LiabilitiesClaimsMoney firstLeg) { + lca.setLiabilitiesClaimsMoneyId(firstLeg.getId()); + lca.setUpdated(Instant.now()); + } } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/LiabilitiesClaimsMoneyCreator.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/LiabilitiesClaimsMoneyCreator.java new file mode 100644 index 000000000..f6fd17c5c --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/LiabilitiesClaimsMoneyCreator.java @@ -0,0 +1,104 @@ +package ru.spcex.clearing.service.builder; + +import org.springframework.stereotype.Component; +import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsAssets; +import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsMoney; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.platform.enumeration.ClearingCategory; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.Optional; + +import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD; + +@Component +public class LiabilitiesClaimsMoneyCreator { + private final Imdg liabilitiesClaimsMoneyImdg; + private final static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + + public LiabilitiesClaimsMoneyCreator(ImdgProvider imdgProvider) { + this.liabilitiesClaimsMoneyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_LiabilitiesClaimsMoney, LiabilitiesClaimsMoney.class); + } + + public Optional searchLcmBySettlementDate(Long accountId, Long companyId, LocalDate settlementDate) { + String sql = String.format("accountId=%d and companyId=%d and settlementDate=%s", + accountId, companyId, formatter.format(settlementDate)); + LiabilitiesClaimsMoney liabilitiesClaimsMoney = liabilitiesClaimsMoneyImdg.getSingleObjectBySQL(sql); + return Optional.ofNullable(liabilitiesClaimsMoney); + } + + public void updateFirstLegLcm(LiabilitiesClaimsMoney liabilitiesClaimsMoney, + LiabilitiesClaimsAssets liabilitiesClaimsAssets, ClearingCategory category) { + BigDecimal prevLAmount = safeBD(liabilitiesClaimsMoney.getLiabilitiesAmount()); + BigDecimal prevClaimsAmount = safeBD(liabilitiesClaimsMoney.getClaimsAmount()); + BigDecimal lcaLiabilitiesQuantity = safeBD(liabilitiesClaimsAssets.getLiabilitiesQuantity()); + BigDecimal lcaClaimsQuantity = safeBD(liabilitiesClaimsAssets.getClaimsQuantity()); + liabilitiesClaimsMoney.setLiabilitiesAmount(prevLAmount.add(lcaLiabilitiesQuantity)); + liabilitiesClaimsMoney.setClaimsAmount(prevClaimsAmount.add(lcaClaimsQuantity)); + } + + + public LiabilitiesClaimsMoney createFirstLegLcm(LiabilitiesClaimsAssets lca, ClearingCategory category) { + LiabilitiesClaimsMoney lcm = new LiabilitiesClaimsMoney(); + lcm.setCompanyId(lca.getCompanyId()); + lcm.setAccountId(lca.getAccountId()); + lcm.setAccountType(lca.getAccountType()); + lcm.setAccount(lca.getAccount()); + if (category.equals(ClearingCategory.I) || category.equals(ClearingCategory.V)) { + lcm.setLiabilitiesAmount(lca.getLiabilitiesQuantity()); + } else if (category.equals(ClearingCategory.B)) { + lcm.setClaimsAmount(lca.getClaimsQuantity()); + } + lcm.setSettlementDate(lca.getSettlementDate()); + lcm.setTradingDate(lca.getTradingDate()); + lcm.setCurrency(lca.getCurrency()); + lcm.setTradingCode(lca.getTradingCode()); + lcm.setShortName(lca.getShortName()); + lcm.setFullName(lca.getFullName()); + lcm.setCreated(lca.getCreated()); + lcm.setClearingDate(LocalDate.now()); + return lcm; + } + + public Optional searchLcmByRefundDate(Long accountId, Long companyId, LocalDate refundDate) { + String sql = String.format("accountId=%d and companyId=%d and settlementDate=%s", + accountId, companyId, formatter.format(refundDate)); + LiabilitiesClaimsMoney liabilitiesClaimsMoney = liabilitiesClaimsMoneyImdg.getSingleObjectBySQL(sql); + return Optional.ofNullable(liabilitiesClaimsMoney); + } + + public LiabilitiesClaimsMoney createSecondLegLcm(LiabilitiesClaimsAssets lca, ClearingCategory category) { + LiabilitiesClaimsMoney lcm = new LiabilitiesClaimsMoney(); + lcm.setCompanyId(lca.getCompanyId()); + lcm.setAccountId(lca.getAccountId()); + lcm.setAccountType(lca.getAccountType()); + lcm.setAccount(lca.getAccount()); + if (category.equals(ClearingCategory.I) || category.equals(ClearingCategory.V)) { + lcm.setClaimsAmount(lca.getClaimsQuantity()); + } else if (category.equals(ClearingCategory.B)) { + lcm.setLiabilitiesAmount(lca.getLiabilitiesQuantity()); + } + lcm.setSettlementDate(lca.getRefundDate()); + lcm.setTradingDate(lca.getTradingDate()); + lcm.setCurrency(lca.getCurrency()); + lcm.setTradingCode(lca.getTradingCode()); + lcm.setShortName(lca.getShortName()); + lcm.setFullName(lca.getFullName()); + lcm.setCreated(lca.getCreated()); + lcm.setClearingDate(lca.getRefundDate()); + return lcm; + } + + public void updateSecondLegLcm(LiabilitiesClaimsMoney lcm, LiabilitiesClaimsAssets lca, ClearingCategory category) { + BigDecimal prevLiabilitiesAmount = safeBD(lcm.getLiabilitiesAmount()); + BigDecimal prevClaimsAmount = safeBD(lcm.getClaimsAmount()); + BigDecimal lcaLiabilitiesQuantity = safeBD(lca.getLiabilitiesQuantity()); + BigDecimal lcaClaimsQuantity = safeBD(lca.getClaimsQuantity()); + lcm.setLiabilitiesAmount(prevLiabilitiesAmount.add(lcaLiabilitiesQuantity)); + lcm.setClaimsAmount(prevClaimsAmount.add(lcaClaimsQuantity)); + } +} diff --git a/platform-parent/platform-utils/src/main/java/ru/spcex/platform/utils/number/BigDecimalUtil.java b/platform-parent/platform-utils/src/main/java/ru/spcex/platform/utils/number/BigDecimalUtil.java index b30f30f12..c458709f9 100644 --- a/platform-parent/platform-utils/src/main/java/ru/spcex/platform/utils/number/BigDecimalUtil.java +++ b/platform-parent/platform-utils/src/main/java/ru/spcex/platform/utils/number/BigDecimalUtil.java @@ -17,4 +17,9 @@ public class BigDecimalUtil { return null; } } + + public static BigDecimal safeBD(BigDecimal bd) { + return bd == null ? BigDecimal.ZERO : bd; + } + } From c9676d3dfb6e4149c2a8fc34bd9bbba7d598a8c8 Mon Sep 17 00:00:00 2001 From: AKurakin Date: Fri, 3 Feb 2023 16:47:10 +0300 Subject: [PATCH 41/42] =?UTF-8?q?http://jira.mfd.msk:8088/browse/CLS-189?= =?UTF-8?q?=20=D0=B8=D0=BD=D1=82=D0=B5=D0=B3=D1=80=D0=B0=D1=86=D0=B8=D1=8F?= =?UTF-8?q?=20=D0=BA=D0=BE=D0=B4=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ru/spcex/clearing/service/Clearing.java | 9 +++++++ .../builder/PaymentInstructionCreator.java | 24 ++++--------------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java index a061ed233..c84fb834d 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java @@ -8,6 +8,7 @@ import ru.clearing.classes.statics.data.execution.ExecutionDeposit; import ru.clearing.classes.statics.data.generated.ClearingMemberCategory; import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsAssets; import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsMoney; +import ru.clearing.classes.statics.data.payment.PaymentInstruction; import ru.spcex.clearing.error.ClearingErrorInternal; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.Consts; @@ -214,6 +215,14 @@ public class Clearing { }); lbltsClmsAssetsCreator.updateLca(lca, lcmFirstLegFound.orElse(wrapperFirstLegCreated.firstLegCreated)); liabilitiesClaimsAssetsImdg.update(lca); + + List paymentInstructions = paymentInstructionCreator.createAndSavePaymentInstructions(lca, Collections.singleton(category)); + paymentInstructionCreator.updateFieldLiabilitiesClaimsAssetsByPayment(lca, paymentInstructions, Collections.singleton(category)); + liabilitiesClaimsAssetsImdg.update(lca); + var firstLegLiabilitiesClaimsMoney = lcmFirstLegFound.orElseGet(() -> wrapperFirstLegCreated.firstLegCreated); + paymentInstructionCreator.updateFieldLiabilitiesClaimsMoneyByPayment(firstLegLiabilitiesClaimsMoney, paymentInstructions, Collections.singleton(category)); + liabilitiesClaimsMoneyImdg.update(firstLegLiabilitiesClaimsMoney); + log.trace("LiabilitiesClaimsMoney first leg {} was updated", firstLegLiabilitiesClaimsMoney.getId()); } } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionCreator.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionCreator.java index 7a8fafd86..60dc70007 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionCreator.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionCreator.java @@ -70,7 +70,7 @@ public class PaymentInstructionCreator { public List createAndSavePaymentInstructions(LiabilitiesClaimsAssets liabilitiesClaimsAssets, Collection clearingCategory) { List newPaymentInstructions = createPaymentInstructions(liabilitiesClaimsAssets, clearingCategory); - log.debug("Created {} PaymentInstruction by LiabilitiesClaimsAssets[{}]", + log.trace("Created {} PaymentInstruction by LiabilitiesClaimsAssets[{}]. Do save ti IMDG.", newPaymentInstructions.size(), liabilitiesClaimsAssets.getId()); for (PaymentInstruction instruction : newPaymentInstructions) { paymentInstructionImdg.insert(instruction); @@ -436,23 +436,7 @@ public class PaymentInstructionCreator { /** * 2.2.2.1. Выполнить Изменение liabilitiesClaimsAssets по paymentInstruction. */ - public LiabilitiesClaimsAssets updateLiabilitiesClaimsAssetsByPaymentInstruction(LiabilitiesClaimsAssets liabilitiesClaimsAssets, - List paymentInstructions, - Collection clearingCategory) { - Long lId = liabilitiesClaimsAssets.getId(); - log.debug("Update LiabilitiesClaimsAssets[{}] by paymentInstructions {}", lId, paymentInstructions.stream().map(SpcexObjectBase::getId).collect(Collectors.toList())); - liabilitiesClaimsAssets = liabilitiesClaimsAssetsImdg.getSingleObjectByID(lId); // update data for update - if (liabilitiesClaimsAssets == null) { - throw new RuntimeException("IMDG not contains liabilitiesClaimsAssets.id=" + lId); - } - - updateFieldLiabilitiesClaimsAssetsByPayment(liabilitiesClaimsAssets, paymentInstructions, clearingCategory); - - liabilitiesClaimsAssetsImdg.update(liabilitiesClaimsAssets); - return liabilitiesClaimsAssets; - } - - protected void updateFieldLiabilitiesClaimsAssetsByPayment(LiabilitiesClaimsAssets liabilitiesClaimsAssets, + public void updateFieldLiabilitiesClaimsAssetsByPayment(LiabilitiesClaimsAssets liabilitiesClaimsAssets, List paymentInstructions, Collection clearingCategory) { @@ -517,12 +501,12 @@ public class PaymentInstructionCreator { /** * Обновление liabilitiesClaimsMoney первой ноги по liabilitiesClaimsAssets - * @param liabilitiesClaimsMoney обновить этот объект + * @param liabilitiesClaimsMoney обновить этот объект (firstLeg) * @param paymentInstructions * @param clearingCategory * @return были внесены изменения в liabilitiesClaimsMoney */ - protected boolean updateFieldLiabilitiesClaimsMoneyByPayment(LiabilitiesClaimsMoney liabilitiesClaimsMoney, + public boolean updateFieldLiabilitiesClaimsMoneyByPayment(LiabilitiesClaimsMoney liabilitiesClaimsMoney, List paymentInstructions, Collection clearingCategory) { boolean modified = false; From 0f2c8bf2dcf5d43342fc925ffd2214cadcad8989 Mon Sep 17 00:00:00 2001 From: ialbert Date: Fri, 3 Feb 2023 16:52:03 +0300 Subject: [PATCH 42/42] http://jira.mfd.msk:8088/browse/CLS-189 --- .../src/main/java/ru/spcex/clearing/service/Clearing.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java index c84fb834d..179569ee6 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java @@ -215,11 +215,13 @@ public class Clearing { }); lbltsClmsAssetsCreator.updateLca(lca, lcmFirstLegFound.orElse(wrapperFirstLegCreated.firstLegCreated)); liabilitiesClaimsAssetsImdg.update(lca); + log.trace("creating paymentInstructions"); List paymentInstructions = paymentInstructionCreator.createAndSavePaymentInstructions(lca, Collections.singleton(category)); paymentInstructionCreator.updateFieldLiabilitiesClaimsAssetsByPayment(lca, paymentInstructions, Collections.singleton(category)); liabilitiesClaimsAssetsImdg.update(lca); var firstLegLiabilitiesClaimsMoney = lcmFirstLegFound.orElseGet(() -> wrapperFirstLegCreated.firstLegCreated); + log.trace("updating LiabilitiesClaimsMoney by payment"); paymentInstructionCreator.updateFieldLiabilitiesClaimsMoneyByPayment(firstLegLiabilitiesClaimsMoney, paymentInstructions, Collections.singleton(category)); liabilitiesClaimsMoneyImdg.update(firstLegLiabilitiesClaimsMoney); log.trace("LiabilitiesClaimsMoney first leg {} was updated", firstLegLiabilitiesClaimsMoney.getId());