diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/state_machine_2/specific/PrepSessionStateMachineConfig.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/state_machine_2/specific/PrepSessionStateMachineConfig.java new file mode 100644 index 000000000..603de00b0 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/state_machine_2/specific/PrepSessionStateMachineConfig.java @@ -0,0 +1,159 @@ +package ru.spcex.clearing.config.state_machine_2.specific; + +import java.time.Instant; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.function.Supplier; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Configuration; +import org.springframework.statemachine.action.Action; +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.listener.StateMachineListenerAdapter; +import ru.clearing.classes.statics.data.execution.ExecutionCurrency; +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.CreateSessionAction; +import ru.spcex.clearing.session.state.action.DealsPrepareAction; +import ru.spcex.clearing.session.state.action.DiscardRegistriesAction; +import ru.spcex.clearing.session.state.action.ObligationAdmissionAction; +import ru.spcex.clearing.session.state.action.RequirementAndObligationCreationAction; +import ru.spcex.clearing.session.state.action.SaveRegistriesAndContinueAction; +import ru.spcex.clearing.session.state.guard.StashedRegistriesPresentGuard; +import ru.spcex.clearing.session.state.listener.MachineMonitoringListener; +import static ru.spcex.clearing.util.StateMachineUtil.chain; +import static ru.spcex.clearing.util.StateMachineUtil.invert; +import ru.spcex.platform.classes.base.interfaces.ExecutionType; +import ru.spcex.platform.enumeration.Section; +import ru.spcex.platform.enumeration.SessionStatus; +import ru.spcex.platform.enumeration.SessionType; +import ru.spcex.platform.enumeration.WorkflowStatus; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; + +@Configuration("prepSessionStateMachineConfig") +@EnableStateMachineFactory(name = "PREP") +public class PrepSessionStateMachineConfig extends EnumStateMachineConfigurerAdapter { + private final Imdg sessionImdg; + private final DealsPrepareAction dealsPrepareAction; + private final RequirementAndObligationCreationAction reqAndOblAction; + private final ObligationAdmissionAction obligationAdmissionAction; + private final SaveRegistriesAndContinueAction obligationAdmissionContinueAction; + private final Action endSession; + private final DiscardRegistriesAction discardOblAdmStash = + new DiscardRegistriesAction(DataEnum.obligationAdmissionStashedRgs); + private final StashedRegistriesPresentGuard oblAdmGuard = new StashedRegistriesPresentGuard( + DataEnum.obligationAdmissionStashedRgs + ); + private final SessionType SESSION_TYPE = SessionType.PREP; + + public PrepSessionStateMachineConfig(ImdgProvider imdgProvider, + + DealsPrepareAction dealsPrepare, + @Qualifier("requirementAndObligationCreationAction") + RequirementAndObligationCreationAction reqAndOblAction, + ObligationAdmissionAction obligationsAdmission, + @Qualifier("marketCodesForCurr") + Supplier> marketCodes, + SaveRegistriesAndContinueAction obligationAdmissionContinueAction) { + this.sessionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Session, Session.class); + Imdg executionCurrencyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionCurrency, ExecutionCurrency.class); + this.dealsPrepareAction = dealsPrepare; + this.reqAndOblAction = reqAndOblAction; + this.obligationAdmissionAction = obligationsAdmission; + this.obligationAdmissionContinueAction = obligationAdmissionContinueAction; + this.endSession = ctx -> { + Session ssn = (Session) ctx.getExtendedState().getVariables().get(DataEnum.session); + if (ssn != null) { + ssn.setSessionStatus(SessionStatus.CLOS.getKey()); + ssn.setWorkflowStatus(WorkflowStatus.Blocked.getKey()); + ssn.setUpdated(Instant.now()); + sessionImdg.update(ssn); + } + }; + + ImdgPredicateBuilder execFondPb = executionCurrencyImdg.predicateBuilder(); + dealsPrepareAction.searchForExecutions(ExecutionType.ExecutionCurrency); + dealsPrepareAction.addExecutionCurrencyCondition(execFondPb.regex("settlementCode", "^T0.*$")); + dealsPrepareAction.addExecutionCurrencyCondition(execFondPb.in("market", marketCodes.get().toArray(new String[0]))); + this.obligationAdmissionContinueAction.setDataEnum(DataEnum.obligationAdmissionStashedRgs); + } + + @Override + public void configure(StateMachineStateConfigurer states) throws Exception { + states + .withStates() + .initial(TaskType.StartRevise, new CreateSessionAction(sessionImdg, SESSION_TYPE, Section.CURR)) + .states(new HashSet<>(Arrays.asList( + TaskType.StartRevise, + TaskType.DealsPrepare, + TaskType.RequirementsAndObligationsCreate, + TaskType.ObligationsAdmission, + TaskType.PSEUDO_waitAfterObligationAdmissionError + ))) + .end(TaskType.PSEUDO_end); + } + + @Override + public void configure(StateMachineTransitionConfigurer transitions) throws Exception { + transitions + .withExternal() + .source(TaskType.StartRevise).target(TaskType.DealsPrepare) + .action(dealsPrepareAction) + .and() + .withExternal() + .source(TaskType.DealsPrepare).target(TaskType.RequirementsAndObligationsCreate) + .action(reqAndOblAction) + .and() + .withExternal() + .source(TaskType.RequirementsAndObligationsCreate).target(TaskType.ObligationsAdmission) + .action(obligationAdmissionAction) + .and(); + sourceObligationAdmission(transitions); + sourcePseudoAfterOAError(transitions); + } + + private void sourceObligationAdmission(StateMachineTransitionConfigurer transitions) throws Exception { + transitions + .withExternal() + .source(TaskType.ObligationsAdmission) + .target(TaskType.PSEUDO_waitAfterObligationAdmissionError) + .guard(oblAdmGuard) + .and() + .withExternal() + .source(TaskType.ObligationsAdmission).target(TaskType.PSEUDO_end) + .guard(invert(oblAdmGuard)) + .action(chain(obligationAdmissionContinueAction, endSession)); + } + + private void sourcePseudoAfterOAError(StateMachineTransitionConfigurer transitions) throws Exception { + transitions + .withExternal() + .source(TaskType.PSEUDO_waitAfterObligationAdmissionError).target(TaskType.PSEUDO_end) + .action(chain(obligationAdmissionContinueAction, endSession)) + .event(SsnEvent.CONTINUE) + .and() + .withExternal() + .source(TaskType.PSEUDO_waitAfterObligationAdmissionError).target(TaskType.ObligationsAdmission) + .action(chain(discardOblAdmStash, obligationAdmissionAction)) + .event(SsnEvent.REPEAT); + } + + @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/stage/TaskType.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/TaskType.java index d0bd81459..046aeb695 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/TaskType.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/TaskType.java @@ -59,6 +59,7 @@ public enum TaskType implements IEnumKey { PSEUDO_waitSdfAfterPaymentInstructions("PSEUDO_waitSdfAfterPaymentInstructions"), PSEUDO_waitSdfAfterAgainRevise("PSEUDO_waitSdfAfterAgainRevise"), PSEUDO_waitAfterObligationAdmissionError("PSEUDO_waitAfterObligationAdmissionError"), + PSEUDO_end("PSEUDO_end"), ; private String key;