Sdf01Executor
This commit is contained in:
parent
389eb7d9fd
commit
f22dad9a20
10 changed files with 551 additions and 72 deletions
|
|
@ -3,8 +3,8 @@ package ru.spcex.clearing.config;
|
|||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import ru.spcex.clearing.service.executors.AbstractExecutor;
|
||||
import ru.spcex.clearing.service.executors.Sdf01Executor;
|
||||
import ru.spcex.clearing.service.executors.Sdf57Executor;
|
||||
import ru.spcex.clearing.service.executors.SdfLegacyExecutor;
|
||||
import ru.spcex.platform.enumeration.SdfTable;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
|
@ -14,7 +14,7 @@ import java.util.Map;
|
|||
public class SdfExecutorsConfig {
|
||||
|
||||
@Bean("sdfExecutors")
|
||||
public Map<SdfTable, AbstractExecutor<?>> executorsMap(Sdf01Executor sdf01Executor,
|
||||
public Map<SdfTable, AbstractExecutor<?>> executorsMap(SdfLegacyExecutor sdf01Executor,
|
||||
Sdf57Executor sdf57Executor) {
|
||||
Map<SdfTable, AbstractExecutor<?>> executors = new HashMap<>();
|
||||
executors.put(SdfTable.SDF_01, sdf01Executor);
|
||||
|
|
|
|||
|
|
@ -140,4 +140,22 @@ public class ValidationConfig {
|
|||
);
|
||||
};
|
||||
}
|
||||
|
||||
@Bean("sdf01ValidatorNew")
|
||||
public Function<SDf01, IValidator> sdf01ValidatorNew() {
|
||||
return sDf01 -> {
|
||||
ImdgValidationContext<SDf01> context = new ImdgValidationContext<>();
|
||||
context.setValidatedObject(sDf01);
|
||||
Consumer<String> addImdg = (s) -> context.addImdg(s, getImdg(s));
|
||||
addImdg.accept(IMDGDistributedNames.Map_Account);
|
||||
addImdg.accept(IMDGDistributedNames.Map_Company);
|
||||
return new ValidatorImpl<>(context,
|
||||
Sdf01NewValidationRule.CompanyPresent,
|
||||
Sdf01NewValidationRule.AccountType,
|
||||
Sdf01NewValidationRule.AccountPresent,
|
||||
Sdf01NewValidationRule.CurrencyCode,
|
||||
Sdf01NewValidationRule.DatIsCurrentDt
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,11 @@ public enum ClearingError implements IErrorEnumId {
|
|||
ClearingUnavailableForCompany(5421L),
|
||||
InsecurityObligation(5422L),
|
||||
NewDealsNotFound(5423L),
|
||||
//ошибки "перенесенные" из balance-service
|
||||
CompanyNotFoundB(5211L),
|
||||
CurrencyNotFound(5213L),
|
||||
OperationCanBeRunForTodayOnly(5214L),
|
||||
AccountWrongType(5216L),
|
||||
;
|
||||
private final Long id;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import ru.spcex.platform.utils.enumeration.IErrorEnumId;
|
|||
public enum ClearingErrorInternal implements IErrorEnumId {
|
||||
ClearingNotAllowed(1L),
|
||||
AccountNotActive(5415L),
|
||||
AccountNotPresent(3L),
|
||||
CompanyNotActive(5411L),
|
||||
FinancialObligationNotSatisfied(4L),
|
||||
SessionGeneralError(2L);
|
||||
|
|
|
|||
|
|
@ -2,69 +2,88 @@ package ru.spcex.clearing.service.executors;
|
|||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.clearing.classes.statics.data.account.Account;
|
||||
import ru.clearing.classes.statics.data.account.AccountBalance;
|
||||
import ru.clearing.classes.statics.data.account.ClearingAccount;
|
||||
import ru.clearing.classes.statics.data.company.Company;
|
||||
import ru.clearing.classes.statics.data.misc.Currency;
|
||||
import ru.clearing.classes.statics.data.registry.Registry;
|
||||
import ru.clearing.classes.statics.data.registry.TradingClearingRegistry;
|
||||
import ru.clearing.classes.statics.data.sdf.SDf01;
|
||||
import ru.clearing.classes.statics.data.sdf.SDf02;
|
||||
import ru.clearing.classes.statics.data.security.Security;
|
||||
import ru.clearing.classes.statics.data.statement.Statement;
|
||||
import ru.spcex.clearing.error.ClearingError;
|
||||
import ru.spcex.clearing.error.ClearingErrorInternal;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.Consts;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountSdfRequestPart;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.balance.ExportToFileRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.clearing.ContinueSessionBnRequest;
|
||||
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
|
||||
import ru.spcex.clearing.service.LoggingService;
|
||||
import ru.spcex.clearing.service.model.Result;
|
||||
import ru.spcex.clearing.service.validation.ValidationStored;
|
||||
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.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.enumeration.EnumMessage;
|
||||
import ru.spcex.platform.utils.enumeration.IEnumKey;
|
||||
import ru.spcex.platform.utils.enumeration.IMessageResolver;
|
||||
import ru.spcex.platform.utils.number.BigDecimalUtil;
|
||||
import ru.spcex.platform.utils.validation.IValidator;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Service
|
||||
public class Sdf01Executor extends AbstractExecutor<SDf01> {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private final static DateTimeFormatter datFormatter = DateTimeFormatter.ofPattern("dd.MM.yy");
|
||||
private final Imdg<Statement> statementImdg;
|
||||
private final Imdg<Registry> registryImdg;
|
||||
private final Function<SDf01, IValidator> sDf01Validator;
|
||||
private final LoggingService errorLogger;
|
||||
private final Imdg<SDf02> sdf02Imdg;
|
||||
private final ImdgProvider imdgProvider;
|
||||
private final IMessageResolver errorResolver;
|
||||
private final Imdg<AccountBalance> accountBalanceImdg;
|
||||
private final Imdg<ClearingAccount> clearingAccountImdg;
|
||||
private final Imdg<TradingClearingRegistry> tradingClearingRegistryImdg;
|
||||
private final Imdg<Security> securityImdg;
|
||||
private final Imdg<Currency> currencyImdg;
|
||||
private final Imdg<SDf02> sdf02Imdg;
|
||||
private final IMessageResolver messageResolver;
|
||||
|
||||
public Sdf01Executor(Function<SDf01, IValidator> sDf01Validator,
|
||||
public Sdf01Executor(@Qualifier("sdf01ValidatorNew") Function<SDf01, IValidator> sDf01Validator,
|
||||
LoggingService errorLogger,
|
||||
ImdgProvider imdgProvider,
|
||||
IMessageResolver errorResolver) {
|
||||
IMessageResolver errorResolver, IMessageResolver messageResolver) {
|
||||
this.statementImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class);
|
||||
this.sdf02Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf02, SDf02.class);
|
||||
this.accountBalanceImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_AccountBalance, AccountBalance.class);
|
||||
;
|
||||
this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
|
||||
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.sDf01Validator = sDf01Validator;
|
||||
this.errorLogger = errorLogger;
|
||||
this.imdgProvider = imdgProvider;
|
||||
this.errorResolver = errorResolver;
|
||||
this.messageResolver = messageResolver;
|
||||
this.securityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Security, Security.class);
|
||||
this.sdf02Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf02, SDf02.class);
|
||||
}
|
||||
|
||||
//todo доделать контроль sdf01 и sdf57
|
||||
|
||||
@Override
|
||||
public String exportTableName() {
|
||||
return "DF-02";
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -74,6 +93,10 @@ public class Sdf01Executor extends AbstractExecutor<SDf01> {
|
|||
|
||||
@Override
|
||||
public void sendCommand(KafkaSender kafkaSender, Result result) {
|
||||
ContinueSessionBnRequest continueSessionBn = new ContinueSessionBnRequest();
|
||||
continueSessionBn.setGenerationId(result.getGenerationId());
|
||||
kafkaSender.sendRequestToQueue(Consts.CONTINUE_SESSION_BN_FIRST_PART, continueSessionBn);
|
||||
|
||||
ExportToFileRequest exportRequest = new ExportToFileRequest();
|
||||
exportRequest.setSdfGroupId(result.getGenerationId());
|
||||
exportRequest.setNameOfTable(exportTableName());
|
||||
|
|
@ -87,76 +110,85 @@ public class Sdf01Executor extends AbstractExecutor<SDf01> {
|
|||
for (SDf01 sdf01 : sdf) {
|
||||
IValidator validator = sDf01Validator.apply(sdf01);
|
||||
Optional<EnumMessage> error = validator.tillFirstError();
|
||||
Company company = validator.getStored(ValidationStored.Company);
|
||||
Company company = validator.getStored(ValidationStored.Sdf01Company);
|
||||
Account account = validator.getStored(ValidationStored.Sdf01Account);
|
||||
if (statementRequest.getAccountCreationResults().size() == 0
|
||||
&& ClearingError.AccountNotPresent.equals(error.map(EnumMessage::getSubject).orElse(null))) {
|
||||
&& ClearingErrorInternal.AccountNotPresent.equals(error.map(EnumMessage::getSubject).orElse(null))) {
|
||||
//на данном шаге company существует -> getId ok
|
||||
//формируем пакетный запрос на добавление account
|
||||
//ответ придет в этот же метод, process
|
||||
result.getAccountRequests().add(createAccountRequestPart(sdf01.getId(), sdf01.getAccount(), company.getId()));
|
||||
log.info("account {} for sdf01.id={} not found - send request for creation", sdf01.getAccount(), sdf01.getId());
|
||||
continue;
|
||||
} else if (ClearingError.AccountNotPresent.equals(error.map(EnumMessage::getSubject).orElse(null))) {
|
||||
} else if (ClearingErrorInternal.AccountNotPresent.equals(error.map(EnumMessage::getSubject).orElse(null))) {
|
||||
log.error("fatal error: resumed processing after generating accounts, but no account found for sdf01.id={}", sdf01.getId());
|
||||
}
|
||||
if (error.isPresent()) {
|
||||
errorLogger.logError("sdf01.id={}", error.get(), sdf01.getId());
|
||||
log.error("sdf01.id={} error: {}", sdf01.getId(), messageResolver.resolve(error.get()));
|
||||
//fixme инициировать = команда для другого сервиса? sdf02Imdg.insert(createErrorSdf02(sdf01, error.get(), generationIdForGroup));
|
||||
sdf02Imdg.insert(createErrorSdf02(sdf01, error.get(), generationIdForGroup));
|
||||
continue;
|
||||
}
|
||||
Statement statement = statementImdg.getSingleObjectByFieldValues(Map.of("account", sdf01.getAccount()));
|
||||
if (statement == null) {
|
||||
statement = createFlow(sdf01,
|
||||
company,
|
||||
validator.getStored(ValidationStored.Account));
|
||||
} else {
|
||||
updateFlow(statement, sdf01,
|
||||
validator.getStored(ValidationStored.Account));
|
||||
}
|
||||
SDf02 sdf02New = createSuccessSdf02(sdf01, generationIdForGroup);
|
||||
|
||||
Statement stmt = createSdf01Statement(sdf01, company, account);
|
||||
|
||||
SDf02 sdf02New = createSuccessSdf02(sdf01, generationIdForGroup); //fixme тоже мб убрать
|
||||
sdf02Imdg.insert(sdf02New);
|
||||
statement.setOutSDfId(sdf02New.getId());
|
||||
// AccountResult accountResult = accountBalanceService.createAccountBalance(statement.getAddresseeId(), statement.getAccountId(), statement.getAmount(),
|
||||
// null/*statement.getCashMovementCurrencyCode()*/);
|
||||
// if (accountResult.getError() != null) {
|
||||
// statement.setErrorCodeId(accountResult.getError().getSubject().getId());
|
||||
// todo statement.setErrorText(errorResolver.resolve(accountResult.getError()));
|
||||
// } else {
|
||||
// accountBalanceImdg.insert(accountResult.getAccount()); //insert == update?
|
||||
// statement.setOperationStatus(OperationStatus.Executed.getKey());
|
||||
// }
|
||||
statementImdg.update(statement);
|
||||
stmt.setOutSDfId(sdf02New.getId());
|
||||
statementImdg.update(stmt);
|
||||
|
||||
Optional<EnumMessage> err = validateActiveness(company, account);
|
||||
if (err.isEmpty()) {
|
||||
Consumer<Registry> update = rgs -> {
|
||||
updateReg(stmt, rgs);
|
||||
registryImdg.update(rgs);
|
||||
};
|
||||
Consumer<RegistryDesignation> create = (dsgn) -> {
|
||||
Registry registry = createRegistryByStatement(stmt, company, account, dsgn);
|
||||
Registry registryF = registry.clone();
|
||||
registryF.setRegistryUnit(RegistryUnit.F.getKey());
|
||||
registryF.setRegistryCode(RegistryUtil.clearingCode(registryF));
|
||||
registryF.setId(imdgProvider.getImdgIdGenerator().nextId());
|
||||
Registry registryB = registry.clone();
|
||||
registryB.setRegistryUnit(RegistryUnit.B.getKey());
|
||||
registryB.setRegistryCode(RegistryUtil.clearingCode(registryB));
|
||||
registryB.setId(imdgProvider.getImdgIdGenerator().nextId());
|
||||
registryImdg.insert(registry);
|
||||
registryImdg.insert(registryF);
|
||||
registryImdg.insert(registryB);
|
||||
};
|
||||
|
||||
findReg(stmt, RegistryInstrumentType.M).ifPresentOrElse(update, () -> create.accept(RegistryDesignation.A));
|
||||
findReg(stmt, RegistryInstrumentType.S).ifPresentOrElse(update, () -> create.accept(RegistryDesignation.D));
|
||||
stmt.setOperationStatus(OperationStatus.Executed.getKey());
|
||||
} else {
|
||||
stmt.setErrorCodeId(err.get().getSubject().getId()); // fixme ErrorText insert
|
||||
stmt.setOperationStatus(OperationStatus.Rejected.getKey());
|
||||
statementImdg.update(stmt);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Statement createFlow(SDf01 sdf01, Company company, Account account) {
|
||||
Statement statement = new Statement();
|
||||
statement.setAddresseeId(company.getId());
|
||||
statement.setSenderId(Sender.Prc.getId());
|
||||
statement.setCreated(Instant.now());
|
||||
statement.setClearingDate(LocalDate.now());
|
||||
statement.setStatementType(StatementType.full.getKey());
|
||||
statement.setAccountId(account.getId());
|
||||
statement.setAccount(sdf01.getAccount());
|
||||
statement.setInOutDirection(InOutDirection.in.getKey());
|
||||
statement.setSettlementDate(LocalDate.parse(sdf01.getDat(), datFormatter));
|
||||
statement.setAmount(BigDecimalUtil.parse(sdf01.getRemainder()));
|
||||
statement.setOperationStatus(OperationStatus.Pending.getKey());
|
||||
statement.setInSDfId(sdf01.getId());
|
||||
statement.setInOutSDfType(InOutSDfType.type1.getKey());
|
||||
statementImdg.insert(statement);
|
||||
return statement;
|
||||
}
|
||||
|
||||
private void updateFlow(Statement statement, SDf01 sdf01, Account account) {
|
||||
statement.setUpdated(Instant.now());
|
||||
statement.setAccountId(account.getId());
|
||||
statement.setAccount(sdf01.getAccount());
|
||||
statement.setInOutDirection(InOutDirection.in.getKey());
|
||||
statement.setSettlementDate(LocalDate.parse(sdf01.getDat(), datFormatter));
|
||||
statement.setAmount(BigDecimalUtil.parse(sdf01.getRemainder()));
|
||||
statementImdg.update(statement);
|
||||
private final static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yy");
|
||||
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());
|
||||
stmt.setAccount(account.getAccount());
|
||||
stmt.setInOutDirection(InOutDirection.in.getKey());
|
||||
stmt.setSettlementDate(LocalDate.parse(sdf01.getDat(), formatter));
|
||||
if (sdf01.getRemainder() != null) {
|
||||
stmt.setAmount(new BigDecimal(sdf01.getRemainder()));
|
||||
}
|
||||
stmt.setOperationStatus(OperationStatus.Pending.getKey());
|
||||
stmt.setInSDfId(sdf01.getId());
|
||||
stmt.setInOutSDfType(InOutSDfType.type1.getKey());
|
||||
stmt.setCreated(Instant.now());
|
||||
return stmt;
|
||||
}
|
||||
|
||||
private AccountSdfRequestPart createAccountRequestPart(Long sdf01Id, String account, Long companyId) {
|
||||
|
|
@ -168,7 +200,6 @@ public class Sdf01Executor extends AbstractExecutor<SDf01> {
|
|||
return req;
|
||||
}
|
||||
|
||||
|
||||
private SDf02 createErrorSdf02(SDf01 sdf01, EnumMessage error, Long generationIdForGroup) {
|
||||
SDf02 sDf02 = new SDf02();
|
||||
sDf02.setCurr_code(sdf01.getCurr_code());
|
||||
|
|
@ -211,4 +242,100 @@ public class Sdf01Executor extends AbstractExecutor<SDf01> {
|
|||
sDf02.setResult("OK!");
|
||||
return sDf02;
|
||||
}
|
||||
|
||||
|
||||
private Optional<EnumMessage> validateActiveness(Company company, Account account) {
|
||||
if (!WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus())) {
|
||||
return Optional.of(new EnumMessage(ClearingError.CompanyNotActive, company.getId()));
|
||||
}
|
||||
if (!WorkflowStatus.Active.equalsByKey(account.getStatus())) {
|
||||
return Optional.of(new EnumMessage(ClearingError.AccountNotActive, account.getId()));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private Registry createRegistryByStatement(Statement statement, Company company, Account account, RegistryDesignation designation) {
|
||||
Registry rgs = new Registry();
|
||||
rgs.setCompanyId(statement.getAddresseeId());
|
||||
rgs.setTradingCode(company.getTradingCode());
|
||||
rgs.setClearingCode(company.getClearingCode());
|
||||
rgs.setShortName(company.getShortName());
|
||||
rgs.setFullName(company.getFullName());
|
||||
rgs.setAccountId(account.getId());
|
||||
rgs.setAccountType(account.getAccountType());
|
||||
rgs.setAccount(account.getAccount());
|
||||
rgs.setRegistryDesignation(designation.getKey());
|
||||
rgs.setRegistryInstrumentType(RegistryInstrumentType.M.getKey());
|
||||
|
||||
ClearingAccount accountForStatement = clearingAccountImdg.getSingleObjectByID(statement.getAccountId());
|
||||
if (accountForStatement != null) {
|
||||
rgs.setRegistryCapacity(accountForStatement.getClearingAccountType());
|
||||
}
|
||||
rgs.setRegistryUnit(RegistryUnit.T.getKey());
|
||||
rgs.setRegistryCode(RegistryUtil.clearingCode(rgs));
|
||||
|
||||
Collection<TradingClearingRegistry> tcrsByAccount = tradingClearingRegistryImdg.getCollectionObjectsByFieldValues(Map.of(
|
||||
"moneyAccountId", statement.getAccountId()
|
||||
));
|
||||
if (!tcrsByAccount.isEmpty()) {
|
||||
TradingClearingRegistry tcr = tcrsByAccount.iterator().next();
|
||||
rgs.setTradingClearingRegistryId(tcr.getId());
|
||||
rgs.setTradingClearingRegistry(tcr.getCode());
|
||||
}
|
||||
|
||||
rgs.setRegistryStatus(RegistryStatus.PROC.getKey());
|
||||
rgs.setSecurityId(statement.getSecurityId());
|
||||
if (statement.getSecurityId() != null) {
|
||||
Security security = securityImdg.getSingleObjectByID(statement.getSecurityId());
|
||||
if (security != null) {
|
||||
rgs.setSecuritySymbol(security.getSecuritySymbol());
|
||||
}
|
||||
}
|
||||
InOutDirection inOutDirection = IEnumKey.getEnumByKey(InOutDirection.class, statement.getInOutDirection());
|
||||
//считаю balance при создании нулевым и исхожу из этого
|
||||
//При добавлении (на базе изменения statement по sDf57):
|
||||
//Если значение statement.inOutDirection=IN, то:
|
||||
//= текущее значение registry.balance + statement.amount
|
||||
//
|
||||
//Если значение statement.inOutDirection=OUT, то:
|
||||
//= текущее значение registry.balance - statement.amount
|
||||
switch (inOutDirection) {
|
||||
case in -> rgs.setBalance(statement.getAmount());
|
||||
case out -> rgs.setBalance(statement.getAmount().negate());
|
||||
}
|
||||
rgs.setBalanceDimension(BalanceDimension.MONY.getKey()); //fixme ! смотри описание и ссылка на начало html'ки
|
||||
//fixme !rgs.setSettlementCode();
|
||||
rgs.setTradingDate(statement.getSettlementDate()); //fixme ! today ?
|
||||
rgs.setClearingDate(LocalDate.now());
|
||||
//fixme rgs.setRefundDate();
|
||||
//fixme rgs.setValueDate();
|
||||
rgs.setContract(statement.getContract());
|
||||
//создается на базе stmt, companyCred, accountDeb
|
||||
rgs.setCounterPartyId(statement.getAddresseeId());
|
||||
rgs.setCreated(Instant.now());
|
||||
return rgs;
|
||||
}
|
||||
|
||||
private void updateReg(Statement s, Registry r) {
|
||||
InOutDirection direction = IEnumKey.getEnumByKey(InOutDirection.class, s.getInOutDirection());
|
||||
switch (direction) {
|
||||
case in -> r.setBalance(r.getBalance().add(s.getAmount()));
|
||||
case out -> r.setBalance(r.getBalance().subtract(s.getAmount()));
|
||||
}
|
||||
r.setUpdated(Instant.now());
|
||||
}
|
||||
|
||||
private Optional<Registry> findReg(Statement s, RegistryInstrumentType registryInstrumentType) {
|
||||
RegistryTradingParams p = new RegistryTradingParams(
|
||||
RegistryDesignation.A, registryInstrumentType, RegistryCapacity.A, RegistryUnit.T
|
||||
);
|
||||
String sql = RegistryCodeSqlBuilder.getInstance(p).build();
|
||||
ImdgPredicateBuilder pb = registryImdg.predicateBuilder();
|
||||
ImdgPredicate rgstrPredicate = pb.and(pb.sql(sql),
|
||||
pb.sql(sql),
|
||||
pb.equals("accountId", s.getAccountId()),
|
||||
pb.equals("companyId", s.getAddresseeId())
|
||||
);
|
||||
return Optional.ofNullable(registryImdg.getSingleObjectByPredicate(rgstrPredicate));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,215 @@
|
|||
package ru.spcex.clearing.service.executors;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.clearing.classes.statics.data.account.Account;
|
||||
import ru.clearing.classes.statics.data.account.AccountBalance;
|
||||
import ru.clearing.classes.statics.data.company.Company;
|
||||
import ru.clearing.classes.statics.data.sdf.SDf01;
|
||||
import ru.clearing.classes.statics.data.sdf.SDf02;
|
||||
import ru.clearing.classes.statics.data.statement.Statement;
|
||||
import ru.spcex.clearing.error.ClearingError;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.Consts;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountSdfRequestPart;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.balance.ExportToFileRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest;
|
||||
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
|
||||
import ru.spcex.clearing.service.LoggingService;
|
||||
import ru.spcex.clearing.service.model.Result;
|
||||
import ru.spcex.clearing.service.validation.ValidationStored;
|
||||
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.EnumMessage;
|
||||
import ru.spcex.platform.utils.enumeration.IMessageResolver;
|
||||
import ru.spcex.platform.utils.number.BigDecimalUtil;
|
||||
import ru.spcex.platform.utils.validation.IValidator;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
@Service
|
||||
public class SdfLegacyExecutor extends AbstractExecutor<SDf01> {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private final static DateTimeFormatter datFormatter = DateTimeFormatter.ofPattern("dd.MM.yy");
|
||||
private final Imdg<Statement> statementImdg;
|
||||
private final Function<SDf01, IValidator> sDf01Validator;
|
||||
private final LoggingService errorLogger;
|
||||
private final Imdg<SDf02> sdf02Imdg;
|
||||
private final ImdgProvider imdgProvider;
|
||||
private final IMessageResolver errorResolver;
|
||||
private final Imdg<AccountBalance> accountBalanceImdg;
|
||||
|
||||
public SdfLegacyExecutor(@Qualifier("sdf01Validator") Function<SDf01, IValidator> sDf01Validator,
|
||||
LoggingService errorLogger,
|
||||
ImdgProvider imdgProvider,
|
||||
IMessageResolver errorResolver) {
|
||||
this.statementImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class);
|
||||
this.sdf02Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf02, SDf02.class);
|
||||
this.accountBalanceImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_AccountBalance, AccountBalance.class);
|
||||
;
|
||||
this.sDf01Validator = sDf01Validator;
|
||||
this.errorLogger = errorLogger;
|
||||
this.imdgProvider = imdgProvider;
|
||||
this.errorResolver = errorResolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String exportTableName() {
|
||||
return "DF-02";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNeedToSendCommand() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendCommand(KafkaSender kafkaSender, Result result) {
|
||||
ExportToFileRequest exportRequest = new ExportToFileRequest();
|
||||
exportRequest.setSdfGroupId(result.getGenerationId());
|
||||
exportRequest.setNameOfTable(exportTableName());
|
||||
kafkaSender.sendRequestToQueue(Consts.EXPORT_PROCESS, exportRequest);
|
||||
}
|
||||
|
||||
public Result execute(Collection<SDf01> sdf, StatementRequest statementRequest) {
|
||||
Result result = new Result();
|
||||
Long generationIdForGroup = imdgProvider.getImdgIdGenerator().nextId();
|
||||
result.setGenerationId(generationIdForGroup);
|
||||
for (SDf01 sdf01 : sdf) {
|
||||
IValidator validator = sDf01Validator.apply(sdf01);
|
||||
Optional<EnumMessage> error = validator.tillFirstError();
|
||||
Company company = validator.getStored(ValidationStored.Company);
|
||||
if (statementRequest.getAccountCreationResults().size() == 0
|
||||
&& ClearingError.AccountNotPresent.equals(error.map(EnumMessage::getSubject).orElse(null))) {
|
||||
//на данном шаге company существует -> getId ok
|
||||
//формируем пакетный запрос на добавление account
|
||||
//ответ придет в этот же метод, process
|
||||
result.getAccountRequests().add(createAccountRequestPart(sdf01.getId(), sdf01.getAccount(), company.getId()));
|
||||
log.info("account {} for sdf01.id={} not found - send request for creation", sdf01.getAccount(), sdf01.getId());
|
||||
continue;
|
||||
} else if (ClearingError.AccountNotPresent.equals(error.map(EnumMessage::getSubject).orElse(null))) {
|
||||
log.error("fatal error: resumed processing after generating accounts, but no account found for sdf01.id={}", sdf01.getId());
|
||||
}
|
||||
if (error.isPresent()) {
|
||||
errorLogger.logError("sdf01.id={}", error.get(), sdf01.getId());
|
||||
sdf02Imdg.insert(createErrorSdf02(sdf01, error.get(), generationIdForGroup));
|
||||
continue;
|
||||
}
|
||||
Statement statement = statementImdg.getSingleObjectByFieldValues(Map.of("account", sdf01.getAccount()));
|
||||
if (statement == null) {
|
||||
statement = createFlow(sdf01,
|
||||
company,
|
||||
validator.getStored(ValidationStored.Account));
|
||||
} else {
|
||||
updateFlow(statement, sdf01,
|
||||
validator.getStored(ValidationStored.Account));
|
||||
}
|
||||
SDf02 sdf02New = createSuccessSdf02(sdf01, generationIdForGroup);
|
||||
sdf02Imdg.insert(sdf02New);
|
||||
statement.setOutSDfId(sdf02New.getId());
|
||||
// AccountResult accountResult = accountBalanceService.createAccountBalance(statement.getAddresseeId(), statement.getAccountId(), statement.getAmount(),
|
||||
// null/*statement.getCashMovementCurrencyCode()*/);
|
||||
// if (accountResult.getError() != null) {
|
||||
// statement.setErrorCodeId(accountResult.getError().getSubject().getId());
|
||||
// todo statement.setErrorText(errorResolver.resolve(accountResult.getError()));
|
||||
// } else {
|
||||
// accountBalanceImdg.insert(accountResult.getAccount()); //insert == update?
|
||||
// statement.setOperationStatus(OperationStatus.Executed.getKey());
|
||||
// }
|
||||
statementImdg.update(statement);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Statement createFlow(SDf01 sdf01, Company company, Account account) {
|
||||
Statement statement = new Statement();
|
||||
statement.setAddresseeId(company.getId());
|
||||
statement.setSenderId(Sender.Prc.getId());
|
||||
statement.setCreated(Instant.now());
|
||||
statement.setClearingDate(LocalDate.now());
|
||||
statement.setStatementType(StatementType.full.getKey());
|
||||
statement.setAccountId(account.getId());
|
||||
statement.setAccount(sdf01.getAccount());
|
||||
statement.setInOutDirection(InOutDirection.in.getKey());
|
||||
statement.setSettlementDate(LocalDate.parse(sdf01.getDat(), datFormatter));
|
||||
statement.setAmount(BigDecimalUtil.parse(sdf01.getRemainder()));
|
||||
statement.setOperationStatus(OperationStatus.Pending.getKey());
|
||||
statement.setInSDfId(sdf01.getId());
|
||||
statement.setInOutSDfType(InOutSDfType.type1.getKey());
|
||||
statementImdg.insert(statement);
|
||||
return statement;
|
||||
}
|
||||
|
||||
private void updateFlow(Statement statement, SDf01 sdf01, Account account) {
|
||||
statement.setUpdated(Instant.now());
|
||||
statement.setAccountId(account.getId());
|
||||
statement.setAccount(sdf01.getAccount());
|
||||
statement.setInOutDirection(InOutDirection.in.getKey());
|
||||
statement.setSettlementDate(LocalDate.parse(sdf01.getDat(), datFormatter));
|
||||
statement.setAmount(BigDecimalUtil.parse(sdf01.getRemainder()));
|
||||
statementImdg.update(statement);
|
||||
}
|
||||
|
||||
private AccountSdfRequestPart createAccountRequestPart(Long sdf01Id, String account, Long companyId) {
|
||||
AccountSdfRequestPart req = new AccountSdfRequestPart();
|
||||
req.setAccount(account);
|
||||
req.setCompanyId(companyId);
|
||||
req.setAccountType(AccountType.Clrn.getKey());
|
||||
req.setSdfId(sdf01Id);
|
||||
return req;
|
||||
}
|
||||
|
||||
|
||||
private SDf02 createErrorSdf02(SDf01 sdf01, EnumMessage error, Long generationIdForGroup) {
|
||||
SDf02 sDf02 = new SDf02();
|
||||
sDf02.setCurr_code(sdf01.getCurr_code());
|
||||
sDf02.setAccount(sdf01.getAccount());
|
||||
sDf02.setRemainder(sdf01.getRemainder());
|
||||
sDf02.setDeal(sdf01.getDeal());
|
||||
sDf02.setAcc_code(sdf01.getAcc_code());
|
||||
sDf02.setDat(sdf01.getDat());
|
||||
sDf02.setMarket(sdf01.getMarket());
|
||||
sDf02.setAcc_name(sdf01.getAcc_name());
|
||||
sDf02.setAcc_type(sdf01.getAcc_type());
|
||||
sDf02.setSumengage(sdf01.getSumengage());
|
||||
sDf02.setSumunblock(sdf01.getSumunblock());
|
||||
sDf02.setFile_type(sdf01.getFile_type());
|
||||
sDf02.setInSDfId(sdf01.getId());
|
||||
String errorId = error.getSubject().getId().toString();
|
||||
sDf02.setResult(errorId.substring(errorId.length() - 3));
|
||||
sDf02.setGenerationId(generationIdForGroup);
|
||||
sDf02.setGenerationTime(Instant.now());
|
||||
return sDf02;
|
||||
}
|
||||
|
||||
private SDf02 createSuccessSdf02(SDf01 sdf01, Long generationIdForGroup) {
|
||||
SDf02 sDf02 = new SDf02();
|
||||
sDf02.setCurr_code(sdf01.getCurr_code());
|
||||
sDf02.setAccount(sdf01.getAccount());
|
||||
sDf02.setRemainder(sdf01.getRemainder());
|
||||
sDf02.setDeal(sdf01.getDeal());
|
||||
sDf02.setAcc_code(sdf01.getAcc_code());
|
||||
sDf02.setDat(sdf01.getDat());
|
||||
sDf02.setMarket(sdf01.getMarket());
|
||||
sDf02.setAcc_name(sdf01.getAcc_name());
|
||||
sDf02.setAcc_type(sdf01.getAcc_type());
|
||||
sDf02.setSumengage(sdf01.getSumengage());
|
||||
sDf02.setSumunblock(sdf01.getSumunblock());
|
||||
sDf02.setFile_type(sdf01.getFile_type());
|
||||
sDf02.setInSDfId(sdf01.getId());
|
||||
sDf02.setGenerationId(generationIdForGroup);
|
||||
sDf02.setGenerationTime(Instant.now());
|
||||
sDf02.setResult("OK!");
|
||||
return sDf02;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
package ru.spcex.clearing.service.validation;
|
||||
|
||||
import ru.clearing.classes.statics.data.account.Account;
|
||||
import ru.clearing.classes.statics.data.company.Company;
|
||||
import ru.clearing.classes.statics.data.sdf.SDf01;
|
||||
import ru.spcex.clearing.error.ClearingError;
|
||||
import ru.spcex.clearing.error.ClearingErrorInternal;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.platform.enumeration.AccType;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
|
||||
import ru.spcex.platform.utils.enumeration.EnumMessage;
|
||||
import ru.spcex.platform.utils.enumeration.IEnumKey;
|
||||
import ru.spcex.platform.utils.text.TextUtil;
|
||||
import ru.spcex.platform.utils.validation.IValidationRule;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Optional;
|
||||
|
||||
public enum Sdf01NewValidationRule implements IValidationRule<ImdgValidationContext<SDf01>> {
|
||||
CompanyPresent() {
|
||||
@Override
|
||||
public Optional<EnumMessage> validate(ImdgValidationContext<SDf01> context) {
|
||||
SDf01 sdf01 = context.getValidatedObject();
|
||||
Imdg<Company> companyImdg = context.obtainMap(IMDGDistributedNames.Map_Company, Company.class);
|
||||
|
||||
if (TextUtil.isEmpty(sdf01.getDeal())) {
|
||||
of(ClearingError.CompanyNotFoundB, sdf01.getDeal());
|
||||
}
|
||||
|
||||
Company company = companyImdg.getSingleObjectBySQL("tradingCode = '" + sdf01.getDeal() + "'");
|
||||
if (company == null) {
|
||||
of(ClearingError.CompanyNotFoundB, sdf01.getDeal());
|
||||
}
|
||||
context.storeObject(ValidationStored.Sdf01Company, company);
|
||||
return empty();
|
||||
}
|
||||
}, AccountType() {
|
||||
@Override
|
||||
public Optional<EnumMessage> validate(ImdgValidationContext<SDf01> context) {
|
||||
SDf01 sdf01 = context.getValidatedObject();
|
||||
|
||||
if (!IEnumKey.contains(sdf01.getAcc_type(), AccType.A, AccType.B)) {
|
||||
of(ClearingError.AccountWrongType, sdf01.getAcc_type());
|
||||
}
|
||||
return empty();
|
||||
}
|
||||
}, AccountPresent() {
|
||||
@Override
|
||||
public Optional<EnumMessage> validate(ImdgValidationContext<SDf01> context) {
|
||||
SDf01 sdf01 = context.getValidatedObject();
|
||||
Imdg<Account> accountImdg = context.obtainMap(IMDGDistributedNames.Map_Account, Account.class);
|
||||
Account acc = accountImdg.getSingleObjectBySQL("account = '" + sdf01.getAccount()
|
||||
+ "' and accountType='" + ru.spcex.platform.enumeration.AccountType.Clrn.getKey() + "'");
|
||||
if (acc == null) {
|
||||
return of (ClearingErrorInternal.AccountNotPresent, sdf01.getAccount());
|
||||
}
|
||||
context.storeObject(ValidationStored.Sdf01Account, acc);
|
||||
return empty();
|
||||
}
|
||||
}, CurrencyCode() {
|
||||
@Override
|
||||
public Optional<EnumMessage> validate(ImdgValidationContext<SDf01> context) {
|
||||
SDf01 sdf01 = context.getValidatedObject();
|
||||
if (!ru.spcex.platform.enumeration.CurrencyCode.RUR.equalsByKey(sdf01.getCurr_code())) {
|
||||
return of(ClearingError.CurrencyNotFound, sdf01.getCurr_code());
|
||||
}
|
||||
return empty();
|
||||
}
|
||||
}, DatIsCurrentDt() {
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yy");
|
||||
@Override
|
||||
public Optional<EnumMessage> validate(ImdgValidationContext<SDf01> context) {
|
||||
SDf01 sdf01 = context.getValidatedObject();
|
||||
LocalDate parse;
|
||||
try {
|
||||
parse = LocalDate.parse(sdf01.getDat(), formatter);
|
||||
} catch (Exception e) {
|
||||
return of(ClearingError.OperationCanBeRunForTodayOnly, sdf01.getDat());
|
||||
}
|
||||
if (!LocalDate.now().equals(parse)) {
|
||||
return of(ClearingError.OperationCanBeRunForTodayOnly, sdf01.getDat());
|
||||
}
|
||||
return empty();
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public String ruleName() {
|
||||
return "Sdf01NewValidationRule." + name();
|
||||
}
|
||||
}
|
||||
|
|
@ -4,5 +4,7 @@ public enum ValidationStored {
|
|||
STradesCompany, STradesCounterCompany, STradesSecurity, STradesTradingClearingRegistry,
|
||||
Account, Company,
|
||||
|
||||
Sdf57CompanyDeb, Sdf57CompanyCred, Sdf57AccountDeb, Sdf57AccountCred
|
||||
Sdf57CompanyDeb, Sdf57CompanyCred, Sdf57AccountDeb, Sdf57AccountCred,
|
||||
|
||||
Sdf01Company, Sdf01Account
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
package ru.spcex.platform.enumeration;
|
||||
|
||||
import ru.spcex.platform.utils.enumeration.IEnumKey;
|
||||
|
||||
public enum AccType implements IEnumKey {
|
||||
A("A"), B("B");
|
||||
|
||||
private final String key;
|
||||
|
||||
AccType(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ package ru.spcex.platform.enumeration;
|
|||
import ru.spcex.platform.utils.enumeration.IEnumKey;
|
||||
|
||||
public enum MarketType implements IEnumKey {
|
||||
PRMR("PRMR");
|
||||
PRMR("PRMR"), SCND("SCND");
|
||||
|
||||
private final String key;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue