diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java index f1f1d799f..af518cc3b 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java @@ -12,6 +12,7 @@ import ru.clearing.classes.statics.data.misc.Session; 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.SDf08; import ru.clearing.classes.statics.data.sdf.SDf57; import ru.clearing.classes.statics.data.security.MoneyMarketSecurity; import ru.clearing.classes.statics.data.security.Security; @@ -171,4 +172,18 @@ public class ValidationConfig { ); }; } + + @Bean("sdf08ValidatorNew") + public Function sdf08ValidatorNew() { + return sDf08 -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(sDf08); + context.addImdg(IMDGDistributedNames.Map_Account, imdgAccount); + context.addImdg(IMDGDistributedNames.Map_Company, imdgCompany); + return new ValidatorImpl<>(context, + Sdf08NewValidationRule.CompanyPresent, + Sdf08NewValidationRule.AccountPresent + ); + }; + } } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf08Executor.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf08Executor.java new file mode 100644 index 000000000..6ef870f59 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf08Executor.java @@ -0,0 +1,163 @@ +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.company.Company; +import ru.clearing.classes.statics.data.registry.Registry; +import ru.clearing.classes.statics.data.sdf.SDf08; +import ru.clearing.classes.statics.data.security.Security; +import ru.clearing.classes.statics.data.statement.Statement; +import ru.spcex.clearing.error.ClearingErrorInternal; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountSdfRequestPart; +import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest; +import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; +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.imdg.api.predicate.ImdgPredicate; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; +import ru.spcex.platform.utils.enumeration.EnumMessage; +import ru.spcex.platform.utils.enumeration.IMessageResolver; +import ru.spcex.platform.utils.validation.IValidator; + +import java.math.BigDecimal; +import java.time.Instant; +import java.time.LocalDate; +import java.util.Collection; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; + +@Service +public class Sdf08Executor extends AbstractExecutor { + private final Logger log = LoggerFactory.getLogger(getClass()); + + private final ImdgProvider imdgProvider; + private final Imdg registryImdg; + private final Imdg securityImdg; + private final Function sDf08Validator; + private final IMessageResolver messageResolver; + + public Sdf08Executor(@Qualifier("sdf08ValidatorNew") Function sDf08Validator, + ImdgProvider imdgProvider, + IMessageResolver messageResolver) { + this.imdgProvider = imdgProvider; + this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); + this.securityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Security, Security.class); + this.sDf08Validator = sDf08Validator; + this.messageResolver = messageResolver; + } + + @Override + public String exportTableName() { + return ""; + } + + @Override + public boolean isNeedToSendCommand() { + return false; + } + + @Override + public void sendCommand(KafkaSender kafkaSender, Result result) { + } + + public Result execute(Collection sdf, StatementRequest statementRequest) { + Result result = new Result(); + Long generationIdForGroup = imdgProvider.getImdgIdGenerator().nextId(); + result.setGenerationId(generationIdForGroup); + for (SDf08 sdf08 : sdf) { + IValidator validator = sDf08Validator.apply(sdf08); + Optional error = validator.tillFirstError(); + Company company = validator.getStored(ValidationStored.Sdf08Company); + Account account = validator.getStored(ValidationStored.Sdf08Account); + if (statementRequest.getAccountCreationResults().size() == 0 + && ClearingErrorInternal.AccountNotPresent.equals(error.map(EnumMessage::getSubject).orElse(null))) { + result.getAccountRequests().add(createAccountRequestPart(sdf08.getId(), sdf08.getDepoCode(), company.getId())); + log.info("account {} for sdf08.id={} not found - send request for creation", sdf08.getDepoCode(), sdf08.getId()); + continue; + } 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={}", sdf08.getId()); + } + if (error.isPresent()) { + log.error("sdf01.id={} error: {}", sdf08.getId(), messageResolver.resolve(error.get())); + //fixme инициировать = команда для другого сервиса? sdf02Imdg.insert(createErrorSdf02(sdf01, error.get(), generationIdForGroup)); +// sdf02Imdg.insert(createErrorSdf02(sdf01, error.get(), generationIdForGroup)); + continue; + } + + Statement stmt = createSdf08Statement(sdf08, company, account); + //на данном шаге 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; +// log.debug("Process sdf08 record; sdf08.id: {}", sdf08.getId()); +// Collection registries = selectRegistryForSDF04(sdf08.getC_acc_cred()); +// registries.forEach(registry -> unlockRegistry(registry, new BigDecimal(sdf08.getPay_val()))); + } + return result; + } + + protected Collection selectRegistryForSDF04(String account) { + ImdgPredicateBuilder pb = registryImdg.predicateBuilder(); + ImdgPredicate query = pb.and( + pb.and( + pb.equals("registryDesignation", RegistryDesignation.A.getKey()), + pb.equals("registryInstrumentType", RegistryInstrumentType.M.getKey()), + pb.equals("registryUnit", RegistryUnit.B.getKey()) + ), + pb.equals("account", account) + ); + + Collection result = registryImdg.getCollectionObjectsByPredicate(query); + log.trace("Selected {} registry's by sql: {}", result.size(), query); + return result; + } + + boolean unlockRegistry(Registry registry, BigDecimal value) { + if (registry.getBalance() == null) registry.setBalance(BigDecimal.ZERO); + registry.setBalance(registry.getBalance().subtract(value)); + return true; + } + + 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 Statement createSdf08Statement(SDf08 sdf08, Company company, Account account) { + Statement stmt = new Statement(); + stmt.setAddresseeId(company.getId()); + stmt.setAddresseeId(company.getId()); + stmt.setSenderId(Sender.Rdc.getId()); + stmt.setStatementType(StatementType.incr.getKey()); + stmt.setAccountId(account.getId()); + stmt.setAccount(account.getAccount()); + stmt.setInOutDirection(InOutDirection.in.getKey()); + if (sdf08.getQuantity() != null) { + stmt.setAmount(new BigDecimal(sdf08.getQuantity())); + } + stmt.setOperationStatus(OperationStatus.Pending.getKey()); + stmt.setInSDfId(sdf08.getId()); + stmt.setInOutSDfType(InOutSDfType.type1.getKey()); + stmt.setClearingDate(LocalDate.now()); + Security security = securityImdg.getSingleObjectByFieldValues(Map.of("securitySymbol", sdf08.getSecurityCode())); + if (security != null) { + stmt.setSecurityId(security.getId()); + } + stmt.setCreated(Instant.now()); + return stmt; + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf08NewValidationRule.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf08NewValidationRule.java new file mode 100644 index 000000000..bbb26fd11 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/Sdf08NewValidationRule.java @@ -0,0 +1,54 @@ +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.SDf08; +import ru.spcex.clearing.error.ClearingError; +import ru.spcex.clearing.error.ClearingErrorInternal; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +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.text.TextUtil; +import ru.spcex.platform.utils.validation.IValidationRule; + +import java.util.Optional; + +public enum Sdf08NewValidationRule implements IValidationRule> { + CompanyPresent() { + @Override + public Optional validate(ImdgValidationContext context) { + SDf08 sdf08 = context.getValidatedObject(); + Imdg companyImdg = context.obtainMap(IMDGDistributedNames.Map_Company, Company.class); + + if (TextUtil.isEmpty(sdf08.getClientName())) { + of(ClearingError.CompanyNotFoundB, sdf08.getClientName()); + } + + Company company = companyImdg.getSingleObjectBySQL("fullName = '" + sdf08.getClientName() + "'"); + if (company == null) { + return of(ClearingError.CompanyNotFoundB, sdf08.getClientName()); + } + context.storeObject(ValidationStored.Sdf08Company, company); + return empty(); + } + }, AccountPresent() { + @Override + public Optional validate(ImdgValidationContext context) { + SDf08 sdf08 = context.getValidatedObject(); + Imdg accountImdg = context.obtainMap(IMDGDistributedNames.Map_Account, Account.class); + Account acc = accountImdg.getSingleObjectBySQL("account = '" + sdf08.getDepoCode() + + "' and accountType='" + ru.spcex.platform.enumeration.AccountType.Depo.getKey() + "'"); + if (acc == null) { + return of (ClearingErrorInternal.AccountNotPresent, sdf08.getDepoCode()); + } + context.storeObject(ValidationStored.Sdf08Account, acc); + return empty(); + } + }; + + @Override + public String ruleName() { + return "Sdf01NewValidationRule." + name(); + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java index aed0a13fe..472a65bfd 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java @@ -6,5 +6,7 @@ public enum ValidationStored { Sdf57CompanyDeb, Sdf57CompanyCred, Sdf57AccountDeb, Sdf57AccountCred, - Sdf01Company, Sdf01Account + Sdf01Company, Sdf01Account, + + Sdf08Company, Sdf08Account } diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Sender.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Sender.java index 60d8132be..9b3cd0317 100644 --- a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Sender.java +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Sender.java @@ -4,7 +4,8 @@ import ru.spcex.platform.utils.enumeration.IEnumId; public enum Sender implements IEnumId { One(1L), /* СПВБ */ - Prc(2L); /* ПРЦ */ + Prc(2L), /* ПРЦ */ + Rdc(3L); /* РДЦ */ private final Long key;