SDF57 обработка
1. DMAU регистры 2. поиск счетов для кейса accountType=ANLT
This commit is contained in:
parent
075591d2ea
commit
28102d34af
6 changed files with 243 additions and 14 deletions
|
|
@ -27,6 +27,8 @@ public enum ClearingError implements IErrorEnumId {
|
|||
AccountNotFoundB(5217L),
|
||||
MarketIsNotMkr(5217L),
|
||||
BalanceInsufficient(5222L),
|
||||
TCRegistryNotFound(3022L),
|
||||
WrongField(5004L),
|
||||
|
||||
ActiveSessionIsPresent(-1L),
|
||||
;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import ru.spcex.clearing.session.stage.util.RegistryUtil;
|
|||
import ru.spcex.platform.enumeration.*;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
import ru.spcex.platform.utils.enumeration.IEnumKey;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Instant;
|
||||
|
|
@ -63,7 +64,7 @@ public class RegistryBuilder {
|
|||
|
||||
public Registry build() {
|
||||
Registry rgs = new Registry();
|
||||
rgs.setCompanyId(statement.getAddresseeId());
|
||||
rgs.setCompanyId(company.getId());
|
||||
rgs.setTradingCode(company.getTradingCode());
|
||||
rgs.setClearingCode(company.getClearingCode());
|
||||
rgs.setShortName(company.getShortName());
|
||||
|
|
@ -74,16 +75,21 @@ public class RegistryBuilder {
|
|||
rgs.setRegistryDesignation(designation.getKey());
|
||||
rgs.setRegistryInstrumentType(RegistryInstrumentType.M.getKey());
|
||||
|
||||
ClearingAccount accountForStatement = clearingAccountImdg.getSingleObjectByID(statement.getAccountId());
|
||||
if (accountForStatement != null) {
|
||||
rgs.setRegistryCapacity(accountForStatement.getClearingAccountType());
|
||||
AccountType accType = IEnumKey.getEnumByKey(AccountType.class, account.getAccountType());
|
||||
if (AccountType.Clrn.equals(accType)) {
|
||||
ClearingAccount accountForStatement = clearingAccountImdg.getSingleObjectByFieldValues(Map.of("accountId", statement.getAccountId()));
|
||||
if (accountForStatement != null) {
|
||||
rgs.setRegistryCapacity(accountForStatement.getClearingAccountType());
|
||||
}
|
||||
} else if (AccountType.Info.equals(accType) || AccountType.Anlt.equals(accType)) {
|
||||
rgs.setRegistryCapacity(RegistryCapacity.A.getKey());
|
||||
}
|
||||
rgs.setRegistryUnit(RegistryUnit.T.getKey());
|
||||
rgs.setRegistryCode(RegistryUtil.clearingCode(rgs));
|
||||
|
||||
Collection<TradingClearingRegistry> tcrsByAccount = tradingClearingRegistryImdg.getCollectionObjectsByFieldValues(Map.of(
|
||||
"moneyAccountId", statement.getAccountId(),
|
||||
"companyId", statement.getAddresseeId(),
|
||||
"moneyAccountId", account.getId(),
|
||||
"companyId", company.getId(),
|
||||
"status", ServiceStatus.Active.getKey()
|
||||
));
|
||||
if (!tcrsByAccount.isEmpty()) {
|
||||
|
|
|
|||
|
|
@ -229,7 +229,6 @@ public class Sdf01Executor extends AbstractExecutor<SDf01> {
|
|||
private Statement createSdf01Statement(SDf01 sdf01, Company company, Account account) {
|
||||
Statement stmt = new Statement();
|
||||
stmt.setAddresseeId(company.getId());
|
||||
stmt.setAddresseeId(company.getId());
|
||||
stmt.setSenderId(Sender.Prc.getId());
|
||||
stmt.setStatementType(StatementType.full.getKey());
|
||||
stmt.setAccountId(account.getId());
|
||||
|
|
|
|||
|
|
@ -34,7 +34,9 @@ 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.RegistryCodeSqlBuilder;
|
||||
import ru.spcex.platform.utils.collection.Pair;
|
||||
import ru.spcex.platform.utils.enumeration.EnumMessage;
|
||||
import ru.spcex.platform.utils.enumeration.IEnumId;
|
||||
import ru.spcex.platform.utils.enumeration.IEnumKey;
|
||||
import ru.spcex.platform.utils.enumeration.IMessageResolver;
|
||||
import ru.spcex.platform.utils.text.TextUtil;
|
||||
|
|
@ -66,6 +68,8 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
|
|||
private final Imdg<AccountBalance> accountBalanceImdg;
|
||||
private final Imdg<ClearingAccount> clearingAccountImdg;
|
||||
private final Imdg<TradingClearingRegistry> tradingClearingRegistryImdg;
|
||||
private final Imdg<Account> accountImdg;
|
||||
private final Imdg<Company> companyImdg;
|
||||
private final Imdg<Security> securityImdg;
|
||||
private final Imdg<Currency> currencyImdg;
|
||||
private final IMessageResolver messageResolver;
|
||||
|
|
@ -82,6 +86,8 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
|
|||
this.clearingAccountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingAccount, ClearingAccount.class);
|
||||
this.tradingClearingRegistryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class);
|
||||
this.currencyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Currency, Currency.class);
|
||||
this.accountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class);
|
||||
this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
|
||||
this.sDf57Validator = sDf57Validator;
|
||||
this.errorLogger = errorLogger;
|
||||
this.imdgProvider = imdgProvider;
|
||||
|
|
@ -174,7 +180,12 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
|
|||
return;
|
||||
Optional<EnumMessage> err = validateActiveness(company, account);
|
||||
if (err.isEmpty()) {
|
||||
findRegByDesignation(stmt, RegistryTradingParams.AM_T, false, false).ifPresentOrElse(rgs -> {
|
||||
Optional<Registry> amtFound = RegistrySearch.builder(registryImdg)
|
||||
.rgsCode(RegistryTradingParams.AM_T)
|
||||
.companyId(company.getId()) //раньше было stmt.getAddresseeId()
|
||||
.accountId(account.getId()) //раньше было stmt.getAccountId()
|
||||
.find();
|
||||
amtFound.ifPresentOrElse(rgs -> {
|
||||
log.debug("stmt.id={}, found AM*T.id={}, updating...", stmt.getId(), rgs.getId());
|
||||
updateReg(stmt, rgs);
|
||||
//добавил создание если не найдены
|
||||
|
|
@ -228,14 +239,31 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
|
|||
//stmt.id=340270002, sdf57.specif=Возврат депозита по договору №DT1000S001U/280623/8/7 new DM*T.id=339610032
|
||||
//1. у stmt accountId 3021, addresseId 2610034, contract DT1000S001U/280623/8/7
|
||||
//
|
||||
Optional<Registry> dm__Found = findRegByDesignation(stmt, RegistryTradingParams.DM__, true, false);
|
||||
Optional<Registry> dm__Found = RegistrySearch.builder(registryImdg)
|
||||
.rgsCode(RegistryTradingParams.DM__)
|
||||
.companyId(company.getId())
|
||||
.accountId(account.getId())
|
||||
.contract(stmt.getContract())
|
||||
.find();
|
||||
Optional<Registry> om_tFound = Optional.empty();
|
||||
Optional<Registry> tm_tFound = Optional.empty();
|
||||
if (dm__Found.isEmpty()) {
|
||||
om_tFound = findRegByDesignation(stmt, RegistryTradingParams.OM_T, true, true);
|
||||
om_tFound = RegistrySearch.builder(registryImdg)
|
||||
.rgsCode(RegistryTradingParams.OM_T)
|
||||
.companyId(company.getId())
|
||||
.accountId(account.getId())
|
||||
.contract(stmt.getContract())
|
||||
.status()
|
||||
.find();
|
||||
}
|
||||
if (dm__Found.isEmpty() && om_tFound.isEmpty()) {
|
||||
tm_tFound = findRegByDesignation(stmt, RegistryTradingParams.TM_T, true, true);
|
||||
tm_tFound = RegistrySearch.builder(registryImdg)
|
||||
.rgsCode(RegistryTradingParams.TM_T)
|
||||
.companyId(company.getId())
|
||||
.accountId(account.getId())
|
||||
.contract(stmt.getContract())
|
||||
.status()
|
||||
.find();
|
||||
}
|
||||
if (dm__Found.isPresent()) {
|
||||
Registry dm__ = dm__Found.get();
|
||||
|
|
@ -276,12 +304,109 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
|
|||
statementImdg.update(stmt);
|
||||
}
|
||||
};
|
||||
statementDeb.ifPresent(stmt -> createRegistryIfNeeded.accept(new StmtCmpAcc(stmt, companyDeb, accountDeb)));
|
||||
statementCred.ifPresent(stmt -> createRegistryIfNeeded.accept(new StmtCmpAcc(stmt, companyCred, accountCred)));
|
||||
Consumer<StmtCmpAcc> registersUpdate = stmtCmpAcc -> {
|
||||
Statement stmt = stmtCmpAcc.statement();
|
||||
Company cmp = stmtCmpAcc.company();
|
||||
Account acc = stmtCmpAcc.account();
|
||||
createRegistryIfNeeded.accept(stmtCmpAcc);
|
||||
if (accountIsAnlt(acc)) {
|
||||
Optional<Pair<Company, Account>> anltLink = loadByAnlt(stmt.getId(), stmt.getComment());
|
||||
//счет оказался биржевым, и удалось найти счет агента по комментарию
|
||||
anltLink.ifPresent(pair -> {
|
||||
log.debug("stmt.id={} comment={} is anlt, loaded account.id={}/companyId={}",
|
||||
stmt.getId(), stmt.getComment(), pair.getSecond().getId(), pair.getFirst().getId());
|
||||
createRegistryIfNeeded.accept(new StmtCmpAcc(stmt, anltLink.get().getFirst(), anltLink.get().getSecond()));
|
||||
});
|
||||
//счет оказался биржевым, но не знаем кто адресат, заполняем DMAU
|
||||
if (anltLink.isEmpty()) {
|
||||
log.debug("stmt.id={} comment={} account not found. Create DMAU registry", stmt.getId(), stmt.getComment());
|
||||
Optional<Registry> dmau = RegistrySearch.builder(registryImdg)
|
||||
.rgsCode(RegistryTradingParams.DMAU)
|
||||
.companyId(cmp.getId())
|
||||
.accountId(acc.getId())
|
||||
.accountType(AccountType.Anlt)
|
||||
.find();
|
||||
dmau.ifPresentOrElse(rgs -> {
|
||||
log.debug("stmt.id={} DMAU.id={} found, updating", stmt.getId(), rgs.getId());
|
||||
updateDmauReg(stmt, rgs);
|
||||
registryImdg.update(rgs);
|
||||
}, () -> {
|
||||
Registry newDmau = RegistryBuilder.builder(imdgProvider)
|
||||
.statement(stmt)
|
||||
.company(cmp)
|
||||
.account(acc)
|
||||
.designation(RegistryDesignation.D)
|
||||
.build();
|
||||
newDmau.setRegistryUnit(RegistryUnit.U.getKey());
|
||||
newDmau.setRegistryCode(RegistryUtil.clearingCode(newDmau));
|
||||
registryImdg.insert(newDmau);
|
||||
log.debug("stmt.id={} created DMAU.id={}", stmt.getId(), newDmau.getId());
|
||||
});
|
||||
//DMAU подразумевает увеличение остатка поля balance и credit registry.code=DMAU
|
||||
}
|
||||
}
|
||||
};
|
||||
statementDeb.map(stmt -> new StmtCmpAcc(stmt, companyDeb, accountDeb)).ifPresent(registersUpdate);
|
||||
statementCred.map(stmt -> new StmtCmpAcc(stmt, companyCred, accountCred)).ifPresent(registersUpdate);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean accountIsAnlt(Account account) {
|
||||
if (account == null) return false;
|
||||
boolean anlt = AccountType.Anlt.getKey().equals(account.getAccountType());
|
||||
log.debug("account.id={} type {} is anlt={}", account.getId(), account.getAccountType(), anlt);
|
||||
return anlt;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface AnltLogger {
|
||||
void log(IEnumId subject, Object... args);
|
||||
}
|
||||
|
||||
private Optional<Pair<Company, Account>> loadByAnlt(Long statementId, String comment) {
|
||||
String commentTcrStripped = getTkrCodeFromComment(comment);
|
||||
AnltLogger localLogger = (subject, args) -> log.debug("stmt.id={} comment='{}' error: {}", statementId, commentTcrStripped, messageResolver.resolve(new EnumMessage(subject, args)));
|
||||
if (commentTcrStripped == null) {
|
||||
localLogger.log(ClearingError.AccountNotFound, "comment not contain TCR");
|
||||
return Optional.empty();
|
||||
}
|
||||
ImdgPredicateBuilder pb = tradingClearingRegistryImdg.predicateBuilder();
|
||||
ImdgPredicate tcrPredicate = pb.and(
|
||||
pb.equals("code", commentTcrStripped),
|
||||
pb.equals("status", ServiceStatus.Active.getKey())
|
||||
);
|
||||
|
||||
TradingClearingRegistry tcr = tradingClearingRegistryImdg.getSingleObjectByPredicate(tcrPredicate);
|
||||
if (tcr == null) {
|
||||
localLogger.log(ClearingError.TCRegistryNotFound, commentTcrStripped);
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
if (tcr.getMoneyAccountId() == null) {
|
||||
localLogger.log(ClearingError.WrongField, "moneyAccountId");
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
Account infoAcc = accountImdg.getSingleObjectByID(tcr.getMoneyAccountId());
|
||||
if (infoAcc == null) {
|
||||
localLogger.log(ClearingError.AccountNotFound, "moneyAccountId");
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
if (!infoAcc.getAccountType().equals(AccountType.Info.getKey())) {
|
||||
localLogger.log(ClearingError.AccountNotFound, "accountType");
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
Company company = companyImdg.getSingleObjectByID(tcr.getCompanyId());
|
||||
if (company == null) {
|
||||
localLogger.log(ClearingError.CompanyNotFoundB, tcr.getCompanyId());
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.of(new Pair<>(company, infoAcc));
|
||||
}
|
||||
|
||||
private Registry copyRegB(Registry rgs) {
|
||||
Registry rgsB = rgs.clone();
|
||||
rgsB.setRegistryUnit(RegistryUnit.B.getKey());
|
||||
|
|
@ -333,6 +458,7 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
|
|||
statement.setSenderId(Sender.Prc.getId());
|
||||
statement.setStatementType(StatementType.incr.getKey());
|
||||
statement.setContract(getContractFromSpecif(sdf57.getSpecif()));
|
||||
statement.setComment(sdf57.getSpecif());
|
||||
statement.setAccountId(accountDeb.getId());
|
||||
|
||||
Currency currency = currencyImdg.getSingleObjectByFieldValues(Map.of("currencyCode", "RUB"));
|
||||
|
|
@ -371,6 +497,10 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
|
|||
rgs.setDebit(statement.getAmount().negate());
|
||||
}
|
||||
}
|
||||
AccountType accType = IEnumKey.getEnumByKey(AccountType.class, rgs.getAccountType());
|
||||
if (!AccountType.Info.equals(accType)) {
|
||||
rgs.setDiffBalance(safeBD(rgs.getBalance()).subtract(safeBD(rgs.getCheckBalance())));
|
||||
}
|
||||
rgs.setDiffBalance(safeBD(rgs.getBalance()).subtract(safeBD(rgs.getCheckBalance())));
|
||||
rgs.setBalanceDimension(BalanceDimension.MONY.getKey()); //fixme ! смотри описание и ссылка на начало html'ки
|
||||
}
|
||||
|
|
@ -387,7 +517,25 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
|
|||
r.setDebit(safeBD(r.getDebit()).add(safeBD(s.getAmount())));
|
||||
}
|
||||
}
|
||||
r.setDiffBalance(safeBD(r.getBalance()).subtract(safeBD(r.getCheckBalance())));
|
||||
AccountType accType = IEnumKey.getEnumByKey(AccountType.class, r.getAccountType());
|
||||
if (!AccountType.Info.equals(accType)) {
|
||||
r.setDiffBalance(safeBD(r.getBalance()).subtract(safeBD(r.getCheckBalance())));
|
||||
}
|
||||
r.setUpdated(Instant.now());
|
||||
}
|
||||
|
||||
private void updateDmauReg(Statement s, Registry r) {
|
||||
InOutDirection direction = IEnumKey.getEnumByKey(InOutDirection.class, s.getInOutDirection());
|
||||
switch (direction) {
|
||||
case in -> {
|
||||
r.setBalance(safeBD(r.getBalance()).add(safeBD(s.getAmount())));
|
||||
r.setCredit(safeBD(r.getCredit()).add(safeBD(s.getAmount())));
|
||||
}
|
||||
case out -> {
|
||||
r.setBalance(safeBD(r.getBalance()).subtract(safeBD(s.getAmount())));
|
||||
r.setDebit(safeBD(r.getDebit()).add(safeBD(s.getAmount())));
|
||||
}
|
||||
}
|
||||
r.setUpdated(Instant.now());
|
||||
}
|
||||
|
||||
|
|
@ -415,6 +563,61 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
|
|||
return Optional.ofNullable(registryImdg.getSingleObjectByPredicate(rgstrPredicate));
|
||||
}
|
||||
|
||||
private static class RegistrySearch {
|
||||
private final ImdgPredicateBuilder pb;
|
||||
private final Imdg<Registry> registryImdg;
|
||||
private ImdgPredicate predicate;
|
||||
|
||||
private RegistrySearch(Imdg<Registry> registryImdg) {
|
||||
this.registryImdg = registryImdg;
|
||||
this.pb = registryImdg.predicateBuilder();
|
||||
}
|
||||
|
||||
private static RegistrySearch builder(Imdg<Registry> registryImdg) {
|
||||
RegistrySearch registrySearch = new RegistrySearch(registryImdg);
|
||||
registrySearch.predicate = registrySearch.pb.alwaysTrue();
|
||||
return registrySearch;
|
||||
}
|
||||
|
||||
private RegistrySearch rgsCode(RegistryTradingParams rgsCode) {
|
||||
String sql = RegistryCodeSqlBuilder.getInstance(rgsCode).build();
|
||||
predicate = pb.and(predicate, pb.sql(sql));
|
||||
return this;
|
||||
}
|
||||
|
||||
private RegistrySearch companyId(Long companyId) {
|
||||
predicate = pb.and(predicate, pb.equals("companyId", companyId));
|
||||
return this;
|
||||
}
|
||||
|
||||
private RegistrySearch accountType(AccountType accountType) {
|
||||
predicate = pb.and(predicate, pb.equals("accountType", accountType.getKey()));
|
||||
return this;
|
||||
}
|
||||
|
||||
private RegistrySearch accountId(Long accountId) {
|
||||
predicate = pb.and(predicate, pb.equals("accountId", accountId));
|
||||
return this;
|
||||
}
|
||||
|
||||
private RegistrySearch contract(String contract) {
|
||||
predicate = pb.and(predicate, pb.equals("contract", contract));
|
||||
return this;
|
||||
}
|
||||
|
||||
private RegistrySearch status() {
|
||||
predicate = pb.and(predicate, pb.or(
|
||||
pb.equals("registryStatus", RegistryStatus.PROC.getKey()),
|
||||
pb.equals("registryStatus", RegistryStatus.MNG.getKey())
|
||||
));
|
||||
return this;
|
||||
}
|
||||
|
||||
private Optional<Registry> find() {
|
||||
return Optional.ofNullable(registryImdg.getSingleObjectByPredicate(predicate));
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<Registry> findRegByUnit(Statement s, Registry registry, RegistryUnit unit) {
|
||||
RegistryTradingParams p = new RegistryTradingParams(
|
||||
IEnumKey.getEnumByKey(RegistryDesignation.class, registry.getRegistryDesignation()),
|
||||
|
|
@ -445,6 +648,19 @@ public class Sdf57Executor extends AbstractExecutor<SDf57> {
|
|||
return LocalDate.parse(payDate, payDateFormatter);
|
||||
}
|
||||
|
||||
private static String getTkrCodeFromComment(String comment) {
|
||||
if (comment == null) {
|
||||
return null;
|
||||
}
|
||||
comment = comment.toUpperCase();
|
||||
int tcrIndex = comment.indexOf("ТКР");
|
||||
if (tcrIndex == -1) {
|
||||
return null;
|
||||
}
|
||||
comment = comment.substring(tcrIndex + 3);
|
||||
return comment.replaceAll("\\s+", "");
|
||||
}
|
||||
|
||||
private String getContractFromSpecif(String specif) {
|
||||
if (specif == null) {
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ public record RegistryTradingParams(RegistryDesignation registryDesignation,
|
|||
public final static RegistryTradingParams AS__;
|
||||
public final static RegistryTradingParams CM__;
|
||||
public final static RegistryTradingParams LM__;
|
||||
public final static RegistryTradingParams DMAU;
|
||||
|
||||
static {
|
||||
OS_T = new RegistryTradingParams(RegistryDesignation.O,
|
||||
|
|
@ -127,6 +128,10 @@ public record RegistryTradingParams(RegistryDesignation registryDesignation,
|
|||
RegistryInstrumentType.M,
|
||||
null,
|
||||
null);
|
||||
DMAU = new RegistryTradingParams(RegistryDesignation.D,
|
||||
RegistryInstrumentType.M,
|
||||
RegistryCapacity.A,
|
||||
RegistryUnit.U);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ public enum RegistryUnit implements IEnumKey {
|
|||
F("F"),
|
||||
B("B"),
|
||||
X("X"),
|
||||
U("U"),
|
||||
;
|
||||
|
||||
private final String key;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue