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 64998ecd5..a7fdb5a56 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 @@ -22,14 +22,18 @@ import ru.clearing.classes.statics.data.statement.Statement; import ru.clearing.platform.dictionary.SectionDictionary; import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.cud.payment.PIClearingOutbondActionNewRequest; import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryReturnDepositRequest; import ru.spcex.clearing.service.validation.*; +import ru.spcex.clearing.util.security.UserRoleVerification; +import ru.spcex.clearing.validation.common.rules.IdPresentRule; 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.imdg.validation.LogPrefixId; import ru.spcex.platform.imdg.validation.rule.PresentById; +import ru.spcex.platform.utils.enumeration.IMessageResolver; import ru.spcex.platform.utils.validation.IValidator; import ru.spcex.platform.utils.validation.ValidatorImpl; @@ -312,4 +316,35 @@ public class ValidationConfig { ); }; } + + @Bean + public Function piOutboundValidation() { + return pmtOut -> { + ImdgValidationContext ctx = new ImdgValidationContext<>(); + ctx.setValidatedObject(pmtOut); + ctx.addImdg(IMDGDistributedNames.Map_Company, imdgCompany); + ctx.addImdg(IMDGDistributedNames.Map_Account, imdgAccount); + return new ValidatorImpl<>(ctx, + PaymentOutboundValidationRule.RequiredFields, + IdPresentRule.instance("senderId", + PIClearingOutbondActionNewRequest::getSenderId, + IMDGDistributedNames.Map_Company, + Company.class, + ClearingError.RequiredFieldEmpty, + ClearingError.DictionaryNotFound), + IdPresentRule.instance("addresseeId", + PIClearingOutbondActionNewRequest::getAddresseeId, + IMDGDistributedNames.Map_Company, + Company.class, + ClearingError.RequiredFieldEmpty, + ClearingError.DictionaryNotFound), + PaymentOutboundValidationRule.CreditLegAccount, + PaymentOutboundValidationRule.DebitLegAccount); + }; + } + + @Bean("userRoleVerification") + public UserRoleVerification userRoleVerification(ImdgProvider imdgProvider, IMessageResolver msgs) { + return new UserRoleVerification(imdgProvider, msgs, ClearingError.UserVerifyDenial); + } } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingError.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingError.java index fb238e9c8..49e05c2cd 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingError.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingError.java @@ -3,7 +3,11 @@ package ru.spcex.clearing.error; import ru.spcex.platform.utils.enumeration.IErrorEnumId; public enum ClearingError implements IErrorEnumId { + WrongFieldValue(1004L), GeneralError(5400L), + UserVerifyDenial(5001L), + RequiredFieldEmpty(5002L), + DictionaryNotFound(5003L), DepoAccNotFound(5011L), RecordNotFoundInDictionary(5423L), IncorrectValue(5404L), 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 8c956a2b4..52f735c9b 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 @@ -14,12 +14,14 @@ import ru.spcex.clearing.platform.messaging.domain.cud.clearing.Sdf04Request; import ru.spcex.clearing.platform.messaging.domain.cud.clearing.SessionContinueEvent; 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.RegistryReturnDepositRequest; import ru.spcex.clearing.platform.messaging.domain.cud.schedule.LauncherCommandRequest; import ru.spcex.clearing.platform.messaging.domain.cud.utilities.STradesImportedRequest; import ru.spcex.clearing.platform.messaging.service.QueueConsumer; 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.session.stage.*; import ru.spcex.clearing.session.stage.impl.BalanceRevise; import ru.spcex.platform.enumeration.Task; @@ -43,6 +45,7 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean { private final Sdf10Executor sdf10Executor; private final BalanceRevise balanceRevise; private final Sdf05Sender sdf05Sender; + private final PaymentInstructionOutboundService pmtOutboundService; @Autowired public EventsReceiver(Consumer kafkaQueue, Producer kafkaResponseQueue, @@ -52,7 +55,7 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean { SecondaryAuctionT0Session secondaryAuctionT0Session, PrimaryAuctionB0Session primaryAuctionB0Session, PrimaryAuctionT0Session primaryAuctionT0Session, IntermediateMkrSession intermediateMkrSession, FinalMkrSession finalMkrSession, ReturnDepositSession returnDepositSession, SessionManager sessionManager, Sdf06Executor sdf06Executor, - Sdf10Executor sdf10Executor, BalanceRevise balanceRevise, Sdf05Sender sdf05Sender) { + Sdf10Executor sdf10Executor, BalanceRevise balanceRevise, Sdf05Sender sdf05Sender, PaymentInstructionOutboundService pmtOutboundService) { super(kafkaQueue, kafkaResponseQueue); this.clearingService = clearingService; this.registryService = registryService; @@ -68,6 +71,7 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean { this.sdf10Executor = sdf10Executor; this.balanceRevise = balanceRevise; this.sdf05Sender = sdf05Sender; + this.pmtOutboundService = pmtOutboundService; } @Override @@ -92,6 +96,9 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean { .setConsumer(sessionManager::defineAndStartSession) .forDestination(Task.startOfClearing.topic(), callbacks::put); + callback(PIClearingOutbondActionNewRequest.class) + .setFunction(pmtOutboundService::sendOutBoundPayment) + .forDestination(Consts.PAYMENT_INSTRUCTION_CLEARING_OUTBOUND_ACTION, callbacks::put); callback(SessionContinueEvent.class) .setConsumer(req -> { primaryAuctionBnSession.continueSession(req); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Sdf54Creator.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Sdf54Creator.java new file mode 100644 index 000000000..d35304dd2 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/Sdf54Creator.java @@ -0,0 +1,175 @@ +package ru.spcex.clearing.service; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import ru.clearing.classes.statics.data.account.Account; +import ru.clearing.classes.statics.data.account.BankAccount; +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.imdg.IMDGDistributedNames; +import ru.spcex.platform.enumeration.AccountType; +import ru.spcex.platform.enumeration.CompanySymbol; +import ru.spcex.platform.enumeration.Sender; +import ru.spcex.platform.enumeration.Status; +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.IEnumKey; +import ru.spcex.platform.utils.number.BigDecimalUtil; +import ru.spcex.platform.utils.time.TimeUtil; + +import java.time.Instant; +import java.time.format.DateTimeFormatter; +import java.util.Map; + +@Component +public class Sdf54Creator { + private Logger log = LoggerFactory.getLogger(getClass()); + private final Imdg tradingClearingRegistryImdg; + private final Imdg companyImdg; + private final Imdg companySymbolImdg; + private final Imdg accountImdg; + private final Imdg bankAccountImdg; + private final ImdgId idGenerator; + private static DateTimeFormatter payDateFormatter = DateTimeFormatter.ofPattern("dd.MM.yy"); + + public Sdf54Creator(ImdgProvider imdgProvider) { + this.tradingClearingRegistryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class); + this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class); + this.accountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class); + this.companySymbolImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CompanySymbols, CompanySymbols.class); + this.bankAccountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_BankAccount, BankAccount.class); + this.idGenerator = imdgProvider.getImdgIdGenerator(); + } + + public SDf54 create(PaymentInstruction paymentInstruction) { + AccountType creditAccType = getAccountType(paymentInstruction.getCreditLeg_accountId()); + AccountType debAccType = getAccountType(paymentInstruction.getDebitLeg_accountId()); + String c_acc_deb = null; + String c_acc_cred = null; + Account anltAcc = accountImdg.getFirstObjectBySQL("accountType = '%s' and status = '%s'" + .formatted(AccountType.Anlt.getKey(), Status.Active.getKey())); + if (AccountType.Info.equals(creditAccType) ^ AccountType.Info.equals(debAccType)) { + if (anltAcc == null) { + throw new IllegalStateException("SDF54 creation error: paymentInstruction.creditLeg_accountId=" + + paymentInstruction.getCreditLeg_accountId() + " accountType 'Info' but no 'ANLT' account found"); + } + if (AccountType.Info.equals(creditAccType)) { + c_acc_deb = anltAcc.getAccount(); + } else { + c_acc_cred = anltAcc.getAccount(); + } + } + c_acc_deb = c_acc_deb == null ? paymentInstruction.getCreditLeg_account() : c_acc_deb; + c_acc_cred = c_acc_cred == null ? paymentInstruction.getDebitLeg_account() : c_acc_cred; + + + SDf54 sDf54 = new SDf54(); + sDf54.setId(idGenerator.nextId()); + sDf54.setSeg_type("V"); + + //********************** + String tranBic = selectSymbolValue(Sender.Prc.getId(), CompanySymbol.BIC); + if (tranBic == null) { + log.warn("CompanySymbols BIC not found for companyId={}", Sender.Prc.getId()); + } else { + sDf54.setSbankcode(tranBic); + } + Company prcCmp = companyImdg.getSingleObjectByID(Sender.Prc.getId()); + String senderSbankName = ""; + if (prcCmp != null) { + senderSbankName = prcCmp.getShortName(); + } + SpecifUtil.fillSegmentsBy35Symbols(senderSbankName, + sDf54::setSbanknam1, + sDf54::setSbanknam2, + sDf54::setSbanknam3, + sDf54::setSbanknam4, + sDf54::setSbanknam5); + sDf54.setOp_type("01"); + sDf54.setOp_order("5"); + String innDeb = selectSymbolValue(Sender.One.getId(), CompanySymbol.INN); + if (innDeb == null) { + log.warn("CompanySymbols INN not found for companyId={}", Sender.One.getId()); + } else { + sDf54.setInn_deb(innDeb); + } + String kppDeb = selectSymbolValue(Sender.One.getId(), CompanySymbol.CPP); + if (kppDeb == null) { + log.warn("CompanySymbols CPP not found for companyId={}", Sender.One.getId()); + } else { + sDf54.setKpp_deb(kppDeb); + } + + if (anltAcc != null) { + sDf54.setAcc_deb(anltAcc.getAccount()); + } + BankAccount bnkAcc = bankAccountImdg.getFirstObjectBySQL("accountId = %d".formatted(paymentInstruction.getDebitLeg_accountId())); + if (bnkAcc != null) { + sDf54.setInn_cred(bnkAcc.getTaxpayerIdentificationNumber()); + sDf54.setKpp_cred(bnkAcc.getTaxRegistrationReasonCode()); + } + sDf54.setAcc_kr_1(paymentInstruction.getDebitLeg_account()); + //********************** + + + sDf54.setDoc_type("002"); + String strId = paymentInstruction.getId().toString(); + String strIdCut = strId.length() > 16 ? strId.substring(strId.length() - 16) : strId; + sDf54.setDocnm_ref(strIdCut); + sDf54.setC_acc_deb(c_acc_deb); + + + + sDf54.setC_acc_cred(c_acc_cred); + + String addresseeSbankName = ""; + if (paymentInstruction.getAddresseeId().equals(1L)) { + addresseeSbankName = paymentInstruction.getAddresseeBankName(); + } else { + Company company = companyImdg.getSingleObjectByID(paymentInstruction.getAddresseeId()); + if (company != null) { + addresseeSbankName = company.getShortName(); + } + } + + SpecifUtil.fillSegmentsBy35Symbols(addresseeSbankName, + sDf54::setRbanknam1, + sDf54::setRbanknam2, + sDf54::setRbanknam3, + sDf54::setRbanknam4, + sDf54::setRbanknam5); + + sDf54.setPay_date(payDateFormatter.format(TimeUtil.toLocalDate(paymentInstruction.getPaymentDate()))); + sDf54.setPay_val("RUR"); + String sumDeb = paymentInstruction.getDebitLeg_amount() != null ? paymentInstruction.getDebitLeg_amount().toString() : ""; + sDf54.setSum_deb(BigDecimalUtil.limitDecimalPlaces(sumDeb, 2)); + sDf54.setSpecif_1(paymentInstruction.getPaymentPurpose()); + sDf54.setGenerationTime(Instant.now()); + log.debug("paymentInstruction.id={}, sdf54.id {}", paymentInstruction.getId(), sDf54.getId()); + return sDf54; + } + + private AccountType getAccountType(Long accountId) { + Account account = accountImdg.getSingleObjectByID(accountId); + return IEnumKey.getEnumByKey(AccountType.class, account.getAccountType()); + } + + protected String selectSymbolValue(Long companyId, CompanySymbol symbol) { + if (companyId == null) { + return null; + } + CompanySymbols cSymbol = companySymbolImdg.getFirstObjectByFieldValues(Map.of( + "companyId", companyId, + "companySymbol", symbol.getKey())); + if (cSymbol == null) { + return null; + } else { + return cSymbol.getCompanySymbolValue(); + } + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf06Executor.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf06Executor.java index 6af94fa15..db1f477b6 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf06Executor.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf06Executor.java @@ -131,15 +131,12 @@ public class Sdf06Executor { if (err.isPresent()) { log.debug("sdf06.id={} validation error: {}", sDf06.getId(), messageResolver.resolve(err.get())); SDf07 errorSdf07; - BigDecimal errorResult; + BigDecimal errorResult = errorById(err.get()); Statement stmt = null; if (needToCreateStatement(err.get())) { - errorResult = errorById(err.get()); stmt = createStatementBySdf06(sDf06, ((Company) validator.getStored(ValidationStored.Sdf06Company)).getId(), validator.getStored(ValidationStored.Sdf06Account)); - } else { - errorResult = errorResult2; } errorSdf07 = createSdf07(sDf06, now, errorResult); errorSdf07.setGenerationId(sdf07GroupId); @@ -203,7 +200,12 @@ public class Sdf06Executor { if (ClearingError.BalanceInsufficient.equals(err.getSubject())) { return errorResult3; } - return errorResult1; + if ( ClearingError.CompanyNotFoundB.equals(err.getSubject()) + || ClearingError.AccountNotFoundB.equals(err.getSubject()) + || ClearingError.TCRegistryNotFound.equals(err.getSubject())) { + return errorResult2; + } + return errorResult2; } public void processGatewayResponse(BaseRequest req) { diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/payment/PaymentInstructionOutboundService.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/payment/PaymentInstructionOutboundService.java new file mode 100644 index 000000000..d1ea34713 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/payment/PaymentInstructionOutboundService.java @@ -0,0 +1,155 @@ +package ru.spcex.clearing.service.payment; + +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.account.Account; +import ru.clearing.classes.statics.data.account.BankAccount; +import ru.clearing.classes.statics.data.company.Company; +import ru.clearing.classes.statics.data.misc.Currency; +import ru.clearing.classes.statics.data.payment.PaymentInstruction; +import ru.clearing.classes.statics.data.registry.Registry; +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.payment.PIClearingOutbondActionNewRequest; +import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate; +import ru.spcex.clearing.platform.messaging.service.Status; +import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; +import ru.spcex.clearing.service.RegistryManager; +import ru.spcex.clearing.service.Sdf54Creator; +import ru.spcex.clearing.service.builder.PaymentInstructionBuilderV2; +import ru.spcex.clearing.service.validation.ValidationStored; +import ru.spcex.clearing.util.security.UserRoleVerification; +import ru.spcex.platform.enumeration.CurrencyCode; +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.IEnumId; +import ru.spcex.platform.utils.enumeration.IMessageResolver; +import ru.spcex.platform.utils.validation.IValidator; + +import java.math.BigDecimal; +import java.util.Optional; +import java.util.function.Function; + +@Service +public class PaymentInstructionOutboundService { + private final Logger log = LoggerFactory.getLogger(getClass()); + private final UserRoleVerification rights; + private final IMessageResolver msgs; + private final Function validation; + private final ImdgProvider imdgProvider; + private final ImdgId idGenerator; + private final Imdg pmtImdg; + private final Imdg cmpImdg; + private final Imdg bnkAccImdg; + private final Imdg rgsImdg; + private final Imdg tcrImdg; + private final Imdg currImdg; + private final Imdg sdf54Imdg; + private final RegistryManager rgsMng; + private final Sdf54Creator sdf54Creator; + private final KafkaSender kafkaSender; + + @Autowired + public PaymentInstructionOutboundService(UserRoleVerification rights, + IMessageResolver msgs, + ImdgProvider imdgProvider, + Function validation, RegistryManager rgsMng, KafkaSender kafkaSender) { + this.imdgProvider = imdgProvider; + this.rights = rights; + this.msgs = msgs; + this.validation = validation; + this.pmtImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_PaymentInstruction, PaymentInstruction.class); + this.cmpImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class); + this.tcrImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class); + this.bnkAccImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_BankAccount, BankAccount.class); + this.rgsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); + this.currImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Currency, Currency.class); + this.sdf54Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf54, SDf54.class); + this.sdf54Creator = new Sdf54Creator(imdgProvider); + this.idGenerator = imdgProvider.getImdgIdGenerator(); + this.rgsMng = rgsMng; + this.kafkaSender = kafkaSender; + } + + public RequestInfoUpdate sendOutBoundPayment(BaseRequest req) { + log.info("new PIClearingOutbondActionNewRequest.id: {}", req.getId()); + PIClearingOutbondActionNewRequest payload = req.getRequestPayload(); + if (!rights.userHasRole(req.getUserId(), UserRole.Admin)) { + return error(req.getId(), ClearingError.UserVerifyDenial); + } + IValidator validator = validation.apply(payload); + Optional validationErr = validator.tillFirstError(); + if (validationErr.isPresent()) { + return error(req.getId(), validationErr.get()); + } + Account accCred = validator.getStored(ValidationStored.PIOutboundAccountCred); + Account accDeb = validator.getStored(ValidationStored.PIOutboundAccountDeb); + Company addressee = cmpImdg.getSingleObjectByID(payload.getAddresseeId()); + Company sender = cmpImdg.getSingleObjectByID(payload.getSenderId()); + BigDecimal amount = payload.getCreditLeg_amount(); + log.debug("all checks passed, accCred.id={}, accDeb.id={}, addressee.id={}, sender.id={}, amount: {}", + accCred.getId(), accDeb.getId(), addressee.getId(), sender.getId(), amount); + + TradingClearingRegistry tcr = tcrImdg.getFirstObjectBySQL("moneyAccountId = '%d' and companyId = %d" + .formatted(accCred.getId(), addressee.getId())); + PaymentInstruction pmt = PaymentInstructionBuilderV2.builder(imdgProvider) + .registry(new Registry()) + .sender(addressee.getId()) + .addressee(addressee.getId()) + .debitLegAccount(accDeb) + .creditLegAccount(accCred) + .amount(amount) + .sessionId(null) + .purpose(tcr != null ? "Вывод средств по ТКР " + tcr.getCode() : "Вывод средств") + .build(); + BankAccount bnkAcc = bnkAccImdg.getFirstObjectBySQL("accountId = %d".formatted(accDeb.getId())); + if (bnkAcc != null) { + pmt.setAddresseeBankName(bnkAcc.getBankIdentificationCode()); + pmt.setDebit_csAccount(bnkAcc.getCorrespondentAccount()); + } + Currency currency = currImdg.getFirstObjectBySQL("currencyCode = '%s'".formatted(CurrencyCode.RUB.getKey())); + if (currency != null) { + pmt.setCreditLeg_securityId(currency.getId()); + pmt.setDebitLeg_securityId(currency.getId()); + } + pmt.setTransactionStatus(TransactionStatus.exec.getKey()); + //fixme pmt.setDocumentNumber(registry.getSecurityId()); + + pmtImdg.insert(pmt); + log.debug("new PaymentInstruction.id: {}", pmt.getId()); + SDf54 sDf54 = sdf54Creator.create(pmt); + Long sdf54Id = idGenerator.nextId(); + sDf54.setId(sdf54Id); + sDf54.setGenerationId(sdf54Id); + sdf54Imdg.insert(sDf54); + log.debug("new sdf54.id: {}", sDf54.getId()); + SdfClearingRequest exp = new SdfClearingRequest(); + exp.setGroupId(sdf54Id); + kafkaSender.sendRequestToQueue(Consts.SDF54_PROCESS, exp); + return success(req.getId()); + } + + private RequestInfoUpdate error(Long id, EnumMessage err) { + return new RequestInfoUpdate(id, Status.Error, msgs.resolve(err)); + } + + private RequestInfoUpdate error(Long id, IEnumId sbj, Object... args) { + EnumMessage error = new EnumMessage(sbj, args); + return new RequestInfoUpdate(id, Status.Error, msgs.resolve(error)); + } + + private RequestInfoUpdate success(Long id) { + return new RequestInfoUpdate(id, Status.Success, null); + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/PaymentOutboundValidationRule.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/PaymentOutboundValidationRule.java new file mode 100644 index 000000000..7ad54df63 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/PaymentOutboundValidationRule.java @@ -0,0 +1,85 @@ +package ru.spcex.clearing.service.validation; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ru.clearing.classes.statics.data.account.Account; +import ru.spcex.clearing.error.ClearingError; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.cud.payment.PIClearingOutbondActionNewRequest; +import ru.spcex.platform.enumeration.AccountType; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; +import ru.spcex.platform.imdg.validation.ImdgValidationContext; +import ru.spcex.platform.utils.enumeration.EnumMessage; +import ru.spcex.platform.utils.validation.IValidationRule; + +import java.util.Optional; + +public enum PaymentOutboundValidationRule implements IValidationRule> { + RequiredFields() { + @Override + public Optional validate(ImdgValidationContext context) { + PIClearingOutbondActionNewRequest pmtOut = context.getValidatedObject(); + if (pmtOut.getSenderId() == null) { + return of(ClearingError.RequiredFieldEmpty, "senderId"); + } + if (pmtOut.getAddresseeId() == null) { + return of(ClearingError.RequiredFieldEmpty, "addresseeId"); + } + if (pmtOut.getCreditLeg_amount() == null) { + return of(ClearingError.RequiredFieldEmpty, "creditLeg_amount"); + } + if (pmtOut.getCreditLeg_accountId() == null) { + return of(ClearingError.RequiredFieldEmpty, "creditLeg_accountId"); + } + if (pmtOut.getDebitLeg_accountId() == null) { + return of(ClearingError.RequiredFieldEmpty, "debitLeg_accountId"); + } + return empty(); + } + }, + CreditLegAccount() { + @Override + public Optional validate(ImdgValidationContext context) { + PIClearingOutbondActionNewRequest pmtOut = context.getValidatedObject(); + Imdg accImdg = context.obtainMap(IMDGDistributedNames.Map_Account, Account.class); + ImdgPredicateBuilder pb = accImdg.predicateBuilder(); + Account acc = accImdg.getSingleObjectByPredicate( + pb.and( + pb.equals("id", pmtOut.getCreditLeg_accountId()), + pb.equals("accountType", AccountType.Info.getKey()) + ) + ); + if (acc == null) { + return of(ClearingError.WrongFieldValue, "creditLeg_accountId"); + } + context.storeObject(ValidationStored.PIOutboundAccountCred, acc); + return empty(); + } + }, + DebitLegAccount() { + @Override + public Optional validate(ImdgValidationContext context) { + PIClearingOutbondActionNewRequest pmtOut = context.getValidatedObject(); + Imdg accImdg = context.obtainMap(IMDGDistributedNames.Map_Account, Account.class); + ImdgPredicateBuilder pb = accImdg.predicateBuilder(); + Account acc = accImdg.getSingleObjectByPredicate( + pb.and( + pb.equals("id", pmtOut.getDebitLeg_accountId()), + pb.equals("accountType", AccountType.Bank.getKey()) + ) + ); + if (acc == null) { + return of(ClearingError.WrongFieldValue, "debitLeg_accountId"); + } + context.storeObject(ValidationStored.PIOutboundAccountDeb, acc); + return empty(); + } + }, + ; + private final static Logger log = LoggerFactory.getLogger(PaymentOutboundValidationRule.class); + @Override + public String ruleName() { + return "PaymentOutboundValidationRule." + 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 847b2603b..64d18121c 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 @@ -14,6 +14,8 @@ public enum ValidationStored { Sdf21Account, + PIOutboundAccountDeb, PIOutboundAccountCred, + Sdf06Company, Sdf06Account, Sdf06Tcr, ReturnDepositDmx, diff --git a/clearing-parent/security-util/src/main/java/ru/spcex/clearing/util/security/UserRoleVerification.java b/clearing-parent/security-util/src/main/java/ru/spcex/clearing/util/security/UserRoleVerification.java index 857550147..4141b7725 100644 --- a/clearing-parent/security-util/src/main/java/ru/spcex/clearing/util/security/UserRoleVerification.java +++ b/clearing-parent/security-util/src/main/java/ru/spcex/clearing/util/security/UserRoleVerification.java @@ -38,7 +38,6 @@ public class UserRoleVerification { public UserRoleVerification(ImdgProvider imdg, IMessageResolver messageResolver, IErrorEnumId roleVerificationError) { - Objects.requireNonNull(roleForVerification); Objects.requireNonNull(roleVerificationError); Objects.requireNonNull(messageResolver); userRoleSessions = imdg.getImdg(IMDGDistributedNames.Map_UserRoleSession, UserRoleSession.class); @@ -62,7 +61,7 @@ public class UserRoleVerification { this.roleForVerification = roleForVerification; } - protected boolean userHasRole(Long userId, IEnumKey role) { + public boolean userHasRole(Long userId, IEnumKey role) { return userHasRole(userId, role == null ? null : role.getKey()); } diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/TransactionStatus.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/TransactionStatus.java index 554033e55..297202e76 100644 --- a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/TransactionStatus.java +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/TransactionStatus.java @@ -3,7 +3,7 @@ package ru.spcex.platform.enumeration; import ru.spcex.platform.utils.enumeration.IEnumKey; public enum TransactionStatus implements IEnumKey { - stld("STLD"), notSent("NSNT"), cher("CHER"), sent("SENT"), ok("OK"), fail("FAIL"); + stld("STLD"), notSent("NSNT"), cher("CHER"), sent("SENT"), ok("OK"), fail("FAIL"), exec("EXEC"); private final String key;