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;