This commit is contained in:
parent
7647a0ff5b
commit
2363c3362c
5 changed files with 223 additions and 1 deletions
|
|
@ -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<String, Imdg<? extends SpcexObjectBase>> imdgs;
|
||||||
|
|
||||||
|
public ValidationConfig(ImdgProvider imdgProvider) {
|
||||||
|
this.imdgs = new HashMap<>();
|
||||||
|
BiConsumer<String, Class<? extends SpcexObjectBase>> 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<ImdgValidationContext<?>, String> addImdg = (context, s)
|
||||||
|
-> context.addImdg(s, getImdg(s));
|
||||||
|
|
||||||
|
@Bean("executionDepositValidator")
|
||||||
|
public BiFunction<ClearingCategory, ExecutionDeposit, IValidator> executionDepositValidator() {
|
||||||
|
return (category, execDeposit) -> {
|
||||||
|
ImdgValidationContext<ExecutionDeposit> 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);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,30 +1,44 @@
|
||||||
package ru.spcex.clearing.service;
|
package ru.spcex.clearing.service;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import ru.clearing.classes.statics.data.execution.ExecutionDeposit;
|
import ru.clearing.classes.statics.data.execution.ExecutionDeposit;
|
||||||
import ru.clearing.classes.statics.data.generated.ClearingMemberCategory;
|
import ru.clearing.classes.statics.data.generated.ClearingMemberCategory;
|
||||||
|
import ru.spcex.clearing.error.ClearingErrorInternal;
|
||||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||||
import ru.spcex.clearing.service.order.ExecutionDepositSorter;
|
import ru.spcex.clearing.service.order.ExecutionDepositSorter;
|
||||||
|
import ru.spcex.platform.enumeration.Allowed;
|
||||||
import ru.spcex.platform.enumeration.ClearingCategory;
|
import ru.spcex.platform.enumeration.ClearingCategory;
|
||||||
import ru.spcex.platform.imdg.api.Imdg;
|
import ru.spcex.platform.imdg.api.Imdg;
|
||||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
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.Collection;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class Clearing {
|
public class Clearing {
|
||||||
|
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
private final Imdg<ExecutionDeposit> executionDepositImdg;
|
private final Imdg<ExecutionDeposit> executionDepositImdg;
|
||||||
private final Imdg<ClearingMemberCategory> clearingCategoryImdg;
|
private final Imdg<ClearingMemberCategory> clearingCategoryImdg;
|
||||||
private final ExecutionDepositSorter sorter;
|
private final ExecutionDepositSorter sorter;
|
||||||
|
private final BiFunction<ClearingCategory, ExecutionDeposit, IValidator> validation;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public Clearing(ImdgProvider imdgProvider, ExecutionDepositSorter sorter) {
|
public Clearing(ImdgProvider imdgProvider,
|
||||||
|
ExecutionDepositSorter sorter,
|
||||||
|
BiFunction<ClearingCategory, ExecutionDeposit, IValidator> validation) {
|
||||||
this.executionDepositImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionDeposit, ExecutionDeposit.class);
|
this.executionDepositImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionDeposit, ExecutionDeposit.class);
|
||||||
this.clearingCategoryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class);
|
this.clearingCategoryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class);
|
||||||
this.sorter = sorter;
|
this.sorter = sorter;
|
||||||
|
this.validation = validation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startClearing() {
|
public void startClearing() {
|
||||||
|
|
@ -41,6 +55,37 @@ public class Clearing {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processSingleCompany(ClearingCategory category, List<ExecDepositWCategory> executionDeposits) {
|
private void processSingleCompany(ClearingCategory category, List<ExecDepositWCategory> 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<EnumMessage> 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
package ru.spcex.clearing.service.validation;
|
||||||
|
|
||||||
|
public enum ClrngValidationStored {
|
||||||
|
relation, categoryPredefined
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
@ -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<ImdgValidationContext<ExecutionDeposit>> {
|
||||||
|
ClearingIsAllowed() {
|
||||||
|
@Override
|
||||||
|
public Optional<EnumMessage> validate(ImdgValidationContext<ExecutionDeposit> context) {
|
||||||
|
ExecutionDeposit validatedObject = context.getValidatedObject();
|
||||||
|
Imdg<Relation> 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<EnumMessage> validate(ImdgValidationContext<ExecutionDeposit> context) {
|
||||||
|
ExecutionDeposit validatedObject = context.getValidatedObject();
|
||||||
|
Imdg<Account> 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<EnumMessage> validate(ImdgValidationContext<ExecutionDeposit> context) {
|
||||||
|
ExecutionDeposit validatedObject = context.getValidatedObject();
|
||||||
|
Imdg<Company> 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<EnumMessage> validate(ImdgValidationContext<ExecutionDeposit> context) {
|
||||||
|
ClearingCategory category = context.getStoredObject(ClrngValidationStored.categoryPredefined);
|
||||||
|
if (!category.equals(ClearingCategory.V)) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
ExecutionDeposit validatedObject = context.getValidatedObject();
|
||||||
|
Imdg<AccountBalance> 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue