diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionBuilderFinalMkrDeals.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionBuilderFinalMkrDeals.java index a121c3723..3bffeaa54 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionBuilderFinalMkrDeals.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/builder/PaymentInstructionBuilderFinalMkrDeals.java @@ -44,6 +44,7 @@ public class PaymentInstructionBuilderFinalMkrDeals { protected AtomicLong documentNumberId = new AtomicLong(0L); // порядковый номер (сквозной по всем компаниям за день private static final DateTimeFormatter DATE_FORMATTER_ddMMyy = DateTimeFormatter.ofPattern("ddMMyy"); private String purpose; + private String lmtPurpose = null; public static PaymentInstructionBuilderFinalMkrDeals builder(ImdgProvider imdgProvider) { return new PaymentInstructionBuilderFinalMkrDeals(imdgProvider); @@ -86,6 +87,11 @@ public class PaymentInstructionBuilderFinalMkrDeals { return this; } + public PaymentInstructionBuilderFinalMkrDeals paymentPurposeLmt(String purpose) { + this.lmtPurpose = purpose; + return this; + } + public Pair build() { PaymentInstruction payment1; @@ -128,7 +134,11 @@ public class PaymentInstructionBuilderFinalMkrDeals { payment1.setPaymentDate(TimeUtil.localDateToInstant(lm_t.getSettlementDate())); - payment1.setPaymentPurpose(purpose); + if (lmtPurpose != null) { + payment1.setPaymentPurpose(lmtPurpose); + } else { + payment1.setPaymentPurpose(purpose); + } payment1.setSettlementDate(lm_t.getSettlementDate()); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf57Executor.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf57Executor.java index 6885b4ae4..6756a54eb 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf57Executor.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/executors/Sdf57Executor.java @@ -19,6 +19,7 @@ import ru.clearing.classes.statics.data.security.Security; import ru.clearing.classes.statics.data.statement.Statement; import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.notification.NotificationSender; import ru.spcex.clearing.platform.messaging.domain.Consts; import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest; import ru.spcex.clearing.platform.messaging.domain.cud.clearing.AssetOperationListRequest; @@ -93,13 +94,14 @@ public class Sdf57Executor extends AbstractExecutor { private final TradingTimeService timeService; private final KafkaSender kafka; private final AssetTBFProcessing assets; + private final NotificationSender notification; private final Pattern pattern = Pattern.compile("№.*"); public Sdf57Executor(@Qualifier("sdf57Validator") Function sDf57Validator, LoggingService errorLogger, ImdgProvider imdgProvider, IMessageResolver errorResolver, AnltSearcher anltSearcher, IMessageResolver messageResolver, DmiService dmiService, TradingTimeService timeService, - @Qualifier("kafkaSenderWithoutRequestInfo") KafkaSender kafka, AssetTBFProcessing assets) { + @Qualifier("kafkaSenderWithoutRequestInfo") KafkaSender kafka, AssetTBFProcessing assets, NotificationSender notification) { this.statementImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class); this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); this.sdf02Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf02, SDf02.class); @@ -121,6 +123,7 @@ public class Sdf57Executor extends AbstractExecutor { this.timeService = timeService; this.kafka = kafka; this.assets = assets; + this.notification = notification; } //todo доделать контроль sdf01 и sdf57 @@ -442,11 +445,16 @@ public class Sdf57Executor extends AbstractExecutor { statementCred.map(stmt -> new StmtCmpAcc(stmt, companyCred, accountCred)).ifPresent(registersUpdate); } if (sessionIsNeededFlag.get()) { - result.setSessionWasStarted(true); - LauncherCommandRequest sessionTask = new LauncherCommandRequest(); - sessionTask.setSection(Section.MKR.getKey()); - sessionTask.setSessionType(SessionType.XDEP.getKey()); - kafka.sendRequestToQueue(Task.startOfClearing.topic(), sessionTask); + if (!timeService.timeForXdep()) { + EnumMessage err = new EnumMessage(ClearingError.XdepTimeIntervalNotMatch); + notification.sendNotification(ObjectType.session, messageResolver.resolve(err), Priority.HIGH); + } else { + result.setSessionWasStarted(true); + LauncherCommandRequest sessionTask = new LauncherCommandRequest(); + sessionTask.setSection(Section.MKR.getKey()); + sessionTask.setSessionType(SessionType.XDEP.getKey()); + kafka.sendRequestToQueue(Task.startOfClearing.topic(), sessionTask); + } } return result; } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/SessionManager.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/SessionManager.java index f911f457a..e55b0c9cf 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/SessionManager.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/SessionManager.java @@ -79,25 +79,20 @@ public class SessionManager { if (session != null) { //checkActive - checkAllowSessionStart(sessionType); + checkAllowSessionStart(); session.runSession(baseRequest); } } - protected void checkAllowSessionStart(SessionType sessionType) throws ValidationException { + protected void checkAllowSessionStart() throws ValidationException { EnumMessage err = null; - if (sessionType.equals(SessionType.XDEP) && !time.timeForXdep()) { - log.warn("cannot launch {} reason: time interval not matched", sessionType); - err = new EnumMessage(ClearingError.XdepTimeIntervalNotMatch); - } else { - Session existActiveSession = sessionImdg.getFirstObjectByFieldValues(Map.of( - "workflowStatus", SessionStatus.ACTV.getKey() - )); - if (existActiveSession != null) { - log.warn("Can not start new session, cause exist active session.id={}", existActiveSession.getId()); - err = new EnumMessage(ClearingError.ActiveSessionIsPresent, String.valueOf(existActiveSession.getId())); - } + Session existActiveSession = sessionImdg.getFirstObjectByFieldValues(Map.of( + "workflowStatus", SessionStatus.ACTV.getKey() + )); + if (existActiveSession != null) { + log.warn("Can not start new session, cause exist active session.id={}", existActiveSession.getId()); + err = new EnumMessage(ClearingError.ActiveSessionIsPresent, String.valueOf(existActiveSession.getId())); } if (err != null) { notification.sendNotification(ObjectType.session, msgs.resolve(err), Priority.HIGH); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionDepositReturn.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionDepositReturn.java index 46da833e4..98bc0be37 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionDepositReturn.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/FormingPaymentInstructionDepositReturn.java @@ -7,6 +7,7 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Scope; 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.payment.PaymentInstruction; import ru.clearing.classes.statics.data.registry.Registry; @@ -58,6 +59,8 @@ public class FormingPaymentInstructionDepositReturn implements ISessionStage { private final ImdgProvider imdgProvider; private final ImdgId idGenerator; private final Imdg registryImdg; + private final Imdg bankAccImdg; + private final Imdg currImdg; private final Imdg paymentInstructionImdg; private final Imdg securityImdg; private final Imdg accountImdg; @@ -81,6 +84,8 @@ public class FormingPaymentInstructionDepositReturn implements ISessionStage { this.sDf03Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf03, SDf03.class); this.sDf12Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf12, SDf12.class); this.paymentInstructionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_PaymentInstruction, PaymentInstruction.class); + this.bankAccImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_BankAccount, BankAccount.class); + this.currImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Currency, ru.clearing.classes.statics.data.misc.Currency.class); this.sdf03Creator = sdf03Creator; this.rgsMng = rgsMng; } @@ -102,6 +107,13 @@ public class FormingPaymentInstructionDepositReturn implements ISessionStage { private StageResult formingPaymentInstruction(Long sessionId) { Instant now = Instant.now(); + Account tranAcc = accountImdg.getFirstObjectBySQL("accountType = '%s' and status = '%s' and processingSign = '%s'" + .formatted(AccountType.Tran.getKey(), AccountStatus.ACTIVE.getKey(), Allowed.ALLOWED.getKey())); + if (tranAcc == null) { + return new StageResult<>( + new EnumMessage(ClearingError.AccountNotPresent, "accountType = " + AccountType.Tran.getKey()), + false); + } RegistryCodeSqlBuilder registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(LM_T,CM_T, LS_T, CS_T); String registryCodeCondition = registryCodeSqlBuilder.build(); @@ -128,15 +140,15 @@ public class FormingPaymentInstructionDepositReturn implements ISessionStage { Optional lmtO = groupRgs.stream().filter(rgs -> RegistryManager.equalsByCode(LM_T, rgs)).findFirst(); Optional cmtO = groupRgs.stream().filter(rgs -> RegistryManager.equalsByCode(CM_T, rgs)).findFirst(); if (lmtO.isEmpty() || cmtO.isEmpty()) { - log.error("LM*T or CM*T not found for group {}", entry.getKey()); + log.error("groupId {} LM*T or CM*T not found", entry.getKey()); continue; } Registry lm_t = lmtO.get(); //obligation by money Registry cm_t = cmtO.get(); Optional dmx = rgsMng.searchDmxByCounterPartyNotOk(lm_t); if (dmx.isPresent()) { - log.debug("LM*T#id={}, DM*X#id={} found, no action needed for group {}, skipping liability", - lm_t.getId(), dmx.get().getId(), lm_t.getGroupId()); + log.debug("groupId {} LM*T#id={}, DM*X#id={} found, no action needed, skipping liability", + lm_t.getGroupId(), lm_t.getId(), dmx.get().getId()); dmx.get().setRegistryStatus(RegistryStatus.OK.getKey()); setUpdatedStoreInImdg(dmx.get(), now); continue; @@ -144,25 +156,35 @@ public class FormingPaymentInstructionDepositReturn implements ISessionStage { Optional dmtInfo = rgsMng.searchDmtInfoNotOk(lm_t); if (dmtInfo.isPresent()) { - BigDecimal balance = safeBD(lm_t.getBalance()).add(safeBD(cm_t.getBalance())); //fixme???? - PaymentInstruction payInstr = createPaymentInstruction(List.of(lm_t, cm_t), balance, sessionId); - lm_t.setPaymentId(payInstr.getId()); + log.debug("groupId {} LM*T#id={}, DM*T(INFO)#id={} found", + lm_t.getGroupId(), lm_t.getId(), dmtInfo.get().getId()); + Pair pmts = PaymentInstructionBuilderFinalMkrDeals.builder(imdgProvider) + .lm_t(lm_t) + .cm_t(cm_t) + .tranAcc(tranAcc) + .sessionId(sessionId) + .paymentPurposeLmt("Возврат депозита " + lm_t.getContract() + " по ТКР " + lm_t.getTradingClearingRegistry()) + .paymentPurpose("Возврат депозита " + cm_t.getContract() + " по ТКР " + cm_t.getTradingClearingRegistry()) + .build(); + Pair.forEach(pmts, paymentInstructionImdg::insert); + Pair.forEach(pmts, pmtCreated::add); + lm_t.setPaymentId(pmts.getFirst().getId()); + cm_t.setPaymentId(pmts.getSecond().getId()); lm_t.setUpdated(Instant.now()); + cm_t.setUpdated(Instant.now()); registryImdg.update(lm_t); + registryImdg.update(cm_t); dmtInfo.get().setRegistryStatus(RegistryStatus.OK.getKey()); setUpdatedStoreInImdg(dmtInfo.get(), now); + log.debug("groupId {} LM*T#id={} CM*T#id={} created PmtInst.id={} and PmtInst.id={}", + lm_t.getGroupId(), lm_t.getId(), cm_t.getId(), pmts.getFirst().getId(), pmts.getSecond().getId()); continue; } Optional dmtClnr = rgsMng.searchDmtClrnNotOk(lm_t); if (dmtClnr.isPresent()) { - Account tranAcc = accountImdg.getFirstObjectBySQL("accountType = '%s' and status = '%s' and processingSign = '%s'" - .formatted(AccountType.Tran.getKey(), AccountStatus.ACTIVE.getKey(), Allowed.ALLOWED.getKey())); - if (tranAcc == null) { - return new StageResult<>( - new EnumMessage(ClearingError.AccountNotPresent, "accountType = " + AccountType.Tran.getKey()), - false); - } + log.debug("groupId {} {}#id={} found", + lm_t.getGroupId(), dmtClnr.get().getRegistryCode(), dmtClnr.get().getId()); { //изменение активов - блокируем средства беред отправкой sdf'ов Optional amfO = rgsMng.findRelatedAsset(lm_t.getTradingClearingRegistryId(), lm_t.getCompanyId(), lm_t.getSecuritySymbol(), AM_F); @@ -177,21 +199,21 @@ public class FormingPaymentInstructionDepositReturn implements ISessionStage { ambO.map(Registry::getId).orElse(null), receiverAmtO.map(Registry::getId).orElse(null) ); - amfO.ifPresent(amf -> { - amf.setBalance(safeBD(amf.getBalance()).subtract(safeBD(lm_t.getBalance()))); - setUpdatedStoreInImdg(amf, now); - }); + //amfO.ifPresent(amf -> { + // amf.setBalance(safeBD(amf.getBalance()).subtract(safeBD(lm_t.getBalance()))); + // setUpdatedStoreInImdg(amf, now); + //}); payerAmtO.ifPresent(amt -> { amt.setSettledDebit(safeBD(amt.getSettledDebit()).add(safeBD(lm_t.getBalance()))); setUpdatedStoreInImdg(amt, now); }); - ambO.ifPresent(amb -> { - amb.setBalance(safeBD(amb.getBalance()).add(safeBD(lm_t.getBalance()))); - setUpdatedStoreInImdg(amb, now); - }); + //ambO.ifPresent(amb -> { + // amb.setBalance(safeBD(amb.getBalance()).add(safeBD(lm_t.getBalance()))); + // setUpdatedStoreInImdg(amb, now); + //}); receiverAmtO.ifPresent(amt -> { // у отправителя и получателя одинаково, см. в FormingPaymentInstruction - amt.setSettledDebit(safeBD(amt.getSettledDebit()).add(safeBD(lm_t.getBalance()))); + amt.setSettledCredit(safeBD(amt.getSettledDebit()).add(safeBD(lm_t.getBalance()))); setUpdatedStoreInImdg(amt, now); }); } @@ -204,8 +226,8 @@ public class FormingPaymentInstructionDepositReturn implements ISessionStage { .build(); paymentInstructionImdg.insert(pmts.getFirst()); paymentInstructionImdg.insert(pmts.getSecond()); - log.debug("LM*T#id={}, CM*T#id={} found, PaymentInstruction id={} and id={} created", - lm_t.getId(), cm_t.getId(), pmts.getFirst().getId(), pmts.getSecond().getId()); + log.debug("groupId {} LM*T#id={}, CM*T#id={} found, PaymentInstruction id={} and id={} created", + lm_t.getGroupId(), lm_t.getId(), cm_t.getId(), pmts.getFirst().getId(), pmts.getSecond().getId()); pmtCreated.add(pmts.getFirst()); pmtCreated.add(pmts.getSecond()); dmtClnr.get().setRegistryStatus(RegistryStatus.OK.getKey());