From 2363c3362cca2416751e412b34f327516a065338 Mon Sep 17 00:00:00 2001 From: ialbert Date: Tue, 31 Jan 2023 20:09:27 +0300 Subject: [PATCH] http://jira.mfd.msk:8088/browse/CLS-189 --- .../clearing/config/ValidationConfig.java | 61 +++++++++++++ .../clearing/error/ClearingErrorInternal.java | 21 +++++ .../ru/spcex/clearing/service/Clearing.java | 47 +++++++++- .../validation/ClrngValidationStored.java | 6 ++ .../ExecutionDepositValidationRule.java | 89 +++++++++++++++++++ 5 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingErrorInternal.java create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ClrngValidationStored.java create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ExecutionDepositValidationRule.java 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 new file mode 100644 index 000000000..f4eb7ac72 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java @@ -0,0 +1,61 @@ +package ru.spcex.clearing.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import ru.clearing.classes.statics.data.company.Company; +import ru.clearing.classes.statics.data.company.relation.Relation; +import ru.clearing.classes.statics.data.execution.ExecutionDeposit; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.service.validation.ClrngValidationStored; +import ru.spcex.clearing.service.validation.ExecutionDepositValidationRule; +import ru.spcex.platform.classes.base.SpcexObjectBase; +import ru.spcex.platform.enumeration.ClearingCategory; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.validation.ImdgValidationContext; +import ru.spcex.platform.utils.validation.IValidator; +import ru.spcex.platform.utils.validation.ValidatorImpl; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; + +@Configuration +public class ValidationConfig { + private final Map> imdgs; + + public ValidationConfig(ImdgProvider imdgProvider) { + this.imdgs = new HashMap<>(); + BiConsumer> addImdg = (s, aClass) -> imdgs.put(s, imdgProvider.getImdg(s, aClass)); + addImdg.accept(IMDGDistributedNames.Map_Relation, Relation.class); + addImdg.accept(IMDGDistributedNames.Map_Company, Company.class); + } + + /** + * чтобы во всех валидаторах был один экземпляр Imdg + */ + private Imdg getImdg(String key) { + return imdgs.get(key); + } + + private final BiConsumer, String> addImdg = (context, s) + -> context.addImdg(s, getImdg(s)); + + @Bean("executionDepositValidator") + public BiFunction executionDepositValidator() { + return (category, execDeposit) -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(execDeposit); + context.storeObject(ClrngValidationStored.categoryPredefined, category); + addImdg.accept(context, IMDGDistributedNames.Map_Relation); + addImdg.accept(context, IMDGDistributedNames.Map_Company); + return new ValidatorImpl<>(context, + ExecutionDepositValidationRule.ClearingIsAllowed, + ExecutionDepositValidationRule.AccountIsNotBlocked, + ExecutionDepositValidationRule.CompanyIsNotBlocked, + ExecutionDepositValidationRule.FinancialObligationSecurity); + }; + } + +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingErrorInternal.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingErrorInternal.java new file mode 100644 index 000000000..dfeee61f9 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingErrorInternal.java @@ -0,0 +1,21 @@ +package ru.spcex.clearing.error; + +import ru.spcex.platform.utils.enumeration.IEnumId; + +public enum ClearingErrorInternal implements IEnumId { + ClearingNotAllowed(1L), + AccountNotActive(2L), + CompanyNotActive(3L), + FinancialObligationNotSatisfied(4L), + ; + private final Long id; + + ClearingErrorInternal(Long id) { + this.id = id; + } + + @Override + public Long getId() { + return id; + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java index 90a4bf630..c46e73787 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Clearing.java @@ -1,30 +1,44 @@ package ru.spcex.clearing.service; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.execution.ExecutionDeposit; import ru.clearing.classes.statics.data.generated.ClearingMemberCategory; +import ru.spcex.clearing.error.ClearingErrorInternal; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.service.order.ExecutionDepositSorter; +import ru.spcex.platform.enumeration.Allowed; import ru.spcex.platform.enumeration.ClearingCategory; 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.validation.IValidator; +import java.time.Instant; import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; +import java.util.Optional; +import java.util.function.BiFunction; @Service public class Clearing { + private final Logger log = LoggerFactory.getLogger(getClass()); private final Imdg executionDepositImdg; private final Imdg clearingCategoryImdg; private final ExecutionDepositSorter sorter; + private final BiFunction validation; @Autowired - public Clearing(ImdgProvider imdgProvider, ExecutionDepositSorter sorter) { + public Clearing(ImdgProvider imdgProvider, + ExecutionDepositSorter sorter, + BiFunction validation) { this.executionDepositImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionDeposit, ExecutionDeposit.class); this.clearingCategoryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class); this.sorter = sorter; + this.validation = validation; } public void startClearing() { @@ -41,6 +55,37 @@ public class Clearing { } private void processSingleCompany(ClearingCategory category, List executionDeposits) { + log.info("Start clearing for category: {}, company: {}", category, executionDeposits.get(0).getCompanyId()); + boolean financialError = false; + for (ExecDepositWCategory execDepositWrapper : executionDeposits) { + ExecutionDeposit execDeposit = execDepositWrapper.getExecutionDeposit(); + if (financialError) { + updateDenied(execDeposit); + continue; + } + IValidator validator = validation.apply(category, execDeposit); + Optional errorMsg = validator.tillFirstError(); + if (errorMsg.isPresent() && !ClearingErrorInternal.FinancialObligationNotSatisfied.equals(errorMsg.get().getSubject())) { + updateDenied(execDeposit); + continue; + } else if (errorMsg.isPresent()) { + financialError = true; + updateDenied(execDeposit); + continue; + } + updateAllowed(execDeposit); + } + } + private void updateDenied(ExecutionDeposit execDeposit) { + execDeposit.setCoverageStatus(Allowed.DENIED.getKey()); + execDeposit.setUpdated(Instant.now()); + executionDepositImdg.update(execDeposit); + } + + private void updateAllowed(ExecutionDeposit execDeposit) { + execDeposit.setCoverageStatus(Allowed.ALLOWED.getKey()); + execDeposit.setUpdated(Instant.now()); + executionDepositImdg.update(execDeposit); } } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ClrngValidationStored.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ClrngValidationStored.java new file mode 100644 index 000000000..27bbb5eec --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ClrngValidationStored.java @@ -0,0 +1,6 @@ +package ru.spcex.clearing.service.validation; + +public enum ClrngValidationStored { + relation, categoryPredefined + ; +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ExecutionDepositValidationRule.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ExecutionDepositValidationRule.java new file mode 100644 index 000000000..b2eaeb6da --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ExecutionDepositValidationRule.java @@ -0,0 +1,89 @@ +package ru.spcex.clearing.service.validation; + +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.company.relation.Relation; +import ru.clearing.classes.statics.data.execution.ExecutionDeposit; +import ru.spcex.clearing.error.ClearingErrorInternal; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.platform.enumeration.AccountStatus; +import ru.spcex.platform.enumeration.ClearingCategory; +import ru.spcex.platform.enumeration.ServiceStatus; +import ru.spcex.platform.enumeration.WorkflowStatus; +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.validation.IValidationRule; + +import java.util.Map; +import java.util.Optional; + +public enum ExecutionDepositValidationRule implements IValidationRule> { + ClearingIsAllowed() { + @Override + public Optional validate(ImdgValidationContext context) { + ExecutionDeposit validatedObject = context.getValidatedObject(); + Imdg relationImdg = context.obtainMap(IMDGDistributedNames.Map_Relation, Relation.class); + Relation relation = relationImdg.getSingleObjectByFieldValues(Map.of("consumerId", validatedObject.getCompanyId())); + if (relation == null || !ServiceStatus.Active.equalsByKey(relation.getServiceStatus())) { + return of(ClearingErrorInternal.ClearingNotAllowed); + } + context.storeObject(ClrngValidationStored.relation, relation); + return empty(); + } + }, + AccountIsNotBlocked() { + @Override + public Optional validate(ImdgValidationContext context) { + ExecutionDeposit validatedObject = context.getValidatedObject(); + Imdg accountImdg = context.obtainMap(IMDGDistributedNames.Map_Account, Account.class); + Relation relation = context.getStoredObject(ClrngValidationStored.relation); + Account account = accountImdg.getSingleObjectByFieldValues( + Map.of("id", validatedObject.getAccountId(), "relationId", relation.getId())); + if (account == null || !AccountStatus.ACTIVE.equalsByKey(account.getAccountStatus())) { + return of(ClearingErrorInternal.AccountNotActive); + } + return empty(); + } + }, + CompanyIsNotBlocked() { + @Override + public Optional validate(ImdgValidationContext context) { + ExecutionDeposit validatedObject = context.getValidatedObject(); + Imdg companyImdg = context.obtainMap(IMDGDistributedNames.Map_Company, Company.class); + Company company = companyImdg.getSingleObjectByFieldValues(Map.of("id", validatedObject.getCompanyId())); + if (company == null || !WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus())) { + return of(ClearingErrorInternal.CompanyNotActive); + } + return empty(); + } + }, + FinancialObligationSecurity() { + @Override + public Optional validate(ImdgValidationContext context) { + ClearingCategory category = context.getStoredObject(ClrngValidationStored.categoryPredefined); + if (!category.equals(ClearingCategory.V)) { + return Optional.empty(); + } + ExecutionDeposit validatedObject = context.getValidatedObject(); + Imdg accountBalanceImdg = context.obtainMap(IMDGDistributedNames.Map_AccountBalance, AccountBalance.class); + AccountBalance accountBalance = accountBalanceImdg.getSingleObjectByFieldValues( + Map.of("accountId", validatedObject.getAccountId(), + "companyId", validatedObject.getCompanyId())); + if (accountBalance == null) { + return of(ClearingErrorInternal.FinancialObligationNotSatisfied); + } + //todo ABS + if (validatedObject.getFirstLegAmount().compareTo(accountBalance.getFreeBalanceAmount()) > 0) { + return of(ClearingErrorInternal.FinancialObligationNotSatisfied); + } + return empty(); + } + }; + + @Override + public String ruleName() { + return "Sdf09ValidationRule." + name(); + } +} \ No newline at end of file