From 43f2365ff004943137d8f30138bd5b6f1931ee10 Mon Sep 17 00:00:00 2001 From: ialbert Date: Tue, 7 Jul 2026 16:37:21 +0300 Subject: [PATCH] http://jira.mfd.msk:8088/browse/CLS-1060 --- ...IntermediateSessionStateMachineConfig.java | 348 ++++++++++++++++++ .../state/action/FinishingSessionAction.java | 2 +- .../action/InspectionObligationsV2Action.java | 6 +- 3 files changed, 352 insertions(+), 4 deletions(-) create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/state_machine_2/specific/PrimaryAuctionBnIntermediateSessionStateMachineConfig.java diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/state_machine_2/specific/PrimaryAuctionBnIntermediateSessionStateMachineConfig.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/state_machine_2/specific/PrimaryAuctionBnIntermediateSessionStateMachineConfig.java new file mode 100644 index 000000000..276e4f92b --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/state_machine_2/specific/PrimaryAuctionBnIntermediateSessionStateMachineConfig.java @@ -0,0 +1,348 @@ +package ru.spcex.clearing.config.state_machine_2.specific; + +import java.util.Arrays; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.List; +import java.util.function.Supplier; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Configuration; +import org.springframework.statemachine.config.EnableStateMachineFactory; +import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter; +import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer; +import org.springframework.statemachine.config.builders.StateMachineStateConfigurer; +import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer; +import org.springframework.statemachine.guard.Guard; +import org.springframework.statemachine.listener.StateMachineListenerAdapter; +import ru.clearing.classes.statics.data.execution.ExecutionFond; +import ru.clearing.classes.statics.data.misc.Session; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.session.stage.TaskType; +import ru.spcex.clearing.session.state.DataEnum; +import ru.spcex.clearing.session.state.SsnEvent; +import ru.spcex.clearing.session.state.action.AgainReviseStage3Action; +import ru.spcex.clearing.session.state.action.CreateSessionAction; +import ru.spcex.clearing.session.state.action.DealsPrepareAction; +import ru.spcex.clearing.session.state.action.DiscardRegistriesAction; +import ru.spcex.clearing.session.state.action.FinishingSessionAction; +import ru.spcex.clearing.session.state.action.FormingPaymentInstructionSecuritiesAction; +import ru.spcex.clearing.session.state.action.InclusionToPoolActionV2; +import ru.spcex.clearing.session.state.action.InspectionObligationsV2Action; +import ru.spcex.clearing.session.state.action.ObligationAdmissionAction; +import ru.spcex.clearing.session.state.action.RequirementAndObligationCreationAction; +import ru.spcex.clearing.session.state.action.ReviseStage1Action; +import ru.spcex.clearing.session.state.action.SaveRegistriesAfterInspectionAndContinueAction; +import ru.spcex.clearing.session.state.action.SaveRegistriesAndContinueAction; +import ru.spcex.clearing.session.state.action.Sdf56Action; +import ru.spcex.clearing.session.state.action.SdfReceivedAction; +import ru.spcex.clearing.session.state.action.UpdateWorkflowStatusAction; +import ru.spcex.clearing.session.state.guard.ErroneousRegistriesPresentGuard; +import ru.spcex.clearing.session.state.guard.PaymentsWereCreatedListGuard; +import ru.spcex.clearing.session.state.guard.PaymentsWereNotCreatedListGuard; +import ru.spcex.clearing.session.state.guard.SdfGuardUtil; +import ru.spcex.clearing.session.state.guard.SdfSetGuard; +import ru.spcex.clearing.session.state.guard.StashedRegistriesPresentGuard; +import ru.spcex.clearing.session.state.listener.MachineMonitoringListener; +import static ru.spcex.clearing.util.StateMachineUtil.*; +import ru.spcex.platform.classes.base.interfaces.ExecutionType; +import ru.spcex.platform.enumeration.RegistryStatus; +import ru.spcex.platform.enumeration.Section; +import ru.spcex.platform.enumeration.SessionType; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; + +@Configuration("primaryAuctionBnIntermediateSessionStateMachineConfig") +@EnableStateMachineFactory(name = "IPOM") +public class PrimaryAuctionBnIntermediateSessionStateMachineConfig + extends EnumStateMachineConfigurerAdapter { + + private final Imdg sessionImdg; + private final Sdf56Action sendSdf56Action; + private final ReviseStage1Action reviseStage1Action; + private final DealsPrepareAction dealsPrepareAction; + private final RequirementAndObligationCreationAction reqAndOblAction; + private final ObligationAdmissionAction obligationAdmissionAction; + private final InclusionToPoolActionV2 inclusionToPoolAction; + private final InspectionObligationsV2Action inspectionObligationsV2Action; + private final FormingPaymentInstructionSecuritiesAction formingPaymentInstructionSecuritiesAction; + private final FinishingSessionAction finishingSessionAction; + private final SaveRegistriesAndContinueAction obligationAdmissionContinueAction; + private final SaveRegistriesAfterInspectionAndContinueAction saveRegistriesAfterInspectionAndContinueAction; + private final DiscardRegistriesAction discardOblAdmStash = + new DiscardRegistriesAction(DataEnum.obligationAdmissionStashedRgs); + private final DiscardRegistriesAction discardInspOblStash = new DiscardRegistriesAction( + DataEnum.inspectionObligationStashedRgs + ); + private final UpdateWorkflowStatusAction pauseWsAction; + private final UpdateWorkflowStatusAction activeWsAction; + private final AgainReviseStage3Action againRevise; + + private final StashedRegistriesPresentGuard oblAdmGuard = new StashedRegistriesPresentGuard( + DataEnum.obligationAdmissionStashedRgs + ); + private final ErroneousRegistriesPresentGuard inspErrGuard = new ErroneousRegistriesPresentGuard(); + private final Guard reviseSuccessGuard = guardCheckCtxForFlag(DataEnum.againReviseSuccess); + + private final SessionType SESSION_TYPE = SessionType.IPOM; + private final Section SECTION = Section.FOND; + + @Autowired + public PrimaryAuctionBnIntermediateSessionStateMachineConfig( + ImdgProvider imdgProvider, + Sdf56Action sendSdf56Action, + ReviseStage1Action reviseStage1Action, + DealsPrepareAction dealsPrepareAction, + @Qualifier("requirementAndObligationCreationAction") + RequirementAndObligationCreationAction reqAndOblAction, + ObligationAdmissionAction obligationAdmissionAction, + InclusionToPoolActionV2 inclusionToPoolAction, + InspectionObligationsV2Action inspectionObligationsV2Action, + FormingPaymentInstructionSecuritiesAction formingPaymentInstructionSecuritiesAction, + FinishingSessionAction finishingSessionAction, + SaveRegistriesAndContinueAction obligationAdmissionContinueAction, + @Qualifier("marketCodesForBn") + Supplier> marketCodes, + SaveRegistriesAfterInspectionAndContinueAction saveRegistriesAfterInspectionAndContinueAction, + @Qualifier("pauseWorkflowStatusAction") + UpdateWorkflowStatusAction pauseWsAction, + @Qualifier("activeWorkflowStatusAction") + UpdateWorkflowStatusAction activeWsAction, AgainReviseStage3Action againRevise + ) { + this.sendSdf56Action = sendSdf56Action; + this.sessionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Session, Session.class); + this.saveRegistriesAfterInspectionAndContinueAction = saveRegistriesAfterInspectionAndContinueAction; + this.pauseWsAction = pauseWsAction; + this.activeWsAction = activeWsAction; + this.againRevise = againRevise; + Imdg executionFondImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionFond, ExecutionFond.class); + this.obligationAdmissionContinueAction = obligationAdmissionContinueAction; + this.reviseStage1Action = reviseStage1Action; + this.dealsPrepareAction = dealsPrepareAction; + this.reqAndOblAction = reqAndOblAction; + this.obligationAdmissionAction = obligationAdmissionAction; + this.inclusionToPoolAction = inclusionToPoolAction; + this.inspectionObligationsV2Action = inspectionObligationsV2Action; + this.formingPaymentInstructionSecuritiesAction = formingPaymentInstructionSecuritiesAction; + this.finishingSessionAction = finishingSessionAction; + this.finishingSessionAction.setPr("0"); + + //stages settings: + this.dealsPrepareAction.searchForExecutions(ExecutionType.ExecutionFond); + ImdgPredicateBuilder pb = executionFondImdg.predicateBuilder(); + dealsPrepareAction.addExecutionFondCondition(pb.regex("settlementCode", "^B\\d{2}$")); + dealsPrepareAction.addExecutionFondCondition(pb.in("market", marketCodes.get().toArray(new String[0]))); + this.obligationAdmissionContinueAction.setDataEnum(DataEnum.obligationAdmissionStashedRgs); + + this.inclusionToPoolAction.addRgsConditionSessionTypeIn( + SessionType.IPOB, SessionType.IPOM + ); + this.inclusionToPoolAction.addRgsConditionStatusIn( + RegistryStatus.PROC, RegistryStatus.MNG + ); + this.inclusionToPoolAction.setExecType(ExecutionType.ExecutionFond); + } + + @Override + public void configure(StateMachineStateConfigurer states) throws Exception { + states + .withStates() + .initial(TaskType.StartRevise, chain( + new CreateSessionAction(sessionImdg, SESSION_TYPE, SECTION), + sendSdf56Action)) + .states(new HashSet<>(Arrays.asList( + TaskType.StartRevise, + TaskType.StartRevisePart1, + TaskType.DealsPrepare, + TaskType.RequirementsAndObligationsCreate, + TaskType.ObligationsAdmission, + TaskType.InclusionToPool, + TaskType.InspectionObligations, + TaskType.FormingRegistersOnOS, + TaskType.FormingPaymentInstruction, + TaskType.FinishingSession, + TaskType.PSEUDO_waitSdfAfterPaymentInstructions, + TaskType.PSEUDO_waitAfterObligationAdmissionError, + TaskType.PSEUDO_waitAfterInspectionError, + TaskType.PSEUDO_waitAfterObligationAdmissionRestore, + TaskType.PSEUDO_waitAfterInspectionRestore, + TaskType.AgainRevise, + TaskType.PSEUDO_waitSdfAfterAgainRevise + ))) + .end(TaskType.FinishingSession); + } + + + @Override + public void configure(StateMachineTransitionConfigurer transitions) throws Exception { + transitions + .withExternal() + .event(SsnEvent.SDF_57) + .source(TaskType.StartRevise).target(TaskType.StartRevisePart1) + .action(reviseStage1Action) + .and() + .withExternal() + .source(TaskType.StartRevisePart1).target(TaskType.DealsPrepare) + .action(dealsPrepareAction) + .and() + .withExternal() + .source(TaskType.DealsPrepare).target(TaskType.RequirementsAndObligationsCreate) + .action(reqAndOblAction) + .and() + .withExternal() + .source(TaskType.RequirementsAndObligationsCreate).target(TaskType.InclusionToPool) + .action(inclusionToPoolAction) + .and() + .withExternal() + .source(TaskType.InclusionToPool).target(TaskType.ObligationsAdmission) + .action(obligationAdmissionAction); + + sourceObligationAdmission(transitions); + sourcePseudoAfterOAPause(transitions); + sourcePseudoAfterIOPause(transitions); + sourceFormingPaymentInstruction(transitions); + sourcePseudoWaitSdfAfterPaymentInstructions(transitions); + sourceInspection(transitions); + sourceAgainRevise(transitions); + sourcePseudoWaitAfterAgainRevise(transitions); + } + + private void sourceObligationAdmission(StateMachineTransitionConfigurer transitions) throws Exception { + transitions + .withExternal() + .source(TaskType.ObligationsAdmission) + .target(TaskType.PSEUDO_waitAfterObligationAdmissionError) + .guard(oblAdmGuard) + .action(pauseWsAction) + .and() + .withExternal() + .source(TaskType.ObligationsAdmission).target(TaskType.InspectionObligations) + .guard(invert(oblAdmGuard)) + .action(chain(obligationAdmissionContinueAction, inspectionObligationsV2Action)); + } + + private void sourceInspection(StateMachineTransitionConfigurer transitions) throws Exception { + transitions + .withExternal() + .source(TaskType.InspectionObligations) + .target(TaskType.PSEUDO_waitAfterInspectionError) + .guard(inspErrGuard) + .action(pauseWsAction) + .and() + .withExternal() + .source(TaskType.InspectionObligations).target(TaskType.FormingPaymentInstruction) + .guard(invert(inspErrGuard)) + .action(saveRegistriesAfterInspectionAndContinueAction) + .action(formingPaymentInstructionSecuritiesAction); + } + + private void sourcePseudoAfterOAPause(StateMachineTransitionConfigurer transitions) throws Exception { + transitions + //continue and repeat after ObligationAdmission + .withExternal() + .source(TaskType.PSEUDO_waitAfterObligationAdmissionError).target(TaskType.InspectionObligations) + .action(chain(activeWsAction, obligationAdmissionContinueAction, inspectionObligationsV2Action)) + .event(SsnEvent.CONTINUE); + for (var taskType : List.of(TaskType.PSEUDO_waitAfterObligationAdmissionError, TaskType.PSEUDO_waitAfterObligationAdmissionRestore)) { + transitions + .withExternal() + .source(taskType).target(TaskType.ObligationsAdmission) + .action(chain(activeWsAction, discardOblAdmStash, obligationAdmissionAction)) + .event(SsnEvent.REPEAT); + } + } + + private void sourcePseudoAfterIOPause(StateMachineTransitionConfigurer transitions) throws Exception { + transitions + //continue and repeat after InspectionObligations + .withExternal() + .source(TaskType.PSEUDO_waitAfterInspectionError).target(TaskType.FormingPaymentInstruction) + .action(activeWsAction) + .action(saveRegistriesAfterInspectionAndContinueAction) + .action(formingPaymentInstructionSecuritiesAction) + .event(SsnEvent.CONTINUE); + for (var taskType : List.of(TaskType.PSEUDO_waitAfterInspectionError, TaskType.PSEUDO_waitAfterInspectionRestore)) { + transitions + .withExternal() + .source(taskType).target(TaskType.InspectionObligations) + .action(chain(activeWsAction, discardInspOblStash, inspectionObligationsV2Action)) + .event(SsnEvent.REPEAT); + } + } + + private void sourceFormingPaymentInstruction(StateMachineTransitionConfigurer transitions) throws Exception { + transitions + //если не создалось paymentInstruction'ов + .withExternal() + .source(TaskType.FormingPaymentInstruction) + .target(TaskType.AgainRevise) + .guard(new PaymentsWereNotCreatedListGuard(FormingPaymentInstructionSecuritiesAction.key)) + .action(againRevise) + .and() + //если создались paymentInstruction, переходим в режим ожидания + .withExternal() + .source(TaskType.FormingPaymentInstruction) + .target(TaskType.PSEUDO_waitSdfAfterPaymentInstructions) + .guard(new PaymentsWereCreatedListGuard(FormingPaymentInstructionSecuritiesAction.key)); + } + + private void sourcePseudoWaitSdfAfterPaymentInstructions(StateMachineTransitionConfigurer transitions) throws Exception { + EnumSet sdfs = SdfGuardUtil.bySectionAfter7Step(SECTION); + transitions + .withExternal() + .source(TaskType.PSEUDO_waitSdfAfterPaymentInstructions) + .target(TaskType.AgainRevise) + .guard(new SdfSetGuard(sdfs)) + .action(againRevise); + for (var event: sdfs) { + transitions + .withInternal() + .source(TaskType.PSEUDO_waitSdfAfterPaymentInstructions) + .event(event) + .action(SdfReceivedAction.instance); + } + } + + private void sourceAgainRevise(StateMachineTransitionConfigurer transitions) throws Exception { + transitions + .withExternal() + .source(TaskType.AgainRevise) + .target(TaskType.FinishingSession) + .action(finishingSessionAction) + .guard(reviseSuccessGuard) + .and() + .withExternal() + .source(TaskType.AgainRevise) + .target(TaskType.PSEUDO_waitSdfAfterAgainRevise) + .guard(invert(reviseSuccessGuard)); + } + + private void sourcePseudoWaitAfterAgainRevise(StateMachineTransitionConfigurer transitions) throws Exception { + EnumSet ssnEvents = SdfGuardUtil.afterAgainReviseError(SECTION); + transitions + .withExternal() + .source(TaskType.PSEUDO_waitSdfAfterAgainRevise) + .target(TaskType.AgainRevise) + .guard(new SdfSetGuard(ssnEvents)) + .action(againRevise); + for (var event : ssnEvents) { + transitions + .withInternal() + .source(TaskType.PSEUDO_waitSdfAfterAgainRevise) + .event(event) + .action(SdfReceivedAction.instance); + } + } + + + @Override + public void configure(StateMachineConfigurationConfigurer config) throws Exception { + StateMachineListenerAdapter loggingChangeStateListener + = new MachineMonitoringListener(SESSION_TYPE.getKey()); + config + .withConfiguration() + .machineId(SESSION_TYPE.getKey()) + .listener(loggingChangeStateListener); + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/action/FinishingSessionAction.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/action/FinishingSessionAction.java index 1272c03c2..cabe8ef00 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/action/FinishingSessionAction.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/action/FinishingSessionAction.java @@ -182,7 +182,7 @@ public class FinishingSessionAction extends AbstractSessionActionForOkErrorHandl notAllowed, executions.size() - (allowed + notAllowed)); } - if (IEnumKey.contains(sessionType, SessionType.CURR, SessionType.PAYM, SessionType.RSLT, SessionType.TRDT, SessionType.IPOB, SessionType.IPO0, SessionType.IPOT, SessionType.UNIT)) { + if (IEnumKey.contains(sessionType, SessionType.CURR, SessionType.PAYM, SessionType.RSLT, SessionType.TRDT, SessionType.IPOB, SessionType.IPOM, SessionType.IPO0, SessionType.IPOT, SessionType.UNIT)) { Collection executions = findExecutionFondBySessionId(sessionId, sessionType); Map execCurr = new HashMap<>(); Map execFond = new HashMap<>(); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/action/InspectionObligationsV2Action.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/action/InspectionObligationsV2Action.java index 5b098ec38..b77c34751 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/action/InspectionObligationsV2Action.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/action/InspectionObligationsV2Action.java @@ -206,7 +206,7 @@ public class InspectionObligationsV2Action extends ReviseStage1Action { continue GROUP; } } - if (SessionType.FINL.equals(sessionType) + if ((SessionType.FINL.equals(sessionType) || SessionType.IPOM.equals(sessionType)) && omt.isPresent() && checkResults.stream().noneMatch(checkResult -> checkResult.isUncovered) && tradingTimeService.isTradingTime()) { @@ -382,7 +382,7 @@ public class InspectionObligationsV2Action extends ReviseStage1Action { } private RegistryStatus uncvStatus() { - if (SessionType.MEDM.equals(sessionType)) { + if (SessionType.MEDM.equals(sessionType) || SessionType.IPOM.equals(sessionType)) { return RegistryStatus.MNG; } else { return RegistryStatus.UNCV; @@ -390,7 +390,7 @@ public class InspectionObligationsV2Action extends ReviseStage1Action { } private RegistryStatus failStatus() { - if (SessionType.MEDM.equals(sessionType)) { + if (SessionType.MEDM.equals(sessionType) || SessionType.IPOM.equals(sessionType)) { return RegistryStatus.MNG; } else { return RegistryStatus.FAIL;