From 122e5f9d263d4e3be219892b3839a5ffb846a80e Mon Sep 17 00:00:00 2001 From: ialbert Date: Mon, 14 Aug 2023 16:21:30 +0300 Subject: [PATCH] forming payment instructions by money AM*B registers --- .../spcex/clearing/service/Sdf12Creator.java | 90 ++++++ .../stage/PrimaryAuctionB0Session.java | 4 +- .../stage/PrimaryAuctionBnSession.java | 8 +- .../FormingPaymentInstructionSecurities.java | 281 ++++++++++++------ .../session/stage/impl/Sdf03And12Sender.java | 104 +++++++ 5 files changed, 389 insertions(+), 98 deletions(-) create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Sdf12Creator.java create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/Sdf03And12Sender.java diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Sdf12Creator.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Sdf12Creator.java new file mode 100644 index 000000000..81569b37a --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Sdf12Creator.java @@ -0,0 +1,90 @@ +package ru.spcex.clearing.service; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import ru.clearing.classes.statics.data.account.Account; +import ru.clearing.classes.statics.data.payment.PaymentInstruction; +import ru.clearing.classes.statics.data.sdf.SDf12; +import ru.clearing.classes.statics.data.security.Security; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgId; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; +import ru.spcex.platform.imdg.api.predicate.specific.SecuritySelector; +import ru.spcex.platform.utils.number.BigDecimalUtil; + +import java.time.Instant; +import java.util.Objects; + +@Component +public class Sdf12Creator { + private Logger log = LoggerFactory.getLogger(getClass()); + private final ImdgId idGenerator; + private final SecuritySelector securitySelector; + private final Imdg sDf12Imdg; + + public Sdf12Creator(ImdgProvider imdgProvider) { + this.idGenerator = imdgProvider.getImdgIdGenerator(); + this.securitySelector = new SecuritySelector<>(imdgProvider, Security.class); + this.sDf12Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf12, SDf12.class); + } + + public SDf12 create(PaymentInstruction paymentInstruction, Account dtrnAcc) { + log.debug("creating sdf12"); + SDf12 sDf12 = new SDf12(); + if (Objects.equals(paymentInstruction.getDebitLeg_accountId(), dtrnAcc.getId())) { + sDf12.setDirection("RECFREE"); + sDf12.setDepoCodeSender(paymentInstruction.getDebitLeg_account()); + sDf12.setDepoCodeAdressee(paymentInstruction.getCreditLeg_account()); + } else if (Objects.equals(paymentInstruction.getCreditLeg_accountId(), dtrnAcc.getId())) { + sDf12.setDirection("DELFREE"); + sDf12.setDepoCodeSender(paymentInstruction.getCreditLeg_account()); + sDf12.setDepoCodeAdressee(paymentInstruction.getDebitLeg_account()); + } + sDf12.setId(idGenerator.nextId()); + sDf12.setOutDocument(sDf12.getId().toString()); + sDf12.setQuantity(BigDecimalUtil.limitDecimalPlaces(paymentInstruction.getCreditLeg_amount().toString(), 2)); + Security security = securitySelector.selectSecurityById(paymentInstruction.getCreditLeg_securityId()); + if (security != null) { + sDf12.setSecurityCode(security.getSecuritySymbol()); + } +// sDf12.setTransactionNumber(); + sDf12.setGenerationTime(Instant.now()); + return sDf12; + } + + + public SDf12 createWithoutIntermediate(PaymentInstruction paymentInstruction) { + log.debug("creating sdf12"); + SDf12 sDf12 = new SDf12(); //todo remove + sDf12.setId(idGenerator.nextId()); + sDf12.setOutDocument(sDf12.getId().toString()); + sDf12.setDirection("DELFREE"); + sDf12.setQuantity(BigDecimalUtil.limitDecimalPlaces(paymentInstruction.getCreditLeg_amount().toString(), 2)); + Security security = securitySelector.selectSecurityById(paymentInstruction.getCreditLeg_securityId()); + if (security != null) { + sDf12.setSecurityCode(security.getSecuritySymbol()); + } + sDf12.setDepoCodeSender(paymentInstruction.getCreditLeg_account()); + sDf12.setDepoCodeAdressee(paymentInstruction.getDebitLeg_account()); +// sDf12.setTransactionNumber(); + sDf12.setGenerationTime(Instant.now()); + return sDf12; + } + + + public Long maxTxNumber() { + long maxTxNumber = 1L; + ImdgPredicateBuilder predicateBuilder = sDf12Imdg.predicateBuilder(); + ImdgPredicate notEmptyTransactionNum = predicateBuilder.not(predicateBuilder.equals("transactionNumber", "")); + Long maxId = sDf12Imdg.aggregateLongMax("id", notEmptyTransactionNum); + if (maxId != null) { + SDf12 sDf12 = sDf12Imdg.getSingleObjectByID(maxId); + maxTxNumber = Long.parseLong(sDf12.getTransactionNumber()) + 1; + } + return maxTxNumber; + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionB0Session.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionB0Session.java index fe67416e2..47504aab5 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionB0Session.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionB0Session.java @@ -39,7 +39,7 @@ public class PrimaryAuctionB0Session extends AbstractSession implements Initiali private final InclusionObligations inclusionObligations; private final InspectionObligations inspectionObligations; private final FormingRegistersOnOS formingRegistersOnOS; - private final FormingPaymentInstructionAssets formingPaymentInstruction; + private final FormingPaymentInstructionSecurities formingPaymentInstruction; //TODO CLRNWORM //private final FormingPaymentInstructionDealsFinalMkr formingPaymentInstructionDealsFinalMkr; private final UnlockResources unlockResources; @@ -61,7 +61,7 @@ public class PrimaryAuctionB0Session extends AbstractSession implements Initiali ObligationAdmission obligationsAdmission, InclusionObligations inclusionObligations, FormingRegistersOnOS formingRegistersOnOS, - FormingPaymentInstructionAssets formingPaymentInstruction, + FormingPaymentInstructionSecurities formingPaymentInstruction, // FormingPaymentInstructionDealsFinalMkr formingPaymentInstructionDealsFinalMkr, UnlockResources unlockResources, FinishingSession finishingSession, diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionBnSession.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionBnSession.java index b8ce4e012..6e068005d 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionBnSession.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionBnSession.java @@ -39,7 +39,7 @@ public class PrimaryAuctionBnSession extends AbstractSession implements Initiali private final InclusionObligations inclusionObligations; private final InspectionObligations inspectionObligations; private final FormingRegistersOnOS formingRegistersOnOS; - private final FormingPaymentInstructionAssets formingPaymentInstructionAssets; + private final FormingPaymentInstructionSecurities formingPaymentInstruction; // private final FormingPaymentInstruction formingPaymentInstruction; // private final FormingPaymentInstructionDealsFinalMkr formingPaymentInstructionDealsFinalMkr; private final UnlockResources unlockResources; @@ -63,7 +63,7 @@ public class PrimaryAuctionBnSession extends AbstractSession implements Initiali FormingRegistersOnOS formingRegistersOnOS, // FormingPaymentInstruction formingPaymentInstruction, // FormingPaymentInstructionDealsFinalMkr formingPaymentInstructionDealsFinalMkr, - FormingPaymentInstructionAssets formingPaymentInstructionAssets, UnlockResources unlockResources, + FormingPaymentInstructionSecurities formingPaymentInstruction, UnlockResources unlockResources, FinishingSession finishingSession, EndStageNotification endStageNotification, IMessageResolver messageResolver, @@ -76,7 +76,7 @@ public class PrimaryAuctionBnSession extends AbstractSession implements Initiali this.obligationsAdmission = obligationsAdmission; this.inclusionObligations = inclusionObligations; this.formingRegistersOnOS = formingRegistersOnOS; - this.formingPaymentInstructionAssets = formingPaymentInstructionAssets; + this.formingPaymentInstruction = formingPaymentInstruction; // this.formingPaymentInstruction = formingPaymentInstruction; this.unlockResources = unlockResources; this.finishingSession = finishingSession; @@ -183,7 +183,7 @@ public class PrimaryAuctionBnSession extends AbstractSession implements Initiali FormingPaymentInstructionPayload payload = new FormingPaymentInstructionPayload(); payload.setSessionId(currSession.getId()); //stage 7 - paymentResult = runStage(TaskType.FormingPaymentInstruction, payload, formingPaymentInstructionAssets); + paymentResult = runStage(TaskType.FormingPaymentInstruction, payload, formingPaymentInstruction); } if (paymentResult.getStageResult().getPaymentInstructions().isEmpty()) { log.info("no payment instructions were created, sending SDF56"); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionSecurities.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionSecurities.java index 20e1ee124..850b63b06 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionSecurities.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionSecurities.java @@ -13,6 +13,7 @@ import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.sdf.SDf03; import ru.clearing.classes.statics.data.sdf.SDf12; import ru.clearing.classes.statics.data.security.Security; +import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.Consts; import ru.spcex.clearing.platform.messaging.domain.cud.balance.ExportToFileRequest; @@ -21,15 +22,14 @@ import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; import ru.spcex.clearing.service.RegistryManager; import ru.spcex.clearing.service.Sdf03Creator; import ru.spcex.clearing.service.builder.PaymentInstructionBuilderForSecurities; +import ru.spcex.clearing.service.builder.PaymentInstructionBuilderV2; import ru.spcex.clearing.session.stage.ISessionStage; import ru.spcex.clearing.session.stage.StageResult; import ru.spcex.clearing.session.stage.Task; import ru.spcex.clearing.session.stage.payment.group.PaymentGroup; import ru.spcex.clearing.session.stage.payment.group.RegistryLiabilitiesGroup; import ru.spcex.clearing.session.stage.task.FormingPaymentInstructionPayload; -import ru.spcex.platform.enumeration.AccountType; -import ru.spcex.platform.enumeration.InstrumentType; -import ru.spcex.platform.enumeration.RegistryTradingParams; +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; @@ -37,17 +37,18 @@ import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; import ru.spcex.platform.imdg.api.predicate.specific.RegistryCodeSqlBuilder; import ru.spcex.platform.imdg.api.predicate.specific.SecuritySelector; +import ru.spcex.platform.utils.enumeration.EnumMessage; import ru.spcex.platform.utils.enumeration.IEnumKey; import ru.spcex.platform.utils.enumeration.IMessageResolver; import ru.spcex.platform.utils.enumeration.SimpleMessageResolver; import ru.spcex.platform.utils.number.BigDecimalUtil; +import java.math.BigDecimal; import java.time.Instant; import java.time.LocalDate; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; -import java.util.stream.Stream; import static ru.spcex.platform.enumeration.RegistryTradingParams.*; import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD; @@ -71,10 +72,11 @@ public class FormingPaymentInstructionSecurities implements ISessionStage { private final IMessageResolver msgResolver = new SimpleMessageResolver(); private final RegistryManager rgsMng; private final SecuritySelector securitySelector; + private final Sdf03And12Sender sdf03And12Sender; @Autowired public FormingPaymentInstructionSecurities(ImdgProvider imdgProvider, - KafkaSender kafkaSender, Sdf03Creator sdf03Creator, RegistryManager rgsMng) { + KafkaSender kafkaSender, Sdf03Creator sdf03Creator, RegistryManager rgsMng, Sdf03And12Sender sdf03And12Sender) { this.kafkaSender = kafkaSender; this.imdgProvider = imdgProvider; this.idGenerator = imdgProvider.getImdgIdGenerator(); @@ -88,6 +90,7 @@ public class FormingPaymentInstructionSecurities implements ISessionStage { this.sdf03Creator = sdf03Creator; this.rgsMng = rgsMng; this.securitySelector = new SecuritySelector<>(imdgProvider, Security.class); + this.sdf03And12Sender = sdf03And12Sender; } @Override @@ -95,7 +98,7 @@ public class FormingPaymentInstructionSecurities implements ISessionStage { FormingPaymentInstructionPayload payload = (FormingPaymentInstructionPayload) task.getData(); switch (task.getTaskType()) { case FormingPaymentInstruction -> { - return formingPaymentInstructions(payload.getSessionId(), payload.getPaymentInstructionReturns()); + return formingPaymentInstructions(payload.getSessionId()); } default -> { throw new IllegalStateException("Unknown task type: " + task.getTaskType()); @@ -104,7 +107,7 @@ public class FormingPaymentInstructionSecurities implements ISessionStage { } - private Collection selectRegistries() { + private Collection selectSecurityRegistries() { ImdgPredicateBuilder rgsPb = registryImdg.predicateBuilder(); RegistryCodeSqlBuilder registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance( CS_T, LS_T @@ -118,104 +121,198 @@ public class FormingPaymentInstructionSecurities implements ISessionStage { .collect(Collectors.toList()); } + private Collection selectMoneyRegistries() { + ImdgPredicateBuilder rgsPb = registryImdg.predicateBuilder(); + RegistryCodeSqlBuilder registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance( + AM_B + ); + ImdgPredicate rgsCodePrdct = rgsPb.sql(registryCodeSqlBuilder.build()); + Collection registries = registryImdg.getCollectionObjectsByPredicate(rgsCodePrdct); + return registries.stream() + .filter(rgs -> Objects.equals(rgs.getValueDate(), rgs.getSettlementDate())) + .collect(Collectors.toList()); + } + + /** * часть для бумаг по первичке IPO0 IPOT IPOB * вторичка прошла идеально * из нее нужно будет взять кусок про деньги */ - private StageResult formingPaymentInstructions(Long sessionId, Collection paymentInstructionReturns) { + private StageResult formingPaymentInstructions(Long sessionId) { + List paymentInstructionAll = new ArrayList<>(); Instant now = Instant.now(); - Collection registries = selectRegistries(); - log.debug("found registries.size() = {}", registries.size()); - //группируем регистры по groupId - Map> groups = registries - .stream() - .collect(Collectors.groupingBy(Registry::getGroupId)); - log.debug("groups.size = {}", groups.size()); - List paymentInstructionDeals = new ArrayList<>(); - Map lstGroups = RegistryLiabilitiesGroup.group(registries); - for (Map.Entry> group : groups.entrySet()) { - Long groupId = group.getKey(); - Function findByCode = rgsCode -> group.getValue() + { + Collection registries = selectSecurityRegistries(); + log.debug("found registries.size() = {}", registries.size()); + //группируем регистры по groupId + Map> groups = registries .stream() - .filter(rgs -> RegistryManager.equalsByCode(rgsCode, rgs)) - .findFirst() - .orElse(null); - //интересуют обязательства и требования по деньгам - Registry cs_t = findByCode.apply(CS_T); - Registry ls_t = findByCode.apply(LS_T); - if (cs_t == null || ls_t == null) { - log.error("groupId {} cmt_t {} ls_t {} - both must be present", groupId, cs_t, ls_t); - continue; + .collect(Collectors.groupingBy(Registry::getGroupId)); + log.debug("groups.size = {}", groups.size()); + Map lstGroups = RegistryLiabilitiesGroup.group(registries); + for (Map.Entry> group : groups.entrySet()) { + Long groupId = group.getKey(); + Function findByCode = rgsCode -> group.getValue() + .stream() + .filter(rgs -> RegistryManager.equalsByCode(rgsCode, rgs)) + .findFirst() + .orElse(null); + //интересуют обязательства и требования по деньгам + Registry cs_t = findByCode.apply(CS_T); + Registry ls_t = findByCode.apply(LS_T); + if (cs_t == null || ls_t == null) { + log.error("groupId {} cmt_t {} ls_t {} - both must be present", groupId, cs_t, ls_t); + continue; + } + PaymentGroup ls_t_group = lstGroups.get(ls_t.getId()); + if (ls_t_group == null) { + log.debug("groupId {} cmt_t {} ls_t {} were included in a group, skipping", groupId, cs_t, ls_t); + continue; + } + + Optional payerAstO = rgsMng.findRelatedAsset( + ls_t.getTradingClearingRegistryId(), + ls_t.getCompanyId(), + ls_t.getSecuritySymbol(), + AS_T + ); + payerAstO.ifPresent(as_t -> { + log.debug("groupId {} cmt_t {} ls_t {} changing AS*T.id={} sender", groupId, cs_t, ls_t, as_t.getId()); + as_t.setSettledDebit(safeBD(as_t.getSettledDebit()).add(safeBD(ls_t_group.getSum()))); + setUpdatedStoreInImdg(as_t, now); + }); + Optional receiverAstO = rgsMng.findRelatedAsset( + cs_t.getTradingClearingRegistryId(), + cs_t.getCompanyId(), + cs_t.getSecuritySymbol(), + AS_T + ); + receiverAstO.ifPresent(as_t -> { + log.debug("groupId {} cmt_t {} ls_t {} changing AS*T.id={} receiver", groupId, cs_t, ls_t, as_t.getId()); + as_t.setSettledCredit(safeBD(as_t.getSettledCredit()).add(safeBD(ls_t_group.getSum()))); + setUpdatedStoreInImdg(as_t, now); + }); + + + log.trace("generating payment instruction for groupId {} cmt_t {} ls_t {}, matched ls_t total {}, total balance {}, LS*T.id={}", + groupId, + cs_t.getId(), + ls_t.getId(), + ls_t_group.getLs_tRegistries().size(), + ls_t_group.getSum(), + ls_t_group.getLs_tRegistries().stream() + .map(Registry::getId) + .map(String::valueOf) + .collect(Collectors.joining(",", "[", "]")) + ); + + PaymentInstruction pmt = PaymentInstructionBuilderForSecurities.builder(imdgProvider) + .ls_t(ls_t) + .creditLegAccountId(ls_t.getAccountId()) + .creditLegAccount(ls_t.getAccount()) + .debitLegAccountId(cs_t.getAccountId()) + .debitLegAccount(cs_t.getAccount()) + .sessionId(sessionId) + .sender(ls_t.getCompanyId()) + .addressee(cs_t.getCompanyId()) + .purpose("Перевод по итогу клиринга") + .amount(ls_t_group.getSum()) + .build(); + + paymentInstructionImdg.insert(pmt); + paymentInstructionAll.add(pmt); + log.trace("generated PaymentInstructions for groupId {}: pmtInstr.id={}", groupId, pmt.getId()); } - PaymentGroup ls_t_group = lstGroups.get(ls_t.getId()); - if (ls_t_group == null) { - log.debug("groupId {} cmt_t {} ls_t {} were included in a group, skipping", groupId, cs_t, ls_t); - continue; + } + { + Collection registries = selectMoneyRegistries(); + Account tranAcc = accountImdg.getFirstObjectBySQL("accountType = '%s' and status = '%s' and processingSign = '%s'" + .formatted(AccountType.Tran.getKey(), AccountStatus.ACTIVE.getKey(), Allowed.ALLOWED.getKey())); + Account dtrnAcc = accountImdg.getFirstObjectBySQL("accountType = '%s' and status = '%s' and processingSign = '%s'" + .formatted(AccountType.Dtrn.getKey(), AccountStatus.ACTIVE.getKey(), Allowed.ALLOWED.getKey())); + + if (tranAcc == null || dtrnAcc == null) { + return new StageResult<>( + new EnumMessage(ClearingError.AccountNotPresent, "accountType = %s/%s" + .formatted(AccountType.Tran.getKey(), AccountType.Dtrn.getKey())), + false); } - Optional payerAstO = rgsMng.findRelatedAsset( - ls_t.getTradingClearingRegistryId(), - ls_t.getCompanyId(), - ls_t.getSecuritySymbol(), - AS_T - ); - payerAstO.ifPresent(as_t -> { - log.debug("groupId {} cmt_t {} ls_t {} changing AS*T.id={} sender", groupId, cs_t, ls_t, as_t.getId()); - as_t.setSettledDebit(safeBD(as_t.getSettledDebit()).add(safeBD(ls_t_group.getSum()))); - setUpdatedStoreInImdg(as_t, now); - }); - Optional receiverAstO = rgsMng.findRelatedAsset( - cs_t.getTradingClearingRegistryId(), - cs_t.getCompanyId(), - cs_t.getSecuritySymbol(), - AS_T - ); - receiverAstO.ifPresent(as_t -> { - log.debug("groupId {} cmt_t {} ls_t {} changing AS*T.id={} receiver", groupId, cs_t, ls_t, as_t.getId()); - as_t.setSettledCredit(safeBD(as_t.getSettledCredit()).add(safeBD(ls_t_group.getSum()))); - setUpdatedStoreInImdg(as_t, now); - }); - - - log.trace("generating payment instruction for groupId {} cmt_t {} ls_t {}, matched ls_t total {}, total balance {}, LS*T.id={}", - groupId, - cs_t.getId(), - ls_t.getId(), - ls_t_group.getLs_tRegistries().size(), - ls_t_group.getSum(), - ls_t_group.getLs_tRegistries().stream() - .map(Registry::getId) - .map(String::valueOf) - .collect(Collectors.joining(",", "[", "]")) - ); - - PaymentInstruction pmt = PaymentInstructionBuilderForSecurities.builder(imdgProvider) - .ls_t(ls_t) - .creditLegAccountId(ls_t.getAccountId()) - .creditLegAccount(ls_t.getAccount()) - .debitLegAccountId(cs_t.getAccountId()) - .debitLegAccount(cs_t.getAccount()) - .sessionId(sessionId) - .sender(ls_t.getCompanyId()) - .addressee(cs_t.getCompanyId()) - .purpose("Перевод по итогу клиринга") - .amount(ls_t_group.getSum()) - .build(); - - paymentInstructionImdg.insert(pmt); - paymentInstructionDeals.add(pmt); - - log.trace("generated PaymentInstructions for groupId {}: pmtInstr.id={}", groupId, pmt.getId()); + log.debug("found AS*B.size() = {}", registries.size()); + //группируем регистры по groupId + for (Registry registry : registries) { + if (registry.getBalance().compareTo(BigDecimal.ZERO) == 0) { + log.debug("Skip creating paymentInstruction by registry with 0 balance"); + continue; + } + boolean isPositiveBalance = registry.getBalance().compareTo(BigDecimal.ZERO) > 0; + Account counterAcc = null; + if (AccountType.Clrn.equalsByKey(registry.getAccountType())) { + counterAcc = accountImdg.getSingleObjectByID(registry.getAccountId()); + } else if (AccountType.Info.equalsByKey(registry.getAccountType())) { + counterAcc = accountImdg.getFirstObjectByFieldValues(Map.of("companyId", 1L, "accountType", AccountType.Anlt.getKey())); + } + Long senderId; + Long addresseeId; + Account debitLegAccount; + Account creditLegAccount; + BigDecimal amount; + if (isPositiveBalance) { + senderId = registry.getCompanyId(); + addresseeId = Sender.One.getId(); + debitLegAccount = tranAcc; + creditLegAccount = counterAcc; + amount = registry.getBalance() == null ? null : registry.getBalance().abs(); + Optional payerAmtO = rgsMng.findRelatedAsset( + registry.getTradingClearingRegistryId(), + registry.getCompanyId(), + registry.getSecuritySymbol(), + AM_T); + payerAmtO.ifPresent(amt -> { + amt.setSettledDebit(safeBD(amt.getSettledDebit()).add(safeBD(registry.getBalance().abs()))); + setUpdatedStoreInImdg(amt, now); + }); + } else { + senderId = Sender.One.getId(); + addresseeId = registry.getCompanyId(); + debitLegAccount = counterAcc; + creditLegAccount = tranAcc; + amount = registry.getBalance() == null ? null : registry.getBalance().abs(); + Optional payerAmtO = rgsMng.findRelatedAsset( + registry.getTradingClearingRegistryId(), + registry.getCompanyId(), + registry.getSecuritySymbol(), + AM_T + ); + payerAmtO.ifPresent(amt -> { + amt.setSettledCredit(safeBD(amt.getSettledCredit()).add(safeBD(registry.getBalance().abs()))); + setUpdatedStoreInImdg(amt, now); + }); + } + PaymentInstructionBuilderV2 paymentInstructionBuilder = PaymentInstructionBuilderV2.builder(imdgProvider) + .registry(registry) + .sender(senderId) + .addressee(addresseeId) + .debitLegAccount(debitLegAccount) + .creditLegAccount(creditLegAccount) + .amount(amount) + .sessionId(sessionId) + .purpose(String.format("Перевод по итогу клиринга по ТКР %s", registry.getTradingClearingRegistry())); + PaymentInstruction paymentInstruction = paymentInstructionBuilder.build(); + log.debug("Created paymentInstruction by registry.id: {}", registry.getId()); + paymentInstructionImdg.insert(paymentInstruction); + registry.setPaymentId(paymentInstruction.getId()); + registry.setUpdated(now); + registryImdg.update(registry); + paymentInstructionAll.add(paymentInstruction); + } } - log.debug("PaymentInstructions return size {}, PaymentInstructions deals size {}. sending SDF03", - paymentInstructionReturns.size(), - paymentInstructionDeals.size()); - List returnsAndDeals = Stream.concat(paymentInstructionReturns.stream(), paymentInstructionDeals.stream()).toList(); - sendSdfs(returnsAndDeals, sessionId); + log.debug("PaymentInstruction size {}", paymentInstructionAll.size()); + sdf03And12Sender.sendSdfs(paymentInstructionAll, sessionId); StageResult> stageResult = new StageResult<>(null, true); - stageResult.setStageResult(returnsAndDeals); + stageResult.setStageResult(paymentInstructionAll); return stageResult; } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/Sdf03And12Sender.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/Sdf03And12Sender.java new file mode 100644 index 000000000..43f57545c --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/Sdf03And12Sender.java @@ -0,0 +1,104 @@ +package ru.spcex.clearing.session.stage.impl; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import ru.clearing.classes.statics.data.account.Account; +import ru.clearing.classes.statics.data.payment.PaymentInstruction; +import ru.clearing.classes.statics.data.sdf.SDf03; +import ru.clearing.classes.statics.data.sdf.SDf12; +import ru.clearing.classes.statics.data.security.Security; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.Consts; +import ru.spcex.clearing.platform.messaging.domain.cud.balance.ExportToFileRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.importexport.SwtExporterRequest; +import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; +import ru.spcex.clearing.service.RegistryManager; +import ru.spcex.clearing.service.Sdf03Creator; +import ru.spcex.clearing.service.Sdf12Creator; +import ru.spcex.platform.enumeration.AccountType; +import ru.spcex.platform.enumeration.InstrumentType; +import ru.spcex.platform.enumeration.SdfTable; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.utils.enumeration.IEnumKey; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +@Component +public class Sdf03And12Sender { + private final Logger log = LoggerFactory.getLogger(getClass()); + private final ImdgProvider imdgProvider; + private final Imdg securityImdg; + private final Imdg accountImdg; + private final Imdg sDf03Imdg; + private final Imdg sDf12Imdg; + private final KafkaSender kafkaSender; + private final Sdf03Creator sdf03Creator; + private final Sdf12Creator sdf12Creator; + + public Sdf03And12Sender(ImdgProvider imdgProvider, + KafkaSender kafkaSender, Sdf03Creator sdf03Creator, Sdf12Creator sdf12Creator, RegistryManager rgsMng) { + this.kafkaSender = kafkaSender; + this.imdgProvider = imdgProvider; + this.securityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Security, Security.class); + this.accountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class); + this.sDf03Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf03, SDf03.class); + this.sDf12Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf12, SDf12.class); + this.sdf03Creator = sdf03Creator; + this.sdf12Creator = sdf12Creator; + } + + public Collection sendSdfs(List formedPaymentInstructions, Long sessionId) { + Collection sentSdfs = new ArrayList<>(); + List sDf03Created = new ArrayList<>(); + List sDf12Created = new ArrayList<>(); + for (PaymentInstruction paymentInstruction : formedPaymentInstructions) { + Account account = accountImdg.getSingleObjectByID(paymentInstruction.getCreditLeg_accountId()); + Security security = securityImdg.getSingleObjectByID(paymentInstruction.getCreditLeg_securityId()); + if (List.of(AccountType.Corr, AccountType.Clrn, AccountType.Tran, AccountType.Anlt, AccountType.Info) + .contains(IEnumKey.getEnumByKey(AccountType.class, account.getAccountType()))) { + sDf03Created.add(sdf03Creator.create(paymentInstruction)); + } else if (!InstrumentType.CRNC.equalsByKey(security.getInstrumentType()) && + List.of(AccountType.Depo, AccountType.Dtrn).contains(IEnumKey.getEnumByKey(AccountType.class, account.getAccountType()))) { + sDf12Created.add(sdf12Creator.createWithoutIntermediate(paymentInstruction)); + } + } + + Long sdf03GroupId = !sDf03Created.isEmpty() ? imdgProvider.getImdgIdGenerator().nextId() : null; + for (SDf03 sDf03 : sDf03Created) { + sDf03.setGenerationId(sdf03GroupId); + sDf03Imdg.insert(sDf03); + } + + if (sdf03GroupId != null) { + ExportToFileRequest exportToFileRequest = new ExportToFileRequest(); + exportToFileRequest.setNameOfTable("DF-03"); + exportToFileRequest.setSdfGroupId(sdf03GroupId); + kafkaSender.sendRequestToQueue(Consts.EXPORT_PROCESS, exportToFileRequest); + } + + Long sdf12GroupId = null; + if (!sDf12Created.isEmpty()) { + sdf12GroupId = imdgProvider.getImdgIdGenerator().nextId(); + Long maxTxNumber = sdf12Creator.maxTxNumber(); + for (SDf12 sDf12 : sDf12Created) { + sDf12.setGenerationId(sdf12GroupId); + sDf12.setTransactionNumber(maxTxNumber.toString()); + sDf12.setTransactionQuantity(String.valueOf(sDf12Created.size())); + sDf12Imdg.insert(sDf12); + } + SwtExporterRequest swtExporterRequest = new SwtExporterRequest(); + swtExporterRequest.setType("SDF_12"); + swtExporterRequest.setGroupId(sdf12GroupId); + swtExporterRequest.setSessionId(sessionId); + kafkaSender.sendRequestToQueue(Consts.SWT_EXPORTER, swtExporterRequest); + } + + if (sdf03GroupId != null) sentSdfs.add(SdfTable.SDF_03); + if (sdf12GroupId != null) sentSdfs.add(SdfTable.SDF_12); + return sentSdfs; + } +}