Sdf01Executor

This commit is contained in:
ialbert 2023-05-25 21:05:36 +03:00
parent 389eb7d9fd
commit f22dad9a20
10 changed files with 551 additions and 72 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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();
}
}

View file

@ -4,5 +4,7 @@ public enum ValidationStored {
STradesCompany, STradesCounterCompany, STradesSecurity, STradesTradingClearingRegistry,
Account, Company,
Sdf57CompanyDeb, Sdf57CompanyCred, Sdf57AccountDeb, Sdf57AccountCred
Sdf57CompanyDeb, Sdf57CompanyCred, Sdf57AccountDeb, Sdf57AccountCred,
Sdf01Company, Sdf01Account
}

View file

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

View file

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