diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Sdf03Creator.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Sdf03Creator.java index fbc204f03..84fd81ed9 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Sdf03Creator.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Sdf03Creator.java @@ -38,20 +38,25 @@ public class Sdf03Creator { } public SDf03 create(PaymentInstruction paymentInstruction) { - Account account = accountImdg.getSingleObjectByID(paymentInstruction.getCreditLeg_accountId()); - AccountType accType = IEnumKey.getEnumByKey(AccountType.class, account.getAccountType()); - String c_acc_deb; - if (AccountType.Info.equals(accType)) { + AccountType creditAccType = getAccountType(paymentInstruction.getCreditLeg_accountId()); + AccountType debAccType = getAccountType(paymentInstruction.getDebitLeg_accountId()); + String c_acc_deb = null; + String c_acc_cred = null; + if (AccountType.Info.equals(creditAccType) ^ AccountType.Info.equals(debAccType)) { Account anltAcc = accountImdg.getSingleObjectBySQL("accountType = '%s' and status = '%s'" .formatted(AccountType.Anlt.getKey(), Status.Active.getKey())); if (anltAcc == null) { throw new IllegalStateException("SDF03 creation error: paymentInstruction.creditLeg_accountId=" + paymentInstruction.getCreditLeg_accountId() + " accountType 'Info' but no 'ANLT' account found"); } - c_acc_deb = anltAcc.getAccount(); - } else { - c_acc_deb = paymentInstruction.getCreditLeg_account(); + if (AccountType.Info.equals(creditAccType)) { + c_acc_deb = anltAcc.getAccount(); + } else { + c_acc_cred = anltAcc.getAccount(); + } } + c_acc_deb = c_acc_deb == null ? paymentInstruction.getCreditLeg_account() : c_acc_deb; + c_acc_cred = c_acc_cred == null ? paymentInstruction.getDebitLeg_account() : c_acc_cred; SDf03 sDf03 = new SDf03(); @@ -79,7 +84,7 @@ public class Sdf03Creator { sDf03::setSbanknam4, sDf03::setSbanknam5); - sDf03.setC_acc_cred(paymentInstruction.getDebitLeg_account()); + sDf03.setC_acc_cred(c_acc_cred); String addresseeSbankName = ""; if (paymentInstruction.getAddresseeId().equals(1L)) { @@ -109,4 +114,8 @@ public class Sdf03Creator { return sDf03; } + private AccountType getAccountType(Long accountId) { + Account account = accountImdg.getSingleObjectByID(accountId); + return IEnumKey.getEnumByKey(AccountType.class, account.getAccountType()); + } } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionDealsFinalMkr.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionDealsFinalMkr.java index 6e2bf38e5..37084a3ee 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionDealsFinalMkr.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionDealsFinalMkr.java @@ -30,6 +30,7 @@ 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.utils.collection.Pair; import ru.spcex.platform.utils.enumeration.EnumMessage; @@ -222,14 +223,10 @@ public class FormingPaymentInstructionDealsFinalMkr implements ISessionStage { } private Optional findRelatedAsset(Long tradingClearingRegistryId, Long companyId, RegistryTradingParams rgsCode) { - ImdgPredicateBuilder rgsPrdBldr = registryImdg.predicateBuilder(); - RegistryCodeSqlBuilder codeSql = RegistryCodeSqlBuilder.getInstance(rgsCode); - ImdgPredicate assetCondition = rgsPrdBldr.and( - rgsPrdBldr.equals("tradingClearingRegistryId", tradingClearingRegistryId), - rgsPrdBldr.equals("companyId", companyId), - rgsPrdBldr.sql(codeSql.build()) - ); - return Optional.ofNullable(registryImdg.getSingleObjectByPredicate(assetCondition)); + ImdgPredicate prdct = RegistryAssetPredicate + .instance(tradingClearingRegistryId, companyId, rgsCode) + .apply(registryImdg); + return Optional.ofNullable(registryImdg.getSingleObjectByPredicate(prdct)); } private void sendSdfs(List formedPaymentInstructions) { 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 9fa846bdf..772634dcb 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 @@ -30,6 +30,8 @@ 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.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.utils.collection.Pair; import ru.spcex.platform.utils.enumeration.EnumMessage; @@ -42,6 +44,8 @@ import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; +import static ru.spcex.platform.enumeration.RegistryTradingParams.AM_B; +import static ru.spcex.platform.enumeration.RegistryTradingParams.AM_T; import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD; @Service @@ -161,8 +165,12 @@ public class FormingPaymentInstructionDepositReturn implements ISessionStage { RegistryCodeSqlBuilder registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(LM_T,CM_T, LS_T, CS_T); String registryCodeCondition = registryCodeSqlBuilder.build(); - Collection obligations = registryImdg.getCollectionObjectsBySQL(registryCodeCondition); - List obligationsByMoney = obligations.stream().filter(registry -> equalByRgs(LM_T, registry)).toList(); + Collection obligations = registryImdg.getCollectionObjectsBySQL(registryCodeCondition) + .stream() + .filter(rgs -> rgs.getValueDate() != null) + .filter(rgs -> rgs.getSettlementDate() != null) + .filter(rgs -> rgs.getSettlementDate().isAfter(rgs.getValueDate())) + .toList(); Map> registriesByGroup = obligations .stream(). @@ -178,26 +186,26 @@ public class FormingPaymentInstructionDepositReturn implements ISessionStage { log.error("LM*T or CM*T not found for group {}", entry.getKey()); continue; } - Registry lmt = lmtO.get(); //obligation by money - Registry cmt = cmtO.get(); - Optional dmx = searchDmx(lmt); + 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", - lmt.getId(), dmx.get().getId(), lmt.getGroupId()); + lm_t.getId(), dmx.get().getId(), lm_t.getGroupId()); continue; } - Optional dmtInfo = searchDmtInfo(lmt); + Optional dmtInfo = searchDmtInfo(lm_t); if (dmtInfo.isPresent()) { - BigDecimal balance = safeBD(lmt.getBalance()).add(safeBD(cmt.getBalance())); //fixme???? - PaymentInstruction payInstr = createPaymentInstruction(List.of(lmt, cmt), balance, sessionId); - lmt.setPaymentId(payInstr.getId()); - lmt.setUpdated(Instant.now()); - registryImdg.update(lmt); + BigDecimal balance = safeBD(lm_t.getBalance()).add(safeBD(cm_t.getBalance())); //fixme???? + PaymentInstruction payInstr = createPaymentInstruction(List.of(lm_t, cm_t), balance, sessionId); + lm_t.setPaymentId(payInstr.getId()); + lm_t.setUpdated(Instant.now()); + registryImdg.update(lm_t); continue; } - Optional dmtClnr = searchDmtClrn(lmt); + 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())); @@ -206,24 +214,56 @@ public class FormingPaymentInstructionDepositReturn implements ISessionStage { 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(lmt) - .cm_t(cmt) + .lm_t(lm_t) + .cm_t(cm_t) .tranAcc(tranAcc) .sessionId(sessionId) - .paymentPurpose("Размещение депозита " + lmt.getContract() + " по ТКР " + lmt.getTradingClearingRegistry()) + .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", - lmt.getId(), cmt.getId(), pmts.getFirst().getId(), pmts.getSecond().getId()); + lm_t.getId(), cm_t.getId(), pmts.getFirst().getId(), pmts.getSecond().getId()); pmtCreated.add(pmts.getFirst()); pmtCreated.add(pmts.getSecond()); } } sendSdfs(pmtCreated); - //todo fill result StageResult> stageResult = new StageResult(null, true); stageResult.setStageResult(pmtCreated); return stageResult; @@ -269,6 +309,18 @@ public class FormingPaymentInstructionDepositReturn implements ISessionStage { 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) { diff --git a/platform-parent/platform-imdg-api/src/main/java/ru/spcex/platform/imdg/api/predicate/specific/RegistryAssetPredicate.java b/platform-parent/platform-imdg-api/src/main/java/ru/spcex/platform/imdg/api/predicate/specific/RegistryAssetPredicate.java new file mode 100644 index 000000000..232dda0df --- /dev/null +++ b/platform-parent/platform-imdg-api/src/main/java/ru/spcex/platform/imdg/api/predicate/specific/RegistryAssetPredicate.java @@ -0,0 +1,27 @@ +package ru.spcex.platform.imdg.api.predicate.specific; + +import ru.spcex.platform.enumeration.RegistryTradingParams; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; + +import java.util.function.Function; + +public record RegistryAssetPredicate(Long tcrId, Long companyId, RegistryTradingParams rgsCode) implements Function, ImdgPredicate> { + + public static RegistryAssetPredicate instance(Long tcrId, Long companyId, RegistryTradingParams rgsCode) { + return new RegistryAssetPredicate(tcrId, companyId, rgsCode); + } + + @Override + public ImdgPredicate apply(Imdg registryImdg) { + registryImdg.predicateBuilder(); + ImdgPredicateBuilder rgsPrdBldr = registryImdg.predicateBuilder(); + RegistryCodeSqlBuilder codeSql = RegistryCodeSqlBuilder.getInstance(rgsCode); + return rgsPrdBldr.and( + rgsPrdBldr.equals("tradingClearingRegistryId", tcrId), + rgsPrdBldr.equals("companyId", companyId), + rgsPrdBldr.sql(codeSql.build()) + ); + } +}