PaymentInstruction Outbound

SDf06
This commit is contained in:
ialbert 2023-08-17 19:27:24 +03:00
parent 848c26d69a
commit 745a13a8f8
10 changed files with 473 additions and 9 deletions

View file

@ -22,14 +22,18 @@ import ru.clearing.classes.statics.data.statement.Statement;
import ru.clearing.platform.dictionary.SectionDictionary; import ru.clearing.platform.dictionary.SectionDictionary;
import ru.spcex.clearing.error.ClearingError; 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.payment.PIClearingOutbondActionNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryReturnDepositRequest; import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryReturnDepositRequest;
import ru.spcex.clearing.service.validation.*; 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.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.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.PresentById; 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.IValidator;
import ru.spcex.platform.utils.validation.ValidatorImpl; import ru.spcex.platform.utils.validation.ValidatorImpl;
@ -312,4 +316,35 @@ public class ValidationConfig {
); );
}; };
} }
@Bean
public Function<PIClearingOutbondActionNewRequest, IValidator> piOutboundValidation() {
return pmtOut -> {
ImdgValidationContext<PIClearingOutbondActionNewRequest> 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);
}
} }

View file

@ -3,7 +3,11 @@ package ru.spcex.clearing.error;
import ru.spcex.platform.utils.enumeration.IErrorEnumId; import ru.spcex.platform.utils.enumeration.IErrorEnumId;
public enum ClearingError implements IErrorEnumId { public enum ClearingError implements IErrorEnumId {
WrongFieldValue(1004L),
GeneralError(5400L), GeneralError(5400L),
UserVerifyDenial(5001L),
RequiredFieldEmpty(5002L),
DictionaryNotFound(5003L),
DepoAccNotFound(5011L), DepoAccNotFound(5011L),
RecordNotFoundInDictionary(5423L), RecordNotFoundInDictionary(5423L),
IncorrectValue(5404L), IncorrectValue(5404L),

View file

@ -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.clearing.SessionContinueEvent;
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.registry.RegistryReturnDepositRequest; 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.schedule.LauncherCommandRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.utilities.STradesImportedRequest; import ru.spcex.clearing.platform.messaging.domain.cud.utilities.STradesImportedRequest;
import ru.spcex.clearing.platform.messaging.service.QueueConsumer; import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
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.session.stage.*; import ru.spcex.clearing.session.stage.*;
import ru.spcex.clearing.session.stage.impl.BalanceRevise; import ru.spcex.clearing.session.stage.impl.BalanceRevise;
import ru.spcex.platform.enumeration.Task; import ru.spcex.platform.enumeration.Task;
@ -43,6 +45,7 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean {
private final Sdf10Executor sdf10Executor; private final Sdf10Executor sdf10Executor;
private final BalanceRevise balanceRevise; private final BalanceRevise balanceRevise;
private final Sdf05Sender sdf05Sender; private final Sdf05Sender sdf05Sender;
private final PaymentInstructionOutboundService pmtOutboundService;
@Autowired @Autowired
public EventsReceiver(Consumer<String, Object> kafkaQueue, Producer<String, Object> kafkaResponseQueue, public EventsReceiver(Consumer<String, Object> kafkaQueue, Producer<String, Object> kafkaResponseQueue,
@ -52,7 +55,7 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean {
SecondaryAuctionT0Session secondaryAuctionT0Session, SecondaryAuctionT0Session secondaryAuctionT0Session,
PrimaryAuctionB0Session primaryAuctionB0Session, PrimaryAuctionT0Session primaryAuctionT0Session, IntermediateMkrSession intermediateMkrSession, FinalMkrSession finalMkrSession, ReturnDepositSession returnDepositSession, SessionManager sessionManager, PrimaryAuctionB0Session primaryAuctionB0Session, PrimaryAuctionT0Session primaryAuctionT0Session, IntermediateMkrSession intermediateMkrSession, FinalMkrSession finalMkrSession, ReturnDepositSession returnDepositSession, SessionManager sessionManager,
Sdf06Executor sdf06Executor, Sdf06Executor sdf06Executor,
Sdf10Executor sdf10Executor, BalanceRevise balanceRevise, Sdf05Sender sdf05Sender) { Sdf10Executor sdf10Executor, BalanceRevise balanceRevise, Sdf05Sender sdf05Sender, PaymentInstructionOutboundService pmtOutboundService) {
super(kafkaQueue, kafkaResponseQueue); super(kafkaQueue, kafkaResponseQueue);
this.clearingService = clearingService; this.clearingService = clearingService;
this.registryService = registryService; this.registryService = registryService;
@ -68,6 +71,7 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean {
this.sdf10Executor = sdf10Executor; this.sdf10Executor = sdf10Executor;
this.balanceRevise = balanceRevise; this.balanceRevise = balanceRevise;
this.sdf05Sender = sdf05Sender; this.sdf05Sender = sdf05Sender;
this.pmtOutboundService = pmtOutboundService;
} }
@Override @Override
@ -92,6 +96,9 @@ public class EventsReceiver extends QueueConsumer implements InitializingBean {
.setConsumer(sessionManager::defineAndStartSession) .setConsumer(sessionManager::defineAndStartSession)
.forDestination(Task.startOfClearing.topic(), callbacks::put); .forDestination(Task.startOfClearing.topic(), callbacks::put);
callback(PIClearingOutbondActionNewRequest.class)
.setFunction(pmtOutboundService::sendOutBoundPayment)
.forDestination(Consts.PAYMENT_INSTRUCTION_CLEARING_OUTBOUND_ACTION, callbacks::put);
callback(SessionContinueEvent.class) callback(SessionContinueEvent.class)
.setConsumer(req -> { .setConsumer(req -> {
primaryAuctionBnSession.continueSession(req); primaryAuctionBnSession.continueSession(req);

View file

@ -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<TradingClearingRegistry> tradingClearingRegistryImdg;
private final Imdg<Company> companyImdg;
private final Imdg<CompanySymbols> companySymbolImdg;
private final Imdg<Account> accountImdg;
private final Imdg<BankAccount> 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();
}
}
}

View file

@ -131,15 +131,12 @@ public class Sdf06Executor {
if (err.isPresent()) { if (err.isPresent()) {
log.debug("sdf06.id={} validation error: {}", sDf06.getId(), messageResolver.resolve(err.get())); log.debug("sdf06.id={} validation error: {}", sDf06.getId(), messageResolver.resolve(err.get()));
SDf07 errorSdf07; SDf07 errorSdf07;
BigDecimal errorResult; BigDecimal errorResult = errorById(err.get());
Statement stmt = null; Statement stmt = null;
if (needToCreateStatement(err.get())) { if (needToCreateStatement(err.get())) {
errorResult = errorById(err.get());
stmt = createStatementBySdf06(sDf06, stmt = createStatementBySdf06(sDf06,
((Company) validator.getStored(ValidationStored.Sdf06Company)).getId(), ((Company) validator.getStored(ValidationStored.Sdf06Company)).getId(),
validator.getStored(ValidationStored.Sdf06Account)); validator.getStored(ValidationStored.Sdf06Account));
} else {
errorResult = errorResult2;
} }
errorSdf07 = createSdf07(sDf06, now, errorResult); errorSdf07 = createSdf07(sDf06, now, errorResult);
errorSdf07.setGenerationId(sdf07GroupId); errorSdf07.setGenerationId(sdf07GroupId);
@ -203,7 +200,12 @@ public class Sdf06Executor {
if (ClearingError.BalanceInsufficient.equals(err.getSubject())) { if (ClearingError.BalanceInsufficient.equals(err.getSubject())) {
return errorResult3; 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<AssetOperationApprovalRequest> req) { public void processGatewayResponse(BaseRequest<AssetOperationApprovalRequest> req) {

View file

@ -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<PIClearingOutbondActionNewRequest, IValidator> validation;
private final ImdgProvider imdgProvider;
private final ImdgId idGenerator;
private final Imdg<PaymentInstruction> pmtImdg;
private final Imdg<Company> cmpImdg;
private final Imdg<BankAccount> bnkAccImdg;
private final Imdg<Registry> rgsImdg;
private final Imdg<TradingClearingRegistry> tcrImdg;
private final Imdg<Currency> currImdg;
private final Imdg<SDf54> sdf54Imdg;
private final RegistryManager rgsMng;
private final Sdf54Creator sdf54Creator;
private final KafkaSender kafkaSender;
@Autowired
public PaymentInstructionOutboundService(UserRoleVerification rights,
IMessageResolver msgs,
ImdgProvider imdgProvider,
Function<PIClearingOutbondActionNewRequest, IValidator> 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<PIClearingOutbondActionNewRequest> 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<EnumMessage> 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);
}
}

View file

@ -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<ImdgValidationContext<PIClearingOutbondActionNewRequest>> {
RequiredFields() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<PIClearingOutbondActionNewRequest> 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<EnumMessage> validate(ImdgValidationContext<PIClearingOutbondActionNewRequest> context) {
PIClearingOutbondActionNewRequest pmtOut = context.getValidatedObject();
Imdg<Account> 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<EnumMessage> validate(ImdgValidationContext<PIClearingOutbondActionNewRequest> context) {
PIClearingOutbondActionNewRequest pmtOut = context.getValidatedObject();
Imdg<Account> 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();
}
}

View file

@ -14,6 +14,8 @@ public enum ValidationStored {
Sdf21Account, Sdf21Account,
PIOutboundAccountDeb, PIOutboundAccountCred,
Sdf06Company, Sdf06Account, Sdf06Tcr, Sdf06Company, Sdf06Account, Sdf06Tcr,
ReturnDepositDmx, ReturnDepositDmx,

View file

@ -38,7 +38,6 @@ public class UserRoleVerification {
public UserRoleVerification(ImdgProvider imdg, public UserRoleVerification(ImdgProvider imdg,
IMessageResolver messageResolver, IMessageResolver messageResolver,
IErrorEnumId roleVerificationError) { IErrorEnumId roleVerificationError) {
Objects.requireNonNull(roleForVerification);
Objects.requireNonNull(roleVerificationError); Objects.requireNonNull(roleVerificationError);
Objects.requireNonNull(messageResolver); Objects.requireNonNull(messageResolver);
userRoleSessions = imdg.getImdg(IMDGDistributedNames.Map_UserRoleSession, UserRoleSession.class); userRoleSessions = imdg.getImdg(IMDGDistributedNames.Map_UserRoleSession, UserRoleSession.class);
@ -62,7 +61,7 @@ public class UserRoleVerification {
this.roleForVerification = roleForVerification; 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()); return userHasRole(userId, role == null ? null : role.getKey());
} }

View file

@ -3,7 +3,7 @@ package ru.spcex.platform.enumeration;
import ru.spcex.platform.utils.enumeration.IEnumKey; import ru.spcex.platform.utils.enumeration.IEnumKey;
public enum TransactionStatus implements 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; private final String key;