clearing-service http://jira.mfd.msk:8088/browse/CLS-189 создание PaymentInstruction, часть 2.2.2 половина

This commit is contained in:
akurakin 2023-02-01 18:04:27 +03:00
parent 5c143ad47a
commit 43b69192e6
4 changed files with 268 additions and 7 deletions

View file

@ -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<ClearingMemberCategory> clearingCategoryImdg;
private final ExecutionDepositSorter sorter;
private final BiFunction<ClearingCategory, ExecutionDeposit, IValidator> validation;
private final PaymentInstructionCreator paymentInstructionCreator;
@Autowired
public Clearing(ImdgProvider imdgProvider,
ExecutionDepositSorter sorter,
ExecutionDepositSorter sorter, PaymentInstructionCreator paymentInstructionCreator,
BiFunction<ClearingCategory, ExecutionDeposit, IValidator> 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<ExecutionDeposit> companyExecDeposits : companies) {
processSingleCompany(category, companyExecDeposits);
// todo paymentInstructionCreator
// LiabilitiesClaimsAssets liabilitiesClaimsAssets = null;
// Collection<ClearingCategory> clearingCategory = Collections.singleton(category);
// List<PaymentInstruction> newPaymentInstructions = paymentInstructionCreator.createAndSavePaymentInstructions(liabilitiesClaimsAssets, );
//todo Изменение liabilitiesClaimsAssets по paymentInstruction
// todo Изменение liabilitiesClaimsMoney по paymentInstruction
}
});
}

View file

@ -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<LiabilitiesClaimsAssets> liabilitiesClaimsAssetsImdg;
protected final Imdg<CompanySymbols> companySymbolsImdg;
protected final Imdg<Company> companyImdg;
protected final Imdg<Account> accountImdg;
protected final Imdg<PaymentInstruction> 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<PaymentInstruction> createAndSavePaymentInstructions(LiabilitiesClaimsAssets liabilitiesClaimsAssets,
Collection<ClearingCategory> clearingCategory) {
List<PaymentInstruction> 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<PaymentInstruction> createPaymentInstructions(LiabilitiesClaimsAssets liabilitiesClaimsAssets,
Collection<ClearingCategory> clearingCategory) {
List<PaymentInstruction> 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;
}
}

View file

@ -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;

View file

@ -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;