From 6b43d3b238245d7b4460b1095f85a2913e5f945e Mon Sep 17 00:00:00 2001 From: AKurakin Date: Wed, 1 Feb 2023 14:48:15 +0300 Subject: [PATCH 1/5] =?UTF-8?q?dbf-exporter=20=D0=B4=D0=BE=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B0=D0=BB=20=D0=BE=D0=BF=D1=86=D0=B8=D0=BE=D0=BD=D0=B0?= =?UTF-8?q?=D0=BB=D1=8C=D0=BD=D1=8B=D0=B9=20KafkaSender,=20=D0=B8=D0=BD?= =?UTF-8?q?=D0=B0=D1=87=D0=B5=20=D0=BD=D0=B5=20=D0=B7=D0=B0=D0=BF=D1=83?= =?UTF-8?q?=D1=81=D0=BA=D0=B0=D0=BB=D1=81=D1=8F=20=D0=B1=D0=B5=D0=B7=20?= =?UTF-8?q?=D0=BD=D0=B5=D0=BE=D0=B1=D1=8F=D0=B7=D0=B0=D1=82=D0=B5=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D1=8B=D1=85=20=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=B5=D0=BA.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../clearing/dbf/exporter/config/KafkaSenderConfig.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/clearing-parent/dbf-exporter/src/main/java/ru/spcex/clearing/dbf/exporter/config/KafkaSenderConfig.java b/clearing-parent/dbf-exporter/src/main/java/ru/spcex/clearing/dbf/exporter/config/KafkaSenderConfig.java index d2397c4a5..2b2319156 100644 --- a/clearing-parent/dbf-exporter/src/main/java/ru/spcex/clearing/dbf/exporter/config/KafkaSenderConfig.java +++ b/clearing-parent/dbf-exporter/src/main/java/ru/spcex/clearing/dbf/exporter/config/KafkaSenderConfig.java @@ -1,6 +1,8 @@ package ru.spcex.clearing.dbf.exporter.config; import org.apache.kafka.clients.producer.Producer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -14,6 +16,7 @@ import ru.spcex.platform.imdg.api.ImdgProvider; //отдельный конфиг для sender чтобы сделать required false @Configuration public class KafkaSenderConfig { + Logger log = LoggerFactory.getLogger(getClass()); private final ImdgProvider imdgProvider; private Producer kafkaProducer; @@ -23,14 +26,15 @@ public class KafkaSenderConfig { this.imdgProvider = imdgProvider; } - @Autowired + @Autowired(required = false) public void setKafkaProducer(Producer kafkaProducer) { this.kafkaProducer = kafkaProducer; } @Bean public KafkaSender kafkaSender() { - if (kafkaProducer == null ||imdgProvider == null) { + if (kafkaProducer == null || imdgProvider == null) { + log.info("Can not create KafkaSender: kafkaProducer={}, imdgProvider={}", kafkaProducer, imdgProvider); return null; } ImdgId imdgIdGenerator = imdgProvider.getImdgIdGenerator(); From 5c143ad47ae28475cc98958c222778252925140a Mon Sep 17 00:00:00 2001 From: etreschenkov Date: Wed, 1 Feb 2023 16:30:37 +0300 Subject: [PATCH 2/5] update meta --- .../backend-api/src/main/resources/meta/meta.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) 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 de067158f..c96d68e05 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 @@ - + @@ -713,8 +713,8 @@ - - + + @@ -752,7 +752,7 @@ - + @@ -907,13 +907,13 @@ - + - - + + From 43b69192e6e68cf74e0f37347357fc62bcffb8a5 Mon Sep 17 00:00:00 2001 From: akurakin Date: Wed, 1 Feb 2023 18:04:27 +0300 Subject: [PATCH 3/5] =?UTF-8?q?clearing-service=20http://jira.mfd.msk:8088?= =?UTF-8?q?/browse/CLS-189=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20PaymentInstruction,=20=D1=87=D0=B0=D1=81=D1=82=D1=8C?= =?UTF-8?q?=202.2.2=20=D0=BF=D0=BE=D0=BB=D0=BE=D0=B2=D0=B8=D0=BD=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ru/spcex/clearing/service/Clearing.java | 18 +- .../order/PaymentInstructionCreator.java | 253 ++++++++++++++++++ .../platform/enumeration/AccountType.java | 2 +- .../platform/enumeration/InOutDirection.java | 2 +- 4 files changed, 268 insertions(+), 7 deletions(-) create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/order/PaymentInstructionCreator.java 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; From 5f41508df3a5727332cf84fdaf1d63f1dd3d8839 Mon Sep 17 00:00:00 2001 From: akurakin Date: Wed, 1 Feb 2023 20:13:43 +0300 Subject: [PATCH 4/5] =?UTF-8?q?clearing-service=20http://jira.mfd.msk:8088?= =?UTF-8?q?/browse/CLS-189=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20PaymentInstruction,=20=D1=87=D0=B0=D1=81=D1=82=D1=8C?= =?UTF-8?q?=202.2.2=20=D0=B4=D0=BE=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D0=BD=D0=BE=D1=81=D1=82=D1=8C=D1=8E,=20=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D0=BB=D0=BE=D1=81=D1=8C=202.2.2.1=20=D0=B8?= =?UTF-8?q?=202.2.2.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- clearing-parent/clearing-service/pom.xml | 4 + .../order/PaymentInstructionCreator.java | 211 ++++++++++++++++-- .../order/PaymentInstructionCreatorTest.java | 29 +++ .../platform/enumeration/AccountType.java | 2 +- 4 files changed, 224 insertions(+), 22 deletions(-) create mode 100644 clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/order/PaymentInstructionCreatorTest.java diff --git a/clearing-parent/clearing-service/pom.xml b/clearing-parent/clearing-service/pom.xml index aa206dcf4..1d7d1fd1a 100644 --- a/clearing-parent/clearing-service/pom.xml +++ b/clearing-parent/clearing-service/pom.xml @@ -51,6 +51,10 @@ assertj-core test + + org.mockito + mockito-core + 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 index 541c0353c..950e3c7a3 100644 --- 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 @@ -27,6 +27,9 @@ import java.util.concurrent.atomic.AtomicLong; @Service public class PaymentInstructionCreator { + protected static final Long SPVB_ID = 1L; // СПВБ + protected static final Long PRC_ID = 2L; // 2 "НКО АО ПРЦ" + private final Logger log = LoggerFactory.getLogger(getClass()); protected final ImdgId idGenerator; @@ -71,18 +74,11 @@ public class PaymentInstructionCreator { 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)) { + log.debug("By liabilitiesClaimsAssets[{}] create for category I 1 record", liabilitiesClaimsAssets.getId()); PaymentInstruction payment1 = new PaymentInstruction(); PaymentInstruction payment2 = new PaymentInstruction(); @@ -94,9 +90,9 @@ public class PaymentInstructionCreator { payment2.setClearingDate(TimeUtil.toLocalDate(now)); payment1.setSenderId(liabilitiesClaimsAssets.getCompanyId()); - payment2.setSenderId(1L); // СПВБ + payment2.setSenderId(SPVB_ID); // СПВБ - payment1.setAddresseeId(1L); // СПВБ + payment1.setAddresseeId(SPVB_ID); // СПВБ String sqlLCA = String.format("securityId = %s and companyId <> %s", liabilitiesClaimsAssets.getSecurityId(), liabilitiesClaimsAssets.getCompanyId()); LiabilitiesClaimsAssets counterLiabilitiesClaimsAssets = liabilitiesClaimsAssetsImdg.getSingleObjectBySQL(sqlLCA); @@ -119,7 +115,7 @@ public class PaymentInstructionCreator { payment2.setAdresseeBic(symbol2); } - Company companyPRC = companyImdg.getSingleObjectByID(2L); // 2 "НКО АО ПРЦ" + Company companyPRC = companyImdg.getSingleObjectByID(PRC_ID); // 2 "НКО АО ПРЦ" String companyPRCName = null; if (companyPRC == null) { log.warn("Company.id=2 not found"); @@ -129,7 +125,7 @@ public class PaymentInstructionCreator { payment1.setPayeeBankName(companyPRCName); payment2.setPayeeBankName(companyPRCName); - String symbolPRC = selectSymbolValue(2L, CompanySymbol.BIC); // 2 "НКО АО ПРЦ" + String symbolPRC = selectSymbolValue(PRC_ID, CompanySymbol.BIC); // 2 "НКО АО ПРЦ" payment1.setPayeeBic(symbolPRC); payment2.setPayeeBic(symbolPRC); @@ -191,10 +187,10 @@ public class PaymentInstructionCreator { 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.setCreditLegDirection(InOutDirection.out.getKey()); +// payment2.setCreditLegDirection(InOutDirection.out.getKey()); +// payment1.setDebitLegDirection(InOutDirection.in.getKey()); +// payment2.setDebitLegDirection(InOutDirection.in.getKey()); payment1.setCreditLegCurrencyCode(liabilitiesClaimsAssets.getCurrency()); payment2.setCreditLegCurrencyCode(liabilitiesClaimsAssets.getCurrency()); @@ -210,18 +206,191 @@ public class PaymentInstructionCreator { newPaymentInstructions.add(payment1); newPaymentInstructions.add(payment2); + } else { + // V / B + if (clearingCategory.contains(ClearingCategory.V)) { + log.debug("By liabilitiesClaimsAssets[{}] create for category V 1 record", liabilitiesClaimsAssets.getId()); + PaymentInstruction payment1 = new PaymentInstruction(); + payment1.setId(idGenerator.nextId()); + payment1.setCreated(now); + payment1.setClearingDate(TimeUtil.toLocalDate(now)); + + payment1.setSenderId(SPVB_ID); // СПВБ + + 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 { + payment1.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); + } + + Company companyPRC = companyImdg.getSingleObjectByID(PRC_ID); // 2 "НКО АО ПРЦ" + String companyPRCName = null; + if (companyPRC == null) { + log.warn("Company.id=2 not found"); + } else { + companyPRCName = companyPRC.getShortName(); + } + payment1.setPayeeBankName(companyPRCName); + + String symbolPRC = selectSymbolValue(PRC_ID, CompanySymbol.BIC); // 2 "НКО АО ПРЦ" + payment1.setPayeeBic(symbolPRC); + + payment1.setAddresseeBankName(companyPRCName); + + payment1.setPaymentDate(TimeUtil.localDateToInstant(liabilitiesClaimsAssets.getSettlementDate())); + + payment1.setPaymentPurpose("Размещение депозита " + liabilitiesClaimsAssets.getContract()); + + payment1.setSettlementDate(liabilitiesClaimsAssets.getSettlementDate()); + + Long amount = liabilitiesClaimsAssets.getLiabilitiesQuantity() == null ? null : liabilitiesClaimsAssets.getLiabilitiesQuantity().abs().longValue(); + payment1.setCreditLegAmount(amount); + payment1.setDebitLegAmount(amount); + + { + String accSql = String.format("companyId = %s AND accountType=ANLT AND accountStatus=ACTV AND processingSign=ALWD", + payment1.getSenderId()); + Account acc1 = accountImdg.getSingleObjectBySQL(accSql); + if (acc1 == null) { + log.warn("Account not found: {}", accSql); + } else { + payment1.setCreditLegAccountId(acc1.getId()); + payment1.setCreditLegAccount(acc1.getAccount()); + } + } + + payment1.setCreditCsAccount(null); + + { + Account acc1 = selectAccount(payment1.getAddresseeId(), AccountType.Corr, Status.Active, Allowed.ALLOWED); + if (acc1 != null) { + payment1.setDebitLegAccountId(acc1.getId()); + payment1.setDebitLegAccount(acc1.getAccount()); + } + } + + payment1.setDebitCsAccount(null); + +// payment1.setCreditLegDirection(InOutDirection.out.getKey()); +// payment1.setDebitLegDirection(InOutDirection.in.getKey()); + + payment1.setCreditLegCurrencyCode(liabilitiesClaimsAssets.getCurrency()); + payment1.setDebitLegCurrencyCode(liabilitiesClaimsAssets.getCurrency()); + + payment1.setTransactionStatus(TransactionStatus.stld.getKey()); + + + payment1.setDocumentNumber(nextDocumentNumber(liabilitiesClaimsAssets, payment1)); + + newPaymentInstructions.add(payment1); + } else // Для V,B только 1 PaymentInstruction + if (clearingCategory.contains(ClearingCategory.B)) { + log.debug("By liabilitiesClaimsAssets[{}] create for category B 1 record", liabilitiesClaimsAssets.getId()); + PaymentInstruction payment1 = new PaymentInstruction(); + payment1.setId(idGenerator.nextId()); + payment1.setCreated(now); + payment1.setClearingDate(TimeUtil.toLocalDate(now)); + + payment1.setSenderId(liabilitiesClaimsAssets.getCompanyId()); + + payment1.setAddresseeId(SPVB_ID); // СПВБ + + String symbol1 = selectSymbolValue(payment1.getAddresseeId(), CompanySymbol.BIC); + if (symbol1 == null) { + log.warn("CompanySymbols BIC not found for companyId={}", payment1.getAddresseeId()); + } else { + payment1.setAdresseeBic(symbol1); + } + + Company companyPRC = companyImdg.getSingleObjectByID(PRC_ID); // 2 "НКО АО ПРЦ" + String companyPRCName = null; + if (companyPRC == null) { + log.warn("Company.id=2 not found"); + } else { + companyPRCName = companyPRC.getShortName(); + } + payment1.setPayeeBankName(companyPRCName); + + String symbolPRC = selectSymbolValue(PRC_ID, CompanySymbol.BIC); // 2 "НКО АО ПРЦ" + payment1.setPayeeBic(symbolPRC); + + payment1.setAddresseeBankName(companyPRCName); + + payment1.setPaymentDate(TimeUtil.localDateToInstant(liabilitiesClaimsAssets.getSettlementDate())); + + payment1.setPaymentPurpose("Размещение депозита " + liabilitiesClaimsAssets.getContract()); + + payment1.setSettlementDate(liabilitiesClaimsAssets.getSettlementDate()); + + Long amount = liabilitiesClaimsAssets.getLiabilitiesQuantity() == null ? null : liabilitiesClaimsAssets.getLiabilitiesQuantity().abs().longValue(); + payment1.setCreditLegAmount(amount); + payment1.setDebitLegAmount(amount); + + { + String accSql = String.format("companyId = %s AND accountType=ANLT AND accountStatus=ACTV AND processingSign=ALWD", + payment1.getSenderId()); + Account acc1 = accountImdg.getSingleObjectBySQL(accSql); + if (acc1 == null) { + log.warn("Account not found: {}", accSql); + } else { + payment1.setCreditLegAccountId(acc1.getId()); + payment1.setCreditLegAccount(acc1.getAccount()); + } + } + + payment1.setCreditCsAccount(null); + + { + Account acc1 = selectAccount(payment1.getAddresseeId(), AccountType.Corr, Status.Active, Allowed.ALLOWED); + if (acc1 != null) { + payment1.setDebitLegAccountId(acc1.getId()); + payment1.setDebitLegAccount(acc1.getAccount()); + } + } + + payment1.setDebitCsAccount(null); + +// payment1.setCreditLegDirection(InOutDirection.out.getKey()); +// payment1.setDebitLegDirection(InOutDirection.in.getKey()); + + payment1.setCreditLegCurrencyCode(liabilitiesClaimsAssets.getCurrency()); + payment1.setDebitLegCurrencyCode(liabilitiesClaimsAssets.getCurrency()); + + payment1.setTransactionStatus(TransactionStatus.stld.getKey()); + + + payment1.setDocumentNumber(nextDocumentNumber(liabilitiesClaimsAssets, payment1)); + + newPaymentInstructions.add(payment1); + } } - //todo сочетания типов??? Другие типы return newPaymentInstructions; } protected String nextDocumentNumber(LiabilitiesClaimsAssets liabilitiesClaimsAssets, PaymentInstruction paymentInstruction) { - if (documentNumberResetAt == null || documentNumberResetAt.isBefore(LocalDate.now())) { - documentNumberId.set(0); - documentNumberResetAt = LocalDate.now(); + LocalDate nowD = LocalDate.now(); + if (documentNumberResetAt == null || documentNumberResetAt.isBefore(nowD)) synchronized (this){ + long oldNum = documentNumberId.get(); // reset optimistic + if (oldNum > 0) { + while (!documentNumberId.compareAndSet(oldNum, 0)) { + oldNum = documentNumberId.get(); + if (oldNum < 2) break; + } + } + documentNumberResetAt = nowD; } DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ddMMyy"); - String num = String.format("%s/%s/%s/", + String num = String.format("%s/%s/%s/%s", liabilitiesClaimsAssets.getContract(), formatter.format(paymentInstruction.getPaymentDate()), paymentInstruction.getSenderId(), documentNumberId.incrementAndGet() ); diff --git a/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/order/PaymentInstructionCreatorTest.java b/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/order/PaymentInstructionCreatorTest.java new file mode 100644 index 000000000..6e4c63700 --- /dev/null +++ b/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/order/PaymentInstructionCreatorTest.java @@ -0,0 +1,29 @@ +package ru.spcex.clearing.service.order; + +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import ru.clearing.classes.statics.data.liabilities.LiabilitiesClaimsAssets; +import ru.clearing.classes.statics.data.payment.PaymentInstruction; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.utils.time.TimeUtil; + +import java.time.LocalDate; + +import static org.junit.jupiter.api.Assertions.*; + +class PaymentInstructionCreatorTest { + + @Test + void nextDocumentNumber() { + ImdgProvider nullImdg = Mockito.mock(ImdgProvider.class); + PaymentInstructionCreator instance = new PaymentInstructionCreator(nullImdg); + LiabilitiesClaimsAssets liabilitiesClaimsAssets = new LiabilitiesClaimsAssets(); + liabilitiesClaimsAssets.setContract("contract"); + PaymentInstruction paymentInstruction = new PaymentInstruction(); + paymentInstruction.setPaymentDate(TimeUtil.localDateToInstant(LocalDate.of(2023,1,4))); + paymentInstruction.setSenderId(1234L); + assertEquals("contract/230104/1234/1", instance.nextDocumentNumber(liabilitiesClaimsAssets, paymentInstruction)); + assertEquals("contract/230104/1234/2", instance.nextDocumentNumber(liabilitiesClaimsAssets, paymentInstruction)); + assertEquals("contract/230104/1234/3", instance.nextDocumentNumber(liabilitiesClaimsAssets, paymentInstruction)); + } +} \ No newline at end of file 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 7c9d342b3..43d0ceebc 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"), Tran("TRAN"); + Clrn("CLRN"), Bank("BANK"), Info("INFO"), Tran("TRAN"), Corr("CORR"); private final String key; From 1debfd81da971fa862618ec43fef17cb9de0eb8c Mon Sep 17 00:00:00 2001 From: AKurakin Date: Wed, 1 Feb 2023 20:06:23 +0300 Subject: [PATCH 5/5] =?UTF-8?q?clearing-service=20http://jira.mfd.msk:8088?= =?UTF-8?q?/browse/CLS-189=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20PaymentInstruction...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/order/PaymentInstructionCreator.java | 9 +++++---- .../service/order/PaymentInstructionCreatorTest.java | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) 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 index 950e3c7a3..94761ff50 100644 --- 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 @@ -29,6 +29,7 @@ import java.util.concurrent.atomic.AtomicLong; public class PaymentInstructionCreator { protected static final Long SPVB_ID = 1L; // СПВБ protected static final Long PRC_ID = 2L; // 2 "НКО АО ПРЦ" + private static final DateTimeFormatter DATE_FORMATTER_ddMMyy = DateTimeFormatter.ofPattern("ddMMyy"); private final Logger log = LoggerFactory.getLogger(getClass()); @@ -39,7 +40,7 @@ public class PaymentInstructionCreator { protected final Imdg accountImdg; protected final Imdg paymentInstructionImdg; - protected AtomicLong documentNumberId = new AtomicLong(); // порядковый номер (сквозной по всем компаниям за день + protected AtomicLong documentNumberId = new AtomicLong(0L); // порядковый номер (сквозной по всем компаниям за день protected LocalDate documentNumberResetAt; @Autowired @@ -379,7 +380,7 @@ public class PaymentInstructionCreator { protected String nextDocumentNumber(LiabilitiesClaimsAssets liabilitiesClaimsAssets, PaymentInstruction paymentInstruction) { LocalDate nowD = LocalDate.now(); - if (documentNumberResetAt == null || documentNumberResetAt.isBefore(nowD)) synchronized (this){ + if (documentNumberResetAt == null || documentNumberResetAt.isBefore(nowD)) synchronized (this) { long oldNum = documentNumberId.get(); // reset optimistic if (oldNum > 0) { while (!documentNumberId.compareAndSet(oldNum, 0)) { @@ -389,9 +390,9 @@ public class PaymentInstructionCreator { } documentNumberResetAt = nowD; } - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ddMMyy"); + String paymentDate = DATE_FORMATTER_ddMMyy.format(TimeUtil.toLocalDate(paymentInstruction.getPaymentDate())); String num = String.format("%s/%s/%s/%s", - liabilitiesClaimsAssets.getContract(), formatter.format(paymentInstruction.getPaymentDate()), + liabilitiesClaimsAssets.getContract(), paymentDate, paymentInstruction.getSenderId(), documentNumberId.incrementAndGet() ); return num; diff --git a/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/order/PaymentInstructionCreatorTest.java b/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/order/PaymentInstructionCreatorTest.java index 6e4c63700..f5a632ab1 100644 --- a/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/order/PaymentInstructionCreatorTest.java +++ b/clearing-parent/clearing-service/src/test/java/ru/spcex/clearing/service/order/PaymentInstructionCreatorTest.java @@ -22,8 +22,8 @@ class PaymentInstructionCreatorTest { PaymentInstruction paymentInstruction = new PaymentInstruction(); paymentInstruction.setPaymentDate(TimeUtil.localDateToInstant(LocalDate.of(2023,1,4))); paymentInstruction.setSenderId(1234L); - assertEquals("contract/230104/1234/1", instance.nextDocumentNumber(liabilitiesClaimsAssets, paymentInstruction)); - assertEquals("contract/230104/1234/2", instance.nextDocumentNumber(liabilitiesClaimsAssets, paymentInstruction)); - assertEquals("contract/230104/1234/3", instance.nextDocumentNumber(liabilitiesClaimsAssets, paymentInstruction)); + assertEquals("contract/040123/1234/1", instance.nextDocumentNumber(liabilitiesClaimsAssets, paymentInstruction)); + assertEquals("contract/040123/1234/2", instance.nextDocumentNumber(liabilitiesClaimsAssets, paymentInstruction)); + assertEquals("contract/040123/1234/3", instance.nextDocumentNumber(liabilitiesClaimsAssets, paymentInstruction)); } } \ No newline at end of file