From 9223d8b391863dbdeaf21b23a8f1e71686f4e097 Mon Sep 17 00:00:00 2001 From: ialbert Date: Wed, 29 Apr 2026 15:05:20 +0300 Subject: [PATCH] http://jira.mfd.msk:8088/browse/CLS-981 --- .../clearing/config/ValidationConfig.java | 92 ++++++++- .../clearing/service/EventsReceiver.java | 9 +- .../payment/WithdrawalFundsService.java | 192 ++++++++++++++++++ .../WithdrawalFundsValidationRule.java | 69 +++++++ .../WithdrawalFundsValidationStore.java | 10 + .../validation/rule/PresentByPredicate.java | 5 + 6 files changed, 375 insertions(+), 2 deletions(-) create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/payment/WithdrawalFundsService.java create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/WithdrawalFundsValidationRule.java create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/WithdrawalFundsValidationStore.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 index 049b76667..1a1fde574 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 @@ -1,5 +1,6 @@ package ru.spcex.clearing.config; +import java.util.Optional; import java.util.function.BiFunction; import java.util.function.Function; 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.platform.messaging.domain.cud.balance.StatementRequest; 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.RegistryChangeRefundDateRequest; 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.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.ClrngValidationStored; 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.SplitDepositRequestValidationRule; 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.validation.common.rules.DictionaryPresentRule; import ru.spcex.clearing.validation.common.rules.FieldRequiredRule; import ru.spcex.clearing.validation.common.rules.IdPresentRule; 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.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.LogPrefixId; import ru.spcex.platform.imdg.validation.rule.CurrencyCodeValidationRule; 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.validation.IValidationRule; import ru.spcex.platform.utils.validation.IValidator; import ru.spcex.platform.utils.validation.ValidatorImpl; @@ -113,8 +126,9 @@ public class ValidationConfig { Imdg pmtImdg; Imdg ctgrImdg; ImdgProvider imdgProvider; + AssetTBFProcessing assetsMng; - public ValidationConfig(ImdgProvider imdgProvider) { + public ValidationConfig(ImdgProvider imdgProvider, AssetTBFProcessing assetsMng) { this.imdgRelation = imdgProvider.getImdg(IMDGDistributedNames.Map_Relation, Relation.class); this.imdgCompany = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.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.digitalCertificateSecurityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_DigitalCertificateSecurity, DigitalCertificateSecurity.class); this.imdgProvider = imdgProvider; + this.assetsMng = assetsMng; } //@Bean("adminRoleVerification") @@ -399,6 +414,81 @@ public class ValidationConfig { }; } + @Bean("withdrawalFundsValidator") + public Function withdrawalFundsValidator() { + return identificationFundsRequest -> { + ImdgValidationContext 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) 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>() { + @Override + public Optional validate(ImdgValidationContext ctx) { + Company cmp = ctx.getStoredObject(WithdrawalFundsValidationStore.Company); + Account acc = ctx.getStoredObject(WithdrawalFundsValidationStore.Account); + Optional 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") public Function splitDepositValidator() { return refundDateRequest -> { diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/EventsReceiver.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/EventsReceiver.java index 5a4698be4..ebab4d998 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/EventsReceiver.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/EventsReceiver.java @@ -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.gateway.AssetOperationApprovalRequest; 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.RegistryChangeRefundDateRequest; 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.Sdf10Executor; 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.TaskType; 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 SessionTerminator sessionTerminator; private final PaymentInstructionOutboundService pmtOutboundService; + private final WithdrawalFundsService withdrawalFundsService; private final ExecutionCurrencyComponent execCurrUpload; private final ExecutionDepositComponent execDepUpload; private final ExecutionFondComponent execFondUpload; @@ -81,7 +84,7 @@ public class EventsReceiver extends QueueConsumerV2 implements InitializingBean Sdf05Sender sdf05Sender, StatementServiceV2 statementService, SessionTerminator sessionTerminator, - PaymentInstructionOutboundService pmtOutboundService, + PaymentInstructionOutboundService pmtOutboundService, WithdrawalFundsService withdrawalFundsService, ExecutionCurrencyComponent execCurrUpload, ExecutionDepositComponent execDepUpload, ExecutionFondComponent execFondUpload) { @@ -98,6 +101,7 @@ public class EventsReceiver extends QueueConsumerV2 implements InitializingBean this.statementService = statementService; this.sessionTerminator = sessionTerminator; this.pmtOutboundService = pmtOutboundService; + this.withdrawalFundsService = withdrawalFundsService; this.execCurrUpload = execCurrUpload; this.execDepUpload = execDepUpload; this.execFondUpload = execFondUpload; @@ -144,6 +148,9 @@ public class EventsReceiver extends QueueConsumerV2 implements InitializingBean callback(PIClearingOutbondActionNewRequest.class) .setFunction(pmtOutboundService::sendOutBoundPayment) .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) .setConsumer(statementService::processReq) .forDestination(Consts.STATEMENT_PROCESS, callbacks::put); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/payment/WithdrawalFundsService.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/payment/WithdrawalFundsService.java new file mode 100644 index 000000000..5a6da932a --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/payment/WithdrawalFundsService.java @@ -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 withdrawalFundsVal; + private final Sdf54Creator sdf54Creator; + private final Imdg sdf54Imdg; + private final Imdg 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 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 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 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 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()); + } + } + +} + diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/WithdrawalFundsValidationRule.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/WithdrawalFundsValidationRule.java new file mode 100644 index 000000000..9d27ac50a --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/WithdrawalFundsValidationRule.java @@ -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> { + Fields() { + @Override + public Optional validate(ImdgValidationContext 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 validate(ImdgValidationContext context) { + Account accCred = context.getStoredObject(WithdrawalFundsValidationStore.Account); + Company addressee = context.getStoredObject(WithdrawalFundsValidationStore.Company); + Imdg tcrImdg = context.obtainMap(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class); + Imdg tcrListImdg = context.obtainMap(IMDGDistributedNames.Map_TradingClearingRegistryList, TradingClearingRegistryList.class); + Imdg companyImdg = context.obtainMap(IMDGDistributedNames.Map_Company, Company.class); + Imdg 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(); + } +} \ No newline at end of file diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/WithdrawalFundsValidationStore.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/WithdrawalFundsValidationStore.java new file mode 100644 index 000000000..55882c5e1 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/WithdrawalFundsValidationStore.java @@ -0,0 +1,10 @@ +package ru.spcex.clearing.service.validation; + +public enum WithdrawalFundsValidationStore { + CompanySymbol, + Company, + Account, + AssetTrio, + TCR, + ; +} diff --git a/platform-parent/platform-imdg-api/src/main/java/ru/spcex/platform/imdg/validation/rule/PresentByPredicate.java b/platform-parent/platform-imdg-api/src/main/java/ru/spcex/platform/imdg/validation/rule/PresentByPredicate.java index 5269785bc..c38ec4be8 100644 --- a/platform-parent/platform-imdg-api/src/main/java/ru/spcex/platform/imdg/validation/rule/PresentByPredicate.java +++ b/platform-parent/platform-imdg-api/src/main/java/ru/spcex/platform/imdg/validation/rule/PresentByPredicate.java @@ -2,6 +2,8 @@ package ru.spcex.platform.imdg.validation.rule; import java.util.Optional; import java.util.function.Function; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import ru.spcex.platform.classes.base.SpcexObjectBase; import ru.spcex.platform.imdg.api.Imdg; 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; public class PresentByPredicate implements IValidationRule> { + private static final Logger log = LoggerFactory.getLogger(PresentByPredicate.class); private final String mapName; private final Function errorProvider; @@ -42,8 +45,10 @@ public class PresentByPredicate implements IValidationRule