From 86469d6ff74089d9915bbc819efff966a7a7615a Mon Sep 17 00:00:00 2001 From: ialbert Date: Mon, 10 Jul 2023 15:30:13 +0300 Subject: [PATCH] =?UTF-8?q?=D0=92=20=D1=84=D0=B8=D0=BD=D0=B0=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D0=BE=D0=B9=20=D0=9C=D0=9A=D0=A0=20=D1=87=D0=B0=D1=81?= =?UTF-8?q?=D1=82=D1=8C=20=D0=BF=D1=80=D0=BE=20=D0=B2=D0=BE=D0=B7=D0=B2?= =?UTF-8?q?=D1=80=D0=B0=D1=82=20=D0=B4=D0=B5=D0=BF=D0=BE=D0=B7=D0=B8=D1=82?= =?UTF-8?q?=D0=BE=D0=B2=20=D1=81=D0=BA=D0=BE=D0=BF=D0=B8=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D0=BD=D0=BD=D0=B0=20=D0=B8=D0=B7=20=D1=81=D0=B5=D1=81?= =?UTF-8?q?=D1=81=D0=B8=20=D0=BF=D0=BE=20=D0=B2=D0=BE=D0=B7=D0=B2=D1=80?= =?UTF-8?q?=D0=B0=D1=82=D0=B0=D0=BC=20=D0=B4=D0=B5=D0=BF=D0=BE=D0=B7=D0=B8?= =?UTF-8?q?=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ormingPaymentInstructionDepositReturn.java | 11 +- .../FormingPaymentInstructionReturnMkr.java | 195 ++++++++++-------- .../specific/RegistryDm_tClrnPredicate.java | 25 +++ 3 files changed, 137 insertions(+), 94 deletions(-) create mode 100644 platform-parent/platform-imdg-api/src/main/java/ru/spcex/platform/imdg/api/predicate/specific/RegistryDm_tClrnPredicate.java diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionDepositReturn.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionDepositReturn.java index 772634dcb..a70718bf5 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionDepositReturn.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionDepositReturn.java @@ -33,6 +33,7 @@ import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; import ru.spcex.platform.imdg.api.predicate.specific.RegistryAssetPredicate; import ru.spcex.platform.imdg.api.predicate.specific.RegistryCodeSqlBuilder; +import ru.spcex.platform.imdg.api.predicate.specific.RegistryDm_tClrnPredicate; import ru.spcex.platform.utils.collection.Pair; import ru.spcex.platform.utils.enumeration.EnumMessage; import ru.spcex.platform.utils.enumeration.IEnumKey; @@ -300,12 +301,10 @@ public class FormingPaymentInstructionDepositReturn implements ISessionStage { * Если УК зачисляет средства на свой ТБС */ private Optional searchDmtClrn(Registry rgs) { - String sqlCondition = String.format("(%s) and accountType='%s' and companyId = %d and counterPartyId = %d", - RegistryCodeSqlBuilder.getInstance(DM_T).build(), - AccountType.Clrn.getKey(), - rgs.getCompanyId(), - rgs.getCounterPartyId()); - Registry dmt = registryImdg.getSingleObjectBySQL(sqlCondition); + ImdgPredicate dmtClrnPrdct = RegistryDm_tClrnPredicate + .instance(rgs.getCompanyId(), rgs.getCounterPartyId()) + .apply(registryImdg); + Registry dmt = registryImdg.getSingleObjectByPredicate(dmtClrnPrdct); return Optional.ofNullable(dmt); } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionReturnMkr.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionReturnMkr.java index 110fbf216..9afa16770 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionReturnMkr.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionReturnMkr.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; @@ -20,6 +21,7 @@ import ru.spcex.clearing.platform.messaging.domain.cud.importexport.SwtExporterR import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; import ru.spcex.clearing.service.SpecifUtil; import ru.spcex.clearing.service.builder.PaymentInstructionBuilder; +import ru.spcex.clearing.service.builder.PaymentInstructionBuilderFinalMkrDeals; import ru.spcex.clearing.session.stage.ISessionStage; import ru.spcex.clearing.session.stage.StageResult; import ru.spcex.clearing.session.stage.Task; @@ -30,7 +32,11 @@ 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.RegistryAssetPredicate; import ru.spcex.platform.imdg.api.predicate.specific.RegistryCodeSqlBuilder; +import ru.spcex.platform.imdg.api.predicate.specific.RegistryDm_tClrnPredicate; +import ru.spcex.platform.utils.collection.Pair; +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.time.TimeUtil; @@ -39,6 +45,7 @@ import java.math.BigDecimal; import java.time.Instant; import java.time.format.DateTimeFormatter; import java.util.*; +import java.util.stream.Collectors; import static ru.spcex.platform.enumeration.RegistryTradingParams.*; @@ -99,35 +106,9 @@ public class FormingPaymentInstructionReturnMkr implements ISessionStage { .toList(); log.debug("LM*T and CM*T size = {}", rgsAll.size()); -// List obligationsByMoney = rgsAll.stream() -// .filter(registry -> equalsByRegistry(LM_T, registry)) -// .toList(); -// -// log.debug("changing assets by LM*T"); - //изменяем активы по обязательствам по деньгам (LM_T) -// for (Registry obligationByMoney : obligationsByMoney) { -// String sql = String.format("tradingClearingRegistryId = %s and companyId = %s", -// obligationByMoney.getTradingClearingRegistryId(), obligationByMoney.getCompanyId()); -// Collection relatedRegistries = registryImdg.getCollectionObjectsBySQL(sql); -// log.trace("found {} related registries (by tcrId&companyId) for LM*T.id={}", -// relatedRegistries.size(), -// obligationByMoney.getId()); -// -// for (Registry relatedRegistry : relatedRegistries) { -// if (equalsByRegistry(AM_F, relatedRegistry)) { -// relatedRegistry.setBalance(safeBD(relatedRegistry.getBalance()).subtract(safeBD(obligationByMoney.getBalance()))); -// } else if (equalsByRegistry(AM_T, relatedRegistry)) { -// relatedRegistry.setSettledDebit(safeBD(relatedRegistry.getSettledDebit()).add(safeBD(obligationByMoney.getBalance()))); -// } else if (equalsByRegistry(AM_B, relatedRegistry)) { -// relatedRegistry.setBalance(safeBD(relatedRegistry.getBalance()).add(safeBD(obligationByMoney.getBalance()))); -// } -// log.trace("updated related registry.id={} for LM*T.id={}", relatedRegistry.getId(), obligationByMoney.getId()); -// registryImdg.update(relatedRegistry); -// } -// } log.debug("changing assets by CM*T"); List requirementsByMoney = rgsAll.stream() - .filter(registry -> equalsByRegistry(CM_T, registry)) + .filter(registry -> equalByRgs(CM_T, registry)) .toList(); //изменяем активы по требованиям по деньгам CM_T for (Registry requirementByMoney : requirementsByMoney) { @@ -136,7 +117,7 @@ public class FormingPaymentInstructionReturnMkr implements ISessionStage { Collection relatedRegistries = registryImdg.getCollectionObjectsBySQL(sql); log.trace("found {} related registries (by tcrId&companyId) for CM*T.id={}", relatedRegistries.size(), requirementByMoney.getId()); for (Registry relatedRegistry : relatedRegistries) { - if (equalsByRegistry(AM_T, relatedRegistry)) { + if (equalByRgs(AM_T, relatedRegistry)) { relatedRegistry.setSettledDebit(safeBD(relatedRegistry.getSettledDebit()).add(safeBD(requirementByMoney.getBalance()))); log.trace("updated related registry.id={} for CM*T.id={}", relatedRegistry.getId(), requirementByMoney.getId()); registryImdg.update(relatedRegistry); @@ -144,69 +125,87 @@ public class FormingPaymentInstructionReturnMkr implements ISessionStage { } } - List formedPaymentInstructions = new ArrayList<>(); + List pmtCreated = new ArrayList<>(); - List allLiabilities = rgsAll - .stream() - .filter(registry -> RegistryDesignation.L.equalsByKey(registry.getRegistryDesignation())) - .filter(obligation -> { - //если valueDate < settlement date - if (!(obligation.getValueDate() != null - && obligation.getSettlementDate() != null - && obligation.getValueDate().isBefore(obligation.getSettlementDate()))) { - return false; - } - Optional dmx = searchDmx(obligation); - if (dmx.isPresent()) { - log.debug("LM*T#id={}, DM*X#id={} found, no action needed for group {}, skipping liability", - obligation.getId(), - obligation.getId(), - obligation.getGroupId()); - } - return dmx.isEmpty(); - }) - .toList(); - for (int i = 0; i < allLiabilities.size(); i++) { - //сортировка чтобы найти сделки с одинаковыми направлениями и адресатами и схлопнуть в одну - Registry lm_t = allLiabilities.get(i); - if (lm_t == null) continue; - LinkedList relatedRegistries = new LinkedList<>(); - relatedRegistries.add(lm_t); - for (int j = i + 1; j < allLiabilities.size(); j++) { - Registry related = allLiabilities.get(j); - if (related == null) continue; - if (registriesOfTheSameAgents(lm_t, related)) { - relatedRegistries.add(related); - allLiabilities.set(j, null); - } + Map> registriesByGroup = rgsAll + .stream(). + collect(Collectors.groupingBy(Registry::getGroupId)); + log.info("registry groups found {}", registriesByGroup.size()); + for (Map.Entry> entry : registriesByGroup.entrySet()) { + List groupRgs = entry.getValue(); + Optional lmtO = groupRgs.stream().filter(rgs -> equalByRgs(LM_T, rgs)).findFirst(); + Optional cmtO = groupRgs.stream().filter(rgs -> equalByRgs(CM_T, rgs)).findFirst(); + if (lmtO.isEmpty() || cmtO.isEmpty()) { + log.error("LM*T or CM*T not found for group {}", entry.getKey()); + continue; + } + Registry lm_t = lmtO.get(); //obligation by money + Registry cm_t = cmtO.get(); + Optional dmx = searchDmx(lm_t); + if (dmx.isPresent()) { + log.debug("LM*T#id={}, DM*X#id={} found, no action needed for group {}, skipping liability", + lm_t.getId(), dmx.get().getId(), lm_t.getGroupId()); + continue; + } + Optional dmtClnr = searchDmtClrn(lm_t); + if (dmtClnr.isPresent()) { + Account tranAcc = accountImdg.getSingleObjectBySQL("accountType = '%s' and status = '%s' and processingSign = '%s'" + .formatted(AccountType.Tran.getKey(), AccountStatus.ACTIVE.getKey(), Allowed.ALLOWED.getKey())); + if (tranAcc == null) { + return new StageResult<>( + new EnumMessage(ClearingError.AccountNotPresent, "accountType = " + AccountType.Tran.getKey()), + false); + } + { + //изменение активов - блокируем средства беред отправкой sdf'ов + Optional amfO = findRelatedAsset(lm_t.getTradingClearingRegistryId(), lm_t.getCompanyId(), AM_F); + Optional payerAmtO = findRelatedAsset(lm_t.getTradingClearingRegistryId(), lm_t.getCompanyId(), AM_T); + Optional ambO = findRelatedAsset(lm_t.getTradingClearingRegistryId(), lm_t.getCompanyId(), AM_B); + Optional receiverAmtO = findRelatedAsset(cm_t.getTradingClearingRegistryId(), cm_t.getCompanyId(), AM_B); + log.debug("changing A* registers based on LM_T.id={} and CM_T.id={} found AM*F.id={}, AM*T.id={}, AM*B.id={}, AM*B.id={}", + lm_t.getId(), + cm_t.getId(), + amfO.map(Registry::getId).orElse(null), + payerAmtO.map(Registry::getId).orElse(null), + ambO.map(Registry::getId).orElse(null), + receiverAmtO.map(Registry::getId).orElse(null) + ); + Instant now = Instant.now(); + amfO.ifPresent(amf -> { + amf.setBalance(safeBD(amf.getBalance()).subtract(safeBD(lm_t.getBalance()))); + setUpdatedStoreInImdg(amf, now); + }); + payerAmtO.ifPresent(amt -> { + amt.setSettledDebit(safeBD(amt.getSettledDebit()).add(safeBD(lm_t.getBalance()))); + setUpdatedStoreInImdg(amt, now); + }); + ambO.ifPresent(amb -> { + amb.setBalance(safeBD(amb.getBalance()).add(safeBD(lm_t.getBalance()))); + setUpdatedStoreInImdg(amb, now); + }); + receiverAmtO.ifPresent(amt -> { + // у отправителя и получателя одинаково, см. в FormingPaymentInstruction + amt.setSettledDebit(safeBD(amt.getSettledDebit()).add(safeBD(lm_t.getBalance()))); + setUpdatedStoreInImdg(amt, now); + }); + } + Pair pmts = PaymentInstructionBuilderFinalMkrDeals.builder(imdgProvider) + .lm_t(lm_t) + .cm_t(cm_t) + .tranAcc(tranAcc) + .sessionId(sessionId) + .paymentPurpose("Возврат депозита " + cm_t.getContract() + " по ТКР " + cm_t.getTradingClearingRegistry()) + .build(); + paymentInstructionImdg.insert(pmts.getFirst()); + paymentInstructionImdg.insert(pmts.getSecond()); + log.debug("LM*T#id={}, CM*T#id={} found, PaymentInstruction id={} and id={} created", + lm_t.getId(), cm_t.getId(), pmts.getFirst().getId(), pmts.getSecond().getId()); + pmtCreated.add(pmts.getFirst()); + pmtCreated.add(pmts.getSecond()); } - log.trace("LM*T.id={} return group size {}", lm_t.getId(), relatedRegistries.size()); - BigDecimal sumBalance = relatedRegistries.stream().map(Registry::getBalance).reduce(BigDecimal.ZERO, BigDecimal::add); - log.trace("LM*T.id={} sumBalance={}", lm_t.getId(), sumBalance); - List builderList = new ArrayList<>(); - builderList.add(lm_t); - rgsAll.stream() - .filter(rgs -> rgs.getGroupId().equals(lm_t.getGroupId())) - .filter(rgs -> RegistryDesignation.C.equalsByKey(rgs.getRegistryDesignation())) - .findFirst() - .ifPresent(builderList::add); - - PaymentInstruction paymentInstruction = createPaymentInstruction(builderList, sumBalance, sessionId); - formedPaymentInstructions.add(paymentInstruction); - paymentInstructionImdg.insert(paymentInstruction); - log.trace("LM*T.id={} created paymentInstruction.id={}", lm_t.getId(), paymentInstruction.getId()); - builderList.forEach(registry -> { - registry.setPaymentId(paymentInstruction.getId()); - registry.setUpdated(Instant.now()); - registryImdg.update(registry); - }); } - - //sdf отправляют - //sendSdfs(formedPaymentInstructions); - StageResult> stageResult = new StageResult(null, true); - stageResult.setStageResult(formedPaymentInstructions); + stageResult.setStageResult(pmtCreated); return stageResult; } @@ -221,6 +220,26 @@ public class FormingPaymentInstructionReturnMkr implements ISessionStage { return Optional.ofNullable(dmx); } + private Optional searchDmtClrn(Registry rgs) { + ImdgPredicate dmtClrnPrdct = RegistryDm_tClrnPredicate + .instance(rgs.getCompanyId(), rgs.getCounterPartyId()) + .apply(registryImdg); + Registry dmt = registryImdg.getSingleObjectByPredicate(dmtClrnPrdct); + return Optional.ofNullable(dmt); + } + + private Optional findRelatedAsset(Long tradingClearingRegistryId, Long companyId, RegistryTradingParams rgsCode) { + ImdgPredicate prdct = RegistryAssetPredicate + .instance(tradingClearingRegistryId, companyId, rgsCode) + .apply(registryImdg); + return Optional.ofNullable(registryImdg.getSingleObjectByPredicate(prdct)); + } + + private void setUpdatedStoreInImdg(Registry rgs, Instant now) { + rgs.setUpdated(now); + registryImdg.update(rgs); + } + private void sendSdfs(List formedPaymentInstructions) { List sDf03Created = new ArrayList<>(); List sDf12Created = new ArrayList<>(); @@ -370,7 +389,7 @@ public class FormingPaymentInstructionReturnMkr implements ISessionStage { && Objects.equals(rgs1.getCounterPartyId(), rgs2.getCounterPartyId()); } - private static boolean equalsByRegistry(RegistryTradingParams code, Registry rgs) { + private static boolean equalByRgs(RegistryTradingParams code, Registry rgs) { return code.equalByRegistry( IEnumKey.getEnumByKey(RegistryDesignation.class, rgs.getRegistryDesignation()), IEnumKey.getEnumByKey(RegistryInstrumentType.class, rgs.getRegistryInstrumentType()), diff --git a/platform-parent/platform-imdg-api/src/main/java/ru/spcex/platform/imdg/api/predicate/specific/RegistryDm_tClrnPredicate.java b/platform-parent/platform-imdg-api/src/main/java/ru/spcex/platform/imdg/api/predicate/specific/RegistryDm_tClrnPredicate.java new file mode 100644 index 000000000..10f3245a4 --- /dev/null +++ b/platform-parent/platform-imdg-api/src/main/java/ru/spcex/platform/imdg/api/predicate/specific/RegistryDm_tClrnPredicate.java @@ -0,0 +1,25 @@ +package ru.spcex.platform.imdg.api.predicate.specific; + +import ru.spcex.platform.enumeration.AccountType; +import ru.spcex.platform.enumeration.RegistryTradingParams; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; + +import java.util.function.Function; + +public record RegistryDm_tClrnPredicate(Long companyId, Long counterPartyId) implements Function, ImdgPredicate> { + + public static RegistryDm_tClrnPredicate instance(Long companyId, Long counterPartyId) { + return new RegistryDm_tClrnPredicate(companyId, counterPartyId); + } + + @Override + public ImdgPredicate apply(Imdg registryImdg) { + String sqlCondition = String.format("(%s) and accountType='%s' and companyId = %d and counterPartyId = %d", + RegistryCodeSqlBuilder.getInstance(RegistryTradingParams.DM_T).build(), + AccountType.Clrn.getKey(), + companyId, + counterPartyId); + return registryImdg.predicateBuilder().sql(sqlCondition); + } +}