This commit is contained in:
parent
ea0a449602
commit
9223d8b391
6 changed files with 375 additions and 2 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
package ru.spcex.clearing.config;
|
package ru.spcex.clearing.config;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
@ -41,11 +42,14 @@ import ru.spcex.clearing.error.ClearingError;
|
||||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||||
import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest;
|
import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest;
|
||||||
import ru.spcex.clearing.platform.messaging.domain.cud.payment.PIClearingOutbondActionNewRequest;
|
import ru.spcex.clearing.platform.messaging.domain.cud.payment.PIClearingOutbondActionNewRequest;
|
||||||
|
import ru.spcex.clearing.platform.messaging.domain.cud.registry.DmauRegistryRequest;
|
||||||
import ru.spcex.clearing.platform.messaging.domain.cud.registry.IdentificationFundsRequest;
|
import ru.spcex.clearing.platform.messaging.domain.cud.registry.IdentificationFundsRequest;
|
||||||
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryChangeRefundDateRequest;
|
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryChangeRefundDateRequest;
|
||||||
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryChangeStatusExtractRequest;
|
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryChangeStatusExtractRequest;
|
||||||
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryReturnDepositRequest;
|
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryReturnDepositRequest;
|
||||||
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistrySplitDepositActionRequest;
|
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistrySplitDepositActionRequest;
|
||||||
|
import ru.spcex.clearing.service.AssetTrio;
|
||||||
|
import ru.spcex.clearing.service.registry.AssetTBFProcessing;
|
||||||
import ru.spcex.clearing.service.validation.AnltAccLoad;
|
import ru.spcex.clearing.service.validation.AnltAccLoad;
|
||||||
import ru.spcex.clearing.service.validation.ClrngValidationStored;
|
import ru.spcex.clearing.service.validation.ClrngValidationStored;
|
||||||
import ru.spcex.clearing.service.validation.CompanyByTradingCodeValidationRule;
|
import ru.spcex.clearing.service.validation.CompanyByTradingCodeValidationRule;
|
||||||
|
|
@ -68,18 +72,27 @@ import ru.spcex.clearing.service.validation.SecurityBySecurityCodeValidationRule
|
||||||
import ru.spcex.clearing.service.validation.SessionTerminationValidationRule;
|
import ru.spcex.clearing.service.validation.SessionTerminationValidationRule;
|
||||||
import ru.spcex.clearing.service.validation.SplitDepositRequestValidationRule;
|
import ru.spcex.clearing.service.validation.SplitDepositRequestValidationRule;
|
||||||
import ru.spcex.clearing.service.validation.StatusExtractValidationRule;
|
import ru.spcex.clearing.service.validation.StatusExtractValidationRule;
|
||||||
|
import ru.spcex.clearing.service.validation.WithdrawalFundsValidationRule;
|
||||||
|
import ru.spcex.clearing.service.validation.WithdrawalFundsValidationStore;
|
||||||
import ru.spcex.clearing.util.security.UserRoleVerification;
|
import ru.spcex.clearing.util.security.UserRoleVerification;
|
||||||
import ru.spcex.clearing.validation.common.rules.DictionaryPresentRule;
|
import ru.spcex.clearing.validation.common.rules.DictionaryPresentRule;
|
||||||
import ru.spcex.clearing.validation.common.rules.FieldRequiredRule;
|
import ru.spcex.clearing.validation.common.rules.FieldRequiredRule;
|
||||||
import ru.spcex.clearing.validation.common.rules.IdPresentRule;
|
import ru.spcex.clearing.validation.common.rules.IdPresentRule;
|
||||||
import ru.spcex.platform.enumeration.ClearingCategory;
|
import ru.spcex.platform.enumeration.ClearingCategory;
|
||||||
|
import ru.spcex.platform.enumeration.CompanySymbol;
|
||||||
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.imdg.api.predicate.ImdgPredicate;
|
||||||
|
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
|
||||||
|
import ru.spcex.platform.imdg.api.predicate.specific.IdEqualPredicate;
|
||||||
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
|
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
|
||||||
import ru.spcex.platform.imdg.validation.LogPrefixId;
|
import ru.spcex.platform.imdg.validation.LogPrefixId;
|
||||||
import ru.spcex.platform.imdg.validation.rule.CurrencyCodeValidationRule;
|
import ru.spcex.platform.imdg.validation.rule.CurrencyCodeValidationRule;
|
||||||
import ru.spcex.platform.imdg.validation.rule.PresentById;
|
import ru.spcex.platform.imdg.validation.rule.PresentById;
|
||||||
|
import ru.spcex.platform.imdg.validation.rule.PresentByPredicate;
|
||||||
|
import ru.spcex.platform.utils.enumeration.EnumMessage;
|
||||||
import ru.spcex.platform.utils.enumeration.IMessageResolver;
|
import ru.spcex.platform.utils.enumeration.IMessageResolver;
|
||||||
|
import ru.spcex.platform.utils.validation.IValidationRule;
|
||||||
import ru.spcex.platform.utils.validation.IValidator;
|
import ru.spcex.platform.utils.validation.IValidator;
|
||||||
import ru.spcex.platform.utils.validation.ValidatorImpl;
|
import ru.spcex.platform.utils.validation.ValidatorImpl;
|
||||||
|
|
||||||
|
|
@ -113,8 +126,9 @@ public class ValidationConfig {
|
||||||
Imdg<PaymentInstruction> pmtImdg;
|
Imdg<PaymentInstruction> pmtImdg;
|
||||||
Imdg<ClearingMemberCategory> ctgrImdg;
|
Imdg<ClearingMemberCategory> ctgrImdg;
|
||||||
ImdgProvider imdgProvider;
|
ImdgProvider imdgProvider;
|
||||||
|
AssetTBFProcessing assetsMng;
|
||||||
|
|
||||||
public ValidationConfig(ImdgProvider imdgProvider) {
|
public ValidationConfig(ImdgProvider imdgProvider, AssetTBFProcessing assetsMng) {
|
||||||
this.imdgRelation = imdgProvider.getImdg(IMDGDistributedNames.Map_Relation, Relation.class);
|
this.imdgRelation = imdgProvider.getImdg(IMDGDistributedNames.Map_Relation, Relation.class);
|
||||||
this.imdgCompany = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
|
this.imdgCompany = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
|
||||||
this.imdgCurrency = imdgProvider.getImdg(IMDGDistributedNames.Map_Currency, Currency.class);
|
this.imdgCurrency = imdgProvider.getImdg(IMDGDistributedNames.Map_Currency, Currency.class);
|
||||||
|
|
@ -142,6 +156,7 @@ public class ValidationConfig {
|
||||||
this.currencyPairSecurityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CurrencyPairSecurity, CurrencyPairSecurity.class);
|
this.currencyPairSecurityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CurrencyPairSecurity, CurrencyPairSecurity.class);
|
||||||
this.digitalCertificateSecurityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_DigitalCertificateSecurity, DigitalCertificateSecurity.class);
|
this.digitalCertificateSecurityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_DigitalCertificateSecurity, DigitalCertificateSecurity.class);
|
||||||
this.imdgProvider = imdgProvider;
|
this.imdgProvider = imdgProvider;
|
||||||
|
this.assetsMng = assetsMng;
|
||||||
}
|
}
|
||||||
|
|
||||||
//@Bean("adminRoleVerification")
|
//@Bean("adminRoleVerification")
|
||||||
|
|
@ -399,6 +414,81 @@ public class ValidationConfig {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean("withdrawalFundsValidator")
|
||||||
|
public Function<DmauRegistryRequest, IValidator> withdrawalFundsValidator() {
|
||||||
|
return identificationFundsRequest -> {
|
||||||
|
ImdgValidationContext<DmauRegistryRequest> context = new ImdgValidationContext<>();
|
||||||
|
context.setValidatedObject(identificationFundsRequest);
|
||||||
|
context.addImdg(IMDGDistributedNames.Map_Account, imdgAccount);
|
||||||
|
context.addImdg(IMDGDistributedNames.Map_Company, imdgCompany);
|
||||||
|
context.addImdg(IMDGDistributedNames.Map_CompanySymbols, imdgCompanySymbols);
|
||||||
|
context.addImdg(IMDGDistributedNames.Map_TradingClearingRegistry, imdgTradingClearingRegistry);
|
||||||
|
context.addImdg(IMDGDistributedNames.Map_TradingClearingRegistryList, imdgTradingClearingRegistryList);
|
||||||
|
|
||||||
|
context.setLogPrefix(dmauRegistryRequest ->
|
||||||
|
"[debitCorrAccount:%s]".formatted(dmauRegistryRequest.getDebitCorrAccount()
|
||||||
|
));
|
||||||
|
|
||||||
|
ImdgPredicateBuilder cmpSymbPb = imdgCompanySymbols.predicateBuilder();
|
||||||
|
var cmpSymbCheck = PresentByPredicate.builder(
|
||||||
|
(Function<DmauRegistryRequest, ImdgPredicate>) req -> cmpSymbPb.and(
|
||||||
|
cmpSymbPb.equals("companyId", req.getSenderId()),
|
||||||
|
cmpSymbPb.equals("companySymbol", CompanySymbol.BIC.getKey())
|
||||||
|
))
|
||||||
|
.mapName(IMDGDistributedNames.Map_CompanySymbols)
|
||||||
|
.errorProvider(req -> new EnumMessage(ClearingError.RecordNotFound, "companySymbol"))
|
||||||
|
.store(WithdrawalFundsValidationStore.CompanySymbol)
|
||||||
|
.build()
|
||||||
|
;
|
||||||
|
|
||||||
|
ImdgPredicateBuilder cmpPb = imdgCompany.predicateBuilder();
|
||||||
|
var cmpCheck = PresentByPredicate.builder(new IdEqualPredicate<>(
|
||||||
|
cmpPb, DmauRegistryRequest::getSenderId
|
||||||
|
))
|
||||||
|
.mapName(IMDGDistributedNames.Map_Company)
|
||||||
|
.errorProvider(req -> new EnumMessage(ClearingError.RecordNotFound, "company"))
|
||||||
|
.store(WithdrawalFundsValidationStore.Company)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ImdgPredicateBuilder accPb = imdgAccount.predicateBuilder();
|
||||||
|
var accCheck = PresentByPredicate.builder(new IdEqualPredicate<>(
|
||||||
|
accPb, DmauRegistryRequest::getCreditLegAccountId
|
||||||
|
))
|
||||||
|
.mapName(IMDGDistributedNames.Map_Account)
|
||||||
|
.errorProvider(req -> new EnumMessage(ClearingError.RecordNotFound, "account"))
|
||||||
|
.store(WithdrawalFundsValidationStore.Account)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
var assetPresent = new IValidationRule<ImdgValidationContext<DmauRegistryRequest>>() {
|
||||||
|
@Override
|
||||||
|
public Optional<EnumMessage> validate(ImdgValidationContext<DmauRegistryRequest> ctx) {
|
||||||
|
Company cmp = ctx.getStoredObject(WithdrawalFundsValidationStore.Company);
|
||||||
|
Account acc = ctx.getStoredObject(WithdrawalFundsValidationStore.Account);
|
||||||
|
Optional<AssetTrio> assetsTrio = assetsMng.searchMoneyByAccAndCompany(cmp.getId(), acc.getId());
|
||||||
|
if (assetsTrio.isEmpty()) {
|
||||||
|
return of(ClearingError.RecordNotFound, "AM_F/AM_B/AM_T");
|
||||||
|
}
|
||||||
|
ctx.storeObject(WithdrawalFundsValidationStore.AssetTrio, assetsTrio.get());
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String ruleName() {
|
||||||
|
return "assets-present";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return new ValidatorImpl<>(context,
|
||||||
|
WithdrawalFundsValidationRule.Fields,
|
||||||
|
cmpSymbCheck,
|
||||||
|
cmpCheck,
|
||||||
|
accCheck,
|
||||||
|
assetPresent,
|
||||||
|
WithdrawalFundsValidationRule.TcrPresent
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Bean("splitDepositValidator")
|
@Bean("splitDepositValidator")
|
||||||
public Function<RegistrySplitDepositActionRequest, IValidator> splitDepositValidator() {
|
public Function<RegistrySplitDepositActionRequest, IValidator> splitDepositValidator() {
|
||||||
return refundDateRequest -> {
|
return refundDateRequest -> {
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import ru.spcex.clearing.platform.messaging.domain.cud.clearing.SessionContinueE
|
||||||
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonIdRequest;
|
import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonIdRequest;
|
||||||
import ru.spcex.clearing.platform.messaging.domain.cud.gateway.AssetOperationApprovalRequest;
|
import ru.spcex.clearing.platform.messaging.domain.cud.gateway.AssetOperationApprovalRequest;
|
||||||
import ru.spcex.clearing.platform.messaging.domain.cud.payment.PIClearingOutbondActionNewRequest;
|
import ru.spcex.clearing.platform.messaging.domain.cud.payment.PIClearingOutbondActionNewRequest;
|
||||||
|
import ru.spcex.clearing.platform.messaging.domain.cud.registry.DmauRegistryRequest;
|
||||||
import ru.spcex.clearing.platform.messaging.domain.cud.registry.IdentificationFundsRequest;
|
import ru.spcex.clearing.platform.messaging.domain.cud.registry.IdentificationFundsRequest;
|
||||||
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryChangeRefundDateRequest;
|
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryChangeRefundDateRequest;
|
||||||
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryChangeStatusExtractRequest;
|
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryChangeStatusExtractRequest;
|
||||||
|
|
@ -40,6 +41,7 @@ import ru.spcex.clearing.service.execution.ExecutionFondComponent;
|
||||||
import ru.spcex.clearing.service.executors.Sdf06Executor;
|
import ru.spcex.clearing.service.executors.Sdf06Executor;
|
||||||
import ru.spcex.clearing.service.executors.Sdf10Executor;
|
import ru.spcex.clearing.service.executors.Sdf10Executor;
|
||||||
import ru.spcex.clearing.service.payment.PaymentInstructionOutboundService;
|
import ru.spcex.clearing.service.payment.PaymentInstructionOutboundService;
|
||||||
|
import ru.spcex.clearing.service.payment.WithdrawalFundsService;
|
||||||
import ru.spcex.clearing.session.stage.SessionTerminator;
|
import ru.spcex.clearing.session.stage.SessionTerminator;
|
||||||
import ru.spcex.clearing.session.stage.TaskType;
|
import ru.spcex.clearing.session.stage.TaskType;
|
||||||
import ru.spcex.clearing.session.stage.impl.BalanceRevise;
|
import ru.spcex.clearing.session.stage.impl.BalanceRevise;
|
||||||
|
|
@ -65,6 +67,7 @@ public class EventsReceiver extends QueueConsumerV2 implements InitializingBean
|
||||||
private final StatementServiceV2 statementService;
|
private final StatementServiceV2 statementService;
|
||||||
private final SessionTerminator sessionTerminator;
|
private final SessionTerminator sessionTerminator;
|
||||||
private final PaymentInstructionOutboundService pmtOutboundService;
|
private final PaymentInstructionOutboundService pmtOutboundService;
|
||||||
|
private final WithdrawalFundsService withdrawalFundsService;
|
||||||
private final ExecutionCurrencyComponent execCurrUpload;
|
private final ExecutionCurrencyComponent execCurrUpload;
|
||||||
private final ExecutionDepositComponent execDepUpload;
|
private final ExecutionDepositComponent execDepUpload;
|
||||||
private final ExecutionFondComponent execFondUpload;
|
private final ExecutionFondComponent execFondUpload;
|
||||||
|
|
@ -81,7 +84,7 @@ public class EventsReceiver extends QueueConsumerV2 implements InitializingBean
|
||||||
Sdf05Sender sdf05Sender,
|
Sdf05Sender sdf05Sender,
|
||||||
StatementServiceV2 statementService,
|
StatementServiceV2 statementService,
|
||||||
SessionTerminator sessionTerminator,
|
SessionTerminator sessionTerminator,
|
||||||
PaymentInstructionOutboundService pmtOutboundService,
|
PaymentInstructionOutboundService pmtOutboundService, WithdrawalFundsService withdrawalFundsService,
|
||||||
ExecutionCurrencyComponent execCurrUpload,
|
ExecutionCurrencyComponent execCurrUpload,
|
||||||
ExecutionDepositComponent execDepUpload,
|
ExecutionDepositComponent execDepUpload,
|
||||||
ExecutionFondComponent execFondUpload) {
|
ExecutionFondComponent execFondUpload) {
|
||||||
|
|
@ -98,6 +101,7 @@ public class EventsReceiver extends QueueConsumerV2 implements InitializingBean
|
||||||
this.statementService = statementService;
|
this.statementService = statementService;
|
||||||
this.sessionTerminator = sessionTerminator;
|
this.sessionTerminator = sessionTerminator;
|
||||||
this.pmtOutboundService = pmtOutboundService;
|
this.pmtOutboundService = pmtOutboundService;
|
||||||
|
this.withdrawalFundsService = withdrawalFundsService;
|
||||||
this.execCurrUpload = execCurrUpload;
|
this.execCurrUpload = execCurrUpload;
|
||||||
this.execDepUpload = execDepUpload;
|
this.execDepUpload = execDepUpload;
|
||||||
this.execFondUpload = execFondUpload;
|
this.execFondUpload = execFondUpload;
|
||||||
|
|
@ -144,6 +148,9 @@ public class EventsReceiver extends QueueConsumerV2 implements InitializingBean
|
||||||
callback(PIClearingOutbondActionNewRequest.class)
|
callback(PIClearingOutbondActionNewRequest.class)
|
||||||
.setFunction(pmtOutboundService::sendOutBoundPayment)
|
.setFunction(pmtOutboundService::sendOutBoundPayment)
|
||||||
.forDestination(Consts.PAYMENT_INSTRUCTION_CLEARING_OUTBOUND_ACTION, callbacks::put);
|
.forDestination(Consts.PAYMENT_INSTRUCTION_CLEARING_OUTBOUND_ACTION, callbacks::put);
|
||||||
|
callback(DmauRegistryRequest.class)
|
||||||
|
.setFunction(withdrawalFundsService::withdrawalFunds)
|
||||||
|
.forDestination(Consts.REGISTRY_DMAU_CREATE_ACTION, callbacks::put);
|
||||||
callback(StatementRequest.class)
|
callback(StatementRequest.class)
|
||||||
.setConsumer(statementService::processReq)
|
.setConsumer(statementService::processReq)
|
||||||
.forDestination(Consts.STATEMENT_PROCESS, callbacks::put);
|
.forDestination(Consts.STATEMENT_PROCESS, callbacks::put);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,192 @@
|
||||||
|
package ru.spcex.clearing.service.payment;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
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.company.CompanySymbols;
|
||||||
|
import ru.clearing.classes.statics.data.payment.PaymentInstruction;
|
||||||
|
import ru.clearing.classes.statics.data.registry.TradingClearingRegistry;
|
||||||
|
import ru.clearing.classes.statics.data.sdf.SDf54;
|
||||||
|
import ru.spcex.clearing.error.ClearingError;
|
||||||
|
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||||
|
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
|
||||||
|
import ru.spcex.clearing.platform.messaging.domain.Consts;
|
||||||
|
import ru.spcex.clearing.platform.messaging.domain.cud.clearing.SdfClearingRequest;
|
||||||
|
import ru.spcex.clearing.platform.messaging.domain.cud.registry.DmauRegistryRequest;
|
||||||
|
import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate;
|
||||||
|
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
|
||||||
|
import ru.spcex.clearing.service.AssetTrio;
|
||||||
|
import ru.spcex.clearing.service.Sdf54Creator;
|
||||||
|
import ru.spcex.clearing.service.SpecifUtil;
|
||||||
|
import ru.spcex.clearing.service.registry.AssetTBFProcessing;
|
||||||
|
import ru.spcex.clearing.service.registry.DmiService;
|
||||||
|
import ru.spcex.clearing.service.validation.WithdrawalFundsValidationStore;
|
||||||
|
import ru.spcex.clearing.util.security.UserRoleVerification;
|
||||||
|
import ru.spcex.clearing.util.services.RequestHelper;
|
||||||
|
import ru.spcex.platform.enumeration.CurrencyCode;
|
||||||
|
import ru.spcex.platform.enumeration.InOutDirection;
|
||||||
|
import ru.spcex.platform.enumeration.TransactionStatus;
|
||||||
|
import ru.spcex.platform.enumeration.UserRole;
|
||||||
|
import ru.spcex.platform.imdg.api.Imdg;
|
||||||
|
import ru.spcex.platform.imdg.api.ImdgId;
|
||||||
|
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.log.ExceptionUtils;
|
||||||
|
import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD;
|
||||||
|
import ru.spcex.platform.utils.text.TextUtil;
|
||||||
|
import ru.spcex.platform.utils.time.TimeUtil;
|
||||||
|
import ru.spcex.platform.utils.validation.IValidator;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class WithdrawalFundsService {
|
||||||
|
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
|
private final Function<DmauRegistryRequest, IValidator> withdrawalFundsVal;
|
||||||
|
private final Sdf54Creator sdf54Creator;
|
||||||
|
private final Imdg<SDf54> sdf54Imdg;
|
||||||
|
private final Imdg<PaymentInstruction> pmtImdg;
|
||||||
|
private final KafkaSender kafkaSender;
|
||||||
|
private final ImdgId idGen;
|
||||||
|
private final RequestHelper reqHelp;
|
||||||
|
private final UserRoleVerification rights;
|
||||||
|
private final IMessageResolver msgResolver;
|
||||||
|
private final AssetTBFProcessing assetsMng;
|
||||||
|
private final DmiService dmiService;
|
||||||
|
|
||||||
|
public WithdrawalFundsService(Function<DmauRegistryRequest, IValidator> withdrawalFundsVal, Sdf54Creator sdf54Creator, ImdgProvider imdgProvider, KafkaSender kafkaSender, RequestHelper reqHelp, UserRoleVerification rights, IMessageResolver msgResolver, AssetTBFProcessing assetsMng, DmiService dmiService) {
|
||||||
|
this.withdrawalFundsVal = withdrawalFundsVal;
|
||||||
|
this.sdf54Creator = sdf54Creator;
|
||||||
|
this.kafkaSender = kafkaSender;
|
||||||
|
this.sdf54Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf54, SDf54.class);
|
||||||
|
this.pmtImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_PaymentInstruction, PaymentInstruction.class);
|
||||||
|
this.idGen = imdgProvider.getImdgIdGenerator();
|
||||||
|
this.reqHelp = reqHelp;
|
||||||
|
this.rights = rights;
|
||||||
|
this.msgResolver = msgResolver;
|
||||||
|
this.assetsMng = assetsMng;
|
||||||
|
this.dmiService = dmiService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RequestInfoUpdate withdrawalFunds(BaseRequest<DmauRegistryRequest> req) {
|
||||||
|
if (!rights.userHasRole(req.getUserId(), UserRole.Admin)) {
|
||||||
|
return reqHelp.error(req.getId(), ClearingError.UserVerifyDenial);
|
||||||
|
}
|
||||||
|
DmauRegistryRequest payload = req.getRequestPayload();
|
||||||
|
IValidator validator = withdrawalFundsVal.apply(payload);
|
||||||
|
Optional<EnumMessage> err = validator.tillFirstError();
|
||||||
|
if (err.isPresent()) {
|
||||||
|
log.error("DmauRegistryRequest.id={} debitCorrAccount={} validation error: {}",
|
||||||
|
req.getId(),
|
||||||
|
payload != null ? payload.getDebitCorrAccount() : null,
|
||||||
|
msgResolver.resolve(err.get()));
|
||||||
|
return reqHelp.error(req.getId(), err.get());
|
||||||
|
}
|
||||||
|
log.info("DmauRegistryRequest.id={} debitCorrAccount={} validation passed", req.getId(), payload.getDebitCorrAccount());
|
||||||
|
CompanySymbols cmpSymb = validator.getStored(WithdrawalFundsValidationStore.CompanySymbol);
|
||||||
|
Company cmp = validator.getStored(WithdrawalFundsValidationStore.Company);
|
||||||
|
Account acc = validator.getStored(WithdrawalFundsValidationStore.Account);
|
||||||
|
AssetTrio assets = validator.getStored(WithdrawalFundsValidationStore.AssetTrio);
|
||||||
|
TradingClearingRegistry tcr = validator.getStored(WithdrawalFundsValidationStore.TCR);
|
||||||
|
String curr = TextUtil.isEmpty(payload.getSecuritySymbol()) ? CurrencyCode.RUB.getKey() : payload.getSecuritySymbol();
|
||||||
|
|
||||||
|
Instant now = Instant.now();
|
||||||
|
LocalDate nowDate = TimeUtil.toLocalDate(now);
|
||||||
|
PaymentInstruction pmtIns = new PaymentInstruction();
|
||||||
|
pmtIns.setSenderId(payload.getSenderId());
|
||||||
|
pmtIns.setPayeeBic(cmpSymb.getCompanySymbolValue());
|
||||||
|
pmtIns.setAdresseeBic(payload.getDebitBIC());
|
||||||
|
pmtIns.setPayeeBankName(cmp.getShortName());
|
||||||
|
pmtIns.setAddresseeBankName(payload.getDebitBankName());
|
||||||
|
pmtIns.setPaymentDate(now);
|
||||||
|
pmtIns.setPaymentPurpose(extractPaymentPurpose(payload));
|
||||||
|
pmtIns.setSettlementDate(nowDate);
|
||||||
|
pmtIns.setCreditLeg_amount(payload.getAmount());
|
||||||
|
pmtIns.setDebitLeg_amount(payload.getAmount());
|
||||||
|
pmtIns.setCreditLeg_accountId(payload.getCreditLegAccountId());
|
||||||
|
pmtIns.setCreditLeg_account(acc.getAccount());
|
||||||
|
pmtIns.setDebit_csAccount(payload.getDebitCorrAccount());
|
||||||
|
pmtIns.setDebitLeg_account(payload.getDebitLegAccount());
|
||||||
|
pmtIns.setCreditLeg_direction(InOutDirection.out.getKey());
|
||||||
|
pmtIns.setDebitLeg_direction(InOutDirection.in.getKey());
|
||||||
|
pmtIns.setCreditLeg_currencyCode(payload.getSecuritySymbol());
|
||||||
|
pmtIns.setDebitLeg_currencyCode(payload.getSecuritySymbol());
|
||||||
|
pmtIns.setCreditLeg_securityId(payload.getSecurityId());
|
||||||
|
pmtIns.setDebitLeg_securityId(payload.getSecurityId());
|
||||||
|
pmtIns.setTransactionStatus(TransactionStatus.stld.getKey());
|
||||||
|
pmtIns.setCreated(now);
|
||||||
|
pmtIns.setClearingDate(nowDate);
|
||||||
|
pmtImdg.insert(pmtIns);
|
||||||
|
log.info("created PaymentInstruction.id={}", pmtIns.getId());
|
||||||
|
SDf54 sDf54;
|
||||||
|
try {
|
||||||
|
sDf54 = sdf54Creator.create(pmtIns);
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
log.error(ExceptionUtils.getStackTrace(e));
|
||||||
|
return failedResponse(req, now, pmtIns);
|
||||||
|
}
|
||||||
|
sDf54.setId(idGen.nextId());
|
||||||
|
sDf54.setGenerationId(pmtIns.getId());
|
||||||
|
sDf54.setRbankcode(pmtIns.getAdresseeBic());
|
||||||
|
sDf54.setC_acc_cred(pmtIns.getDebit_csAccount());
|
||||||
|
SpecifUtil.fillSegmentsBy35Symbols(pmtIns.getAddresseeBankName(),
|
||||||
|
sDf54::setRbanknam1,
|
||||||
|
sDf54::setRbanknam2,
|
||||||
|
sDf54::setRbanknam3,
|
||||||
|
sDf54::setRbanknam4,
|
||||||
|
sDf54::setRbanknam5);
|
||||||
|
SpecifUtil.fillSegmentsBy35Symbols(payload.getDebitCompanyName(),
|
||||||
|
sDf54::setRclientn1,
|
||||||
|
sDf54::setRclientn2,
|
||||||
|
sDf54::setRclientn3,
|
||||||
|
sDf54::setRclientn4
|
||||||
|
);
|
||||||
|
sDf54.setInn_cred(payload.getDebitINN());
|
||||||
|
sDf54.setKpp_cred(payload.getDebitKPP());
|
||||||
|
sdf54Imdg.insert(sDf54);
|
||||||
|
log.info("created sdf54.id={}", sDf54.getId());
|
||||||
|
|
||||||
|
dmiService.setProcComment(tcr.getId(),
|
||||||
|
curr,
|
||||||
|
safeBD(payload.getAmount()).negate(),
|
||||||
|
sDf54.getDocnm_ref());
|
||||||
|
log.debug("recalculating assests...");
|
||||||
|
assetsMng.process(assets.a__b(), assets.a__t(), assets.a__f(), BigDecimal.ZERO);
|
||||||
|
|
||||||
|
SdfClearingRequest exp = new SdfClearingRequest();
|
||||||
|
exp.setGroupId(sDf54.getGenerationId());
|
||||||
|
kafkaSender.sendRequestToQueue(Consts.SDF54_PROCESS, exp);
|
||||||
|
|
||||||
|
return reqHelp.success(req.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private RequestInfoUpdate failedResponse(BaseRequest<DmauRegistryRequest> req,
|
||||||
|
Instant now,
|
||||||
|
PaymentInstruction pmtIns) {
|
||||||
|
pmtIns.setTransactionStatus(TransactionStatus.fail.getKey());
|
||||||
|
pmtIns.setUpdated(now);
|
||||||
|
pmtImdg.update(pmtIns);
|
||||||
|
return reqHelp.error(req.getId(), ClearingError.GeneralError);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String extractPaymentPurpose(DmauRegistryRequest payload) {
|
||||||
|
if (!TextUtil.isEmpty(payload.getPaymentPurpose())) {
|
||||||
|
return payload.getPaymentPurpose();
|
||||||
|
}
|
||||||
|
if (CurrencyCode.RUB.equalsByKey(payload.getSecuritySymbol())) {
|
||||||
|
return "Вывод средств с регистра невыясненных денежных средств по %s"
|
||||||
|
.formatted(payload.getSecuritySymbol());
|
||||||
|
} else {
|
||||||
|
return "Withdrawal of funds from the register %s of unidentified funds"
|
||||||
|
.formatted(payload.getSecuritySymbol());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
package ru.spcex.clearing.service.validation;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import ru.clearing.classes.statics.data.account.Account;
|
||||||
|
import ru.clearing.classes.statics.data.company.Company;
|
||||||
|
import ru.clearing.classes.statics.data.registry.TradingClearingRegistry;
|
||||||
|
import ru.clearing.classes.statics.data.registry.TradingClearingRegistryList;
|
||||||
|
import ru.spcex.clearing.error.ClearingError;
|
||||||
|
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||||
|
import ru.spcex.clearing.platform.messaging.domain.cud.registry.DmauRegistryRequest;
|
||||||
|
import ru.spcex.clearing.service.AnltSearcher;
|
||||||
|
import ru.spcex.clearing.service.TcrSearcher;
|
||||||
|
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;
|
||||||
|
|
||||||
|
public enum WithdrawalFundsValidationRule implements IValidationRule<ImdgValidationContext<DmauRegistryRequest>> {
|
||||||
|
Fields() {
|
||||||
|
@Override
|
||||||
|
public Optional<EnumMessage> validate(ImdgValidationContext<DmauRegistryRequest> context) {
|
||||||
|
DmauRegistryRequest validatedObject = context.getValidatedObject();
|
||||||
|
if (validatedObject.getAmount() == null || validatedObject.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
|
return of(ClearingError.WrongField, "amount");
|
||||||
|
}
|
||||||
|
if (validatedObject.getBalance() == null || validatedObject.getBalance().compareTo(validatedObject.getAmount()) < 0) {
|
||||||
|
return of(ClearingError.WrongField, "balance");
|
||||||
|
}
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
TcrPresent() {
|
||||||
|
@Override
|
||||||
|
public Optional<EnumMessage> validate(ImdgValidationContext<DmauRegistryRequest> context) {
|
||||||
|
Account accCred = context.getStoredObject(WithdrawalFundsValidationStore.Account);
|
||||||
|
Company addressee = context.getStoredObject(WithdrawalFundsValidationStore.Company);
|
||||||
|
Imdg<TradingClearingRegistry> tcrImdg = context.obtainMap(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class);
|
||||||
|
Imdg<TradingClearingRegistryList> tcrListImdg = context.obtainMap(IMDGDistributedNames.Map_TradingClearingRegistryList, TradingClearingRegistryList.class);
|
||||||
|
Imdg<Company> companyImdg = context.obtainMap(IMDGDistributedNames.Map_Company, Company.class);
|
||||||
|
Imdg<Account> accountImdg = context.obtainMap(IMDGDistributedNames.Map_Account, Account.class);
|
||||||
|
TcrSearcher tcrSearcher = new TcrSearcher(tcrImdg, tcrListImdg, companyImdg, accountImdg);
|
||||||
|
AnltSearcher.AnltSearch srchRes = tcrSearcher.searchByAccountId(accCred.getId(), accCred.getCurrency());
|
||||||
|
if (!srchRes.isFound()) {
|
||||||
|
return Optional.of(srchRes.getError());
|
||||||
|
}
|
||||||
|
if (srchRes.getCompany() != null) {
|
||||||
|
if (!Objects.equals(srchRes.getCompany().getId(), addressee.getId())) {
|
||||||
|
return of(ClearingError.AccountIsNotMatchedWithCompany, accCred.getId(), addressee.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TradingClearingRegistry tcr = srchRes.getTcr();
|
||||||
|
if (tcr == null) {
|
||||||
|
return of(ClearingError.RecordNotFound, "TCR");
|
||||||
|
}
|
||||||
|
context.storeObject(WithdrawalFundsValidationStore.TCR, tcr);
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private final static Logger log = LoggerFactory.getLogger(WithdrawalFundsValidationRule.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String ruleName() {
|
||||||
|
return "WithdrawalFundsValidationRule." + name();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
package ru.spcex.clearing.service.validation;
|
||||||
|
|
||||||
|
public enum WithdrawalFundsValidationStore {
|
||||||
|
CompanySymbol,
|
||||||
|
Company,
|
||||||
|
Account,
|
||||||
|
AssetTrio,
|
||||||
|
TCR,
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,8 @@ package ru.spcex.platform.imdg.validation.rule;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import ru.spcex.platform.classes.base.SpcexObjectBase;
|
import ru.spcex.platform.classes.base.SpcexObjectBase;
|
||||||
import ru.spcex.platform.imdg.api.Imdg;
|
import ru.spcex.platform.imdg.api.Imdg;
|
||||||
import ru.spcex.platform.imdg.api.predicate.ImdgPredicate;
|
import ru.spcex.platform.imdg.api.predicate.ImdgPredicate;
|
||||||
|
|
@ -10,6 +12,7 @@ import ru.spcex.platform.utils.enumeration.EnumMessage;
|
||||||
import ru.spcex.platform.utils.validation.IValidationRule;
|
import ru.spcex.platform.utils.validation.IValidationRule;
|
||||||
|
|
||||||
public class PresentByPredicate<T> implements IValidationRule<ImdgValidationContext<T>> {
|
public class PresentByPredicate<T> implements IValidationRule<ImdgValidationContext<T>> {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(PresentByPredicate.class);
|
||||||
|
|
||||||
private final String mapName;
|
private final String mapName;
|
||||||
private final Function<T, EnumMessage> errorProvider;
|
private final Function<T, EnumMessage> errorProvider;
|
||||||
|
|
@ -42,8 +45,10 @@ public class PresentByPredicate<T> implements IValidationRule<ImdgValidationCont
|
||||||
|
|
||||||
if (obj == null) {
|
if (obj == null) {
|
||||||
EnumMessage errMsg = errorProvider.apply(validatedObject);
|
EnumMessage errMsg = errorProvider.apply(validatedObject);
|
||||||
|
log.debug("object not found by predicate: {}", predicate);
|
||||||
return Optional.of(errMsg);
|
return Optional.of(errMsg);
|
||||||
}
|
}
|
||||||
|
log.debug("object found by predicate [{}]: {}.id={}", predicate, mapName, obj.getId());
|
||||||
|
|
||||||
if (storeEnabled != null) {
|
if (storeEnabled != null) {
|
||||||
context.storeObject(storeEnabled, obj);
|
context.storeObject(storeEnabled, obj);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue