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 c5b7fbd9d..72ccf83f2 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 @@ - + @@ -1150,8 +1150,8 @@ - - + + @@ -1171,7 +1171,7 @@ - + diff --git a/clearing-parent/classes/src/main/java/ru/clearing/classes/statics/data/liabilities/LiabilitiesClaimsMoney.java b/clearing-parent/classes/src/main/java/ru/clearing/classes/statics/data/liabilities/LiabilitiesClaimsMoney.java index 0b45b316e..4f78f41c7 100644 --- a/clearing-parent/classes/src/main/java/ru/clearing/classes/statics/data/liabilities/LiabilitiesClaimsMoney.java +++ b/clearing-parent/classes/src/main/java/ru/clearing/classes/statics/data/liabilities/LiabilitiesClaimsMoney.java @@ -125,4 +125,23 @@ public class LiabilitiesClaimsMoney extends BusinessObject { public void setClearingDate(LocalDate clearingDate) { this.clearingDate = clearingDate; } + + @Override + public String toString() { + return "LiabilitiesClaimsMoney{" + + "companyId=" + companyId + + ", accountId=" + accountId + + ", accountType='" + accountType + '\'' + + ", account='" + account + '\'' + + ", liabilitiesAmount=" + liabilitiesAmount + + ", claimsAmount=" + claimsAmount + + ", settlementDate=" + settlementDate + + ", tradingDate=" + tradingDate + + ", currency='" + currency + '\'' + + ", tradingCode='" + tradingCode + '\'' + + ", shortName='" + shortName + '\'' + + ", fullName='" + fullName + '\'' + + ", clearingDate=" + clearingDate + + '}'; + } } \ No newline at end of file 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 6dff5866e..23d5d81a9 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 @@ -208,6 +208,7 @@ public class Clearing { wrapperFirstLegCreated.firstLegCreated = lcmFirstLeg; }); Optional lcmSecondLegFound = lbltsClmsMoneyCreator.searchLcmByRefundDate(lca.getAccountId(), lca.getCompanyId(), lca.getRefundDate()); + var wrapperSecondLegCreated = new Object() {LiabilitiesClaimsMoney secondLegCreated;}; lcmSecondLegFound.ifPresentOrElse(lcm -> { log.trace("LiabilitiesClaimsMoney second leg {} was found", lcm.getId()); lbltsClmsMoneyCreator.updateSecondLegLcm(lcm, lca, category); @@ -216,6 +217,7 @@ public class Clearing { LiabilitiesClaimsMoney lcmSecondLeg = lbltsClmsMoneyCreator.createSecondLegLcm(lca, category); liabilitiesClaimsMoneyImdg.insert(lcmSecondLeg); log.trace("LiabilitiesClaimsMoney second leg {} was created", lcmSecondLeg.getId()); + wrapperSecondLegCreated.secondLegCreated = lcmSecondLeg; }); lbltsClmsAssetsCreator.updateLca(lca, lcmFirstLegFound.orElse(wrapperFirstLegCreated.firstLegCreated)); liabilitiesClaimsAssetsImdg.update(lca); @@ -225,10 +227,15 @@ public class Clearing { paymentInstructionCreator.updateFieldLiabilitiesClaimsAssetsByPayment(lca, paymentInstructions, Collections.singleton(category)); liabilitiesClaimsAssetsImdg.update(lca); var firstLegLiabilitiesClaimsMoney = lcmFirstLegFound.orElseGet(() -> wrapperFirstLegCreated.firstLegCreated); + var secondLegLiabilitiesClaimsMoney = lcmSecondLegFound.orElseGet(() -> wrapperSecondLegCreated.secondLegCreated); log.trace("updating LiabilitiesClaimsMoney by payment"); - paymentInstructionCreator.updateFieldLiabilitiesClaimsMoneyByPayment(firstLegLiabilitiesClaimsMoney, paymentInstructions, Collections.singleton(category)); + log.trace("firstLegLiabilitiesClaimsMoney: {}; secondLegLiabilitiesClaimsMoney: {}", firstLegLiabilitiesClaimsMoney, secondLegLiabilitiesClaimsMoney); + paymentInstructionCreator.updateFieldLiabilitiesClaimsMoneyByPayment(firstLegLiabilitiesClaimsMoney, true, paymentInstructions, Collections.singleton(category)); liabilitiesClaimsMoneyImdg.update(firstLegLiabilitiesClaimsMoney); - log.trace("LiabilitiesClaimsMoney first leg {} was updated", firstLegLiabilitiesClaimsMoney.getId()); + paymentInstructionCreator.updateFieldLiabilitiesClaimsMoneyByPayment(secondLegLiabilitiesClaimsMoney, false, paymentInstructions, Collections.singleton(category)); + liabilitiesClaimsMoneyImdg.update(secondLegLiabilitiesClaimsMoney); + log.trace("LiabilitiesClaimsMoney first leg {}, second leg {} was updated", firstLegLiabilitiesClaimsMoney.getId(), secondLegLiabilitiesClaimsMoney.getId()); + log.trace("firstLegLiabilitiesClaimsMoney: {}; secondLegLiabilitiesClaimsMoney: {}", firstLegLiabilitiesClaimsMoney, secondLegLiabilitiesClaimsMoney); execDeposit.setSessionId(clearingSessionId); execDeposit.setUpdated(Instant.now()); executionDepositImdg.update(execDeposit); 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 4e75f188b..25b5cafea 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 @@ -7,6 +7,7 @@ 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.execution.ExecutionDeposit; import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsAssets; import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsMoney; import ru.clearing.classes.statics.data.payment.PaymentInstruction; @@ -28,6 +29,8 @@ import java.util.*; import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Collectors; +import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD; + /* todo использовать так: paymentInstructionCreator.createAndSavePaymentInstructions() @@ -50,6 +53,7 @@ public class PaymentInstructionCreator { protected final Imdg accountImdg; protected final Imdg paymentInstructionImdg; protected final Imdg liabilitiesClaimsMoneyImdg; + protected final Imdg executionDepositImdg; protected AtomicLong documentNumberId = new AtomicLong(0L); // порядковый номер (сквозной по всем компаниям за день protected LocalDate documentNumberResetAt; @@ -62,11 +66,13 @@ public class PaymentInstructionCreator { 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.executionDepositImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionDeposit, ExecutionDeposit.class); this.idGenerator = imdgProvider.getImdgIdGenerator(); } /** * 2.2.2. Выполнить Создание paymentInstruction по liabilitiesClaimsAssets + * * @return Созданные PaymentInstruction, может быть несколько. Они уже сохранены в IMDG. */ public List createAndSavePaymentInstructions(LiabilitiesClaimsAssets liabilitiesClaimsAssets, @@ -109,13 +115,13 @@ public class PaymentInstructionCreator { payment2.setSenderId(SPVB_ID); // СПВБ payment1.setAddresseeId(SPVB_ID); // СПВБ - String sqlLCA = String.format("securityId = %s and companyId <> %s", + 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); + ExecutionDeposit counterExecutionDeposit = executionDepositImdg.getSingleObjectBySQL(sqlLCA); + if (counterExecutionDeposit == null) { + log.warn("Counter ExecutionDeposit not found for : {}", sqlLCA); } else { - payment2.setAddresseeId(counterLiabilitiesClaimsAssets.getCompanyId()); + payment2.setAddresseeId(counterExecutionDeposit.getCompanyId()); } String symbol1 = selectSymbolValue(payment1.getAddresseeId(), CompanySymbol.BIC); @@ -233,13 +239,13 @@ public class PaymentInstructionCreator { payment1.setSenderId(SPVB_ID); // СПВБ - String sqlLCA = String.format("securityId = %s and companyId <> %s", + 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); + ExecutionDeposit counterExecutionDeposit = executionDepositImdg.getSingleObjectBySQL(sqlLCA); + if (counterExecutionDeposit == null) { + log.warn("Counter ExecutionDeposit not found for : {}", sqlLCA); } else { - payment1.setAddresseeId(counterLiabilitiesClaimsAssets.getCompanyId()); + payment1.setAddresseeId(counterExecutionDeposit.getCompanyId()); } String symbol1 = selectSymbolValue(payment1.getAddresseeId(), CompanySymbol.BIC); @@ -414,6 +420,9 @@ public class PaymentInstructionCreator { } protected String selectSymbolValue(Long companyId, CompanySymbol symbol) { + if (companyId == null) { + return null; + } CompanySymbols cSymbol = companySymbolsImdg.getSingleObjectByFieldValues(Map.of( "companyId", companyId, "companySymbol", symbol.getKey())); @@ -425,6 +434,9 @@ public class PaymentInstructionCreator { } protected Account selectAccount(Long companyId, AccountType accountType, Status accountStatus, Allowed processingSign) { + if (companyId == null) { + return null; + } Account account = accountImdg.getSingleObjectByFieldValues(Map.of( "companyId", companyId, "accountType", accountType.getKey(), @@ -439,29 +451,31 @@ public class PaymentInstructionCreator { * 2.2.2.1. Выполнить Изменение liabilitiesClaimsAssets по paymentInstruction. */ public void updateFieldLiabilitiesClaimsAssetsByPayment(LiabilitiesClaimsAssets liabilitiesClaimsAssets, - List paymentInstructions, - Collection clearingCategory) { - AccountType accountType = IEnumKey.getEnumByKey(AccountType.class, liabilitiesClaimsAssets.getAccountType()); - PaymentInstruction paymentIAny=paymentInstructions.iterator().next(); + List paymentInstructions, + Collection clearingCategory) { - if ((clearingCategory.contains(ClearingCategory.I) && AccountType.Clrn.equals(accountType)) - || (clearingCategory.contains(ClearingCategory.V) && AccountType.Info.equals(accountType))) { - BigDecimal amount = paymentIAny.getCreditLegAmount() == null ? BigDecimal.ZERO : new BigDecimal(paymentIAny.getCreditLegAmount()); - BigDecimal prevLQuantity = BigDecimalUtil.safeBD(liabilitiesClaimsAssets.getLiabilitiesQuantity()); - liabilitiesClaimsAssets.setLiabilitiesQuantity(prevLQuantity.subtract(amount)); + PaymentInstruction paymentIAny = paymentInstructions.iterator().next(); + + if (clearingCategory.contains(ClearingCategory.I) || clearingCategory.contains(ClearingCategory.V)) { + BigDecimal amount = bdFromLongSafe(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) && AccountType.Clrn.equals(accountType)) { - BigDecimal amount = paymentIAny.getCreditLegAmount() == null ? BigDecimal.ZERO : new BigDecimal(paymentIAny.getCreditLegAmount()); + if (clearingCategory.contains(ClearingCategory.B)) { + BigDecimal amount = bdFromLongSafe(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()); + BigDecimal amount = bdFromLongSafe(paymentIAny.getDebitLegAmount()); liabilitiesClaimsAssets.setClaimsQuantity(amount); } if (clearingCategory.contains(ClearingCategory.B)) { - BigDecimal amount = new BigDecimal((Long)paymentIAny.getDebitLegAmount()); - amount = liabilitiesClaimsAssets.getClaimsQuantity().subtract(amount); + BigDecimal amount = bdFromLongSafe(paymentIAny.getDebitLegAmount()); + amount = safeBD(liabilitiesClaimsAssets.getClaimsQuantity()).subtract(amount); liabilitiesClaimsAssets.setClaimsQuantity(amount); } @@ -478,56 +492,55 @@ public class PaymentInstructionCreator { /** * 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 (liabilitiesClaimsMoney == null) { - throw new RuntimeException("IMDG not found LiabilitiesClaimsMoney.id=" + lmId); - } - 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 + * Обновление liabilitiesClaimsMoney первой/второй ноги по liabilitiesClaimsAssets + * * @param liabilitiesClaimsMoney обновить этот объект (firstLeg) + * @param isFirstLeg true - первая, false вторая * @param paymentInstructions * @param clearingCategory * @return были внесены изменения в liabilitiesClaimsMoney */ public boolean updateFieldLiabilitiesClaimsMoneyByPayment(LiabilitiesClaimsMoney liabilitiesClaimsMoney, - List paymentInstructions, - Collection clearingCategory) { + boolean isFirstLeg, + List paymentInstructions, + Collection clearingCategory) { + final boolean isSecondLeg = !isFirstLeg; boolean modified = false; - PaymentInstruction paymentIAny=paymentInstructions.iterator().next(); + PaymentInstruction paymentIAny = paymentInstructions.iterator().next(); - 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.I) || clearingCategory.contains(ClearingCategory.V)) { + if (isFirstLeg) { + BigDecimal amount = safeBD(liabilitiesClaimsMoney.getLiabilitiesAmount()).subtract(bdFromLongSafe(paymentIAny.getCreditLegAmount())); + liabilitiesClaimsMoney.setLiabilitiesAmount(amount); + modified = true; + } + if (isSecondLeg) { + // liabilitiesAmount не меняется + } } - if ((clearingCategory.contains(ClearingCategory.B))) { - BigDecimal amount = liabilitiesClaimsMoney.getClaimsAmount().subtract(new BigDecimal((Long)paymentIAny.getDebitLegAmount())); - liabilitiesClaimsMoney.setClaimsAmount(amount); - modified = true; + if (clearingCategory.contains(ClearingCategory.B)) { + if (isFirstLeg) { + // liabilitiesAmount не меняется ; + } + if (isSecondLeg) { + BigDecimal amount = safeBD(liabilitiesClaimsMoney.getClaimsAmount()).subtract(bdFromLongSafe(paymentIAny.getDebitLegAmount())); + liabilitiesClaimsMoney.setClaimsAmount(amount); + modified = true; + } } if (modified) { liabilitiesClaimsMoney.setUpdated(Instant.now()); } + log.debug("updateFieldLiabilitiesClaimsMoneyByPayment: isFirstLeg={}, isSecondLeg={}, modified={}, LiabilitiesClaimsMoney.id={}", + isFirstLeg, isSecondLeg, modified, liabilitiesClaimsMoney.getId()); return modified; } + + private BigDecimal bdFromLongSafe(Long l) { + if (l == null) return BigDecimal.ZERO; + return new BigDecimal(l); + } }