ialbert 2026-02-26 15:00:40 +03:00
parent 6a01cb328f
commit 0758c9654c
8 changed files with 274 additions and 10 deletions

View file

@ -87,7 +87,7 @@ public class PaymSessionStateMachineConfig extends EnumStateMachineConfigurerAda
AgainReviseStage3Action againReviseStage3Action, AgainReviseStage3Action againReviseStage3Action,
FinishingSessionAction finishingSession, FinishingSessionAction finishingSession,
@Qualifier("marketCodesForCurr") @Qualifier("marketCodesForCurr")
Supplier<List<String>> marketCodes, Supplier<List<String>> marketCodes,
SaveRegistriesAndContinueAction obligationAdmissionContinueAction, SaveRegistriesAndContinueAction obligationAdmissionContinueAction,
SaveRegistriesAfterInspectionAndContinueAction saveRegistriesAfterInspectionAndContinueAction, SaveRegistriesAfterInspectionAndContinueAction saveRegistriesAfterInspectionAndContinueAction,
@Qualifier("pauseWorkflowStatusAction") @Qualifier("pauseWorkflowStatusAction")
@ -114,6 +114,7 @@ public class PaymSessionStateMachineConfig extends EnumStateMachineConfigurerAda
dealsPrepareAction.searchForExecutions(ExecutionType.ExecutionCurrency); dealsPrepareAction.searchForExecutions(ExecutionType.ExecutionCurrency);
ImdgPredicateBuilder execFondPb = executionCurrencyImdg.predicateBuilder(); ImdgPredicateBuilder execFondPb = executionCurrencyImdg.predicateBuilder();
dealsPrepareAction.addExecutionCurrencyCondition(execFondPb.in("market", marketCodes.get().toArray(new String[0]))); dealsPrepareAction.addExecutionCurrencyCondition(execFondPb.in("market", marketCodes.get().toArray(new String[0])));
dealsPrepareAction.addExecutionCurrencyCondition(execFondPb.regex("settlementCode", "^T1.*$"));
this.obligationAdmissionContinueAction.setDataEnum(DataEnum.obligationAdmissionStashedRgs); this.obligationAdmissionContinueAction.setDataEnum(DataEnum.obligationAdmissionStashedRgs);
this.formingPaymentInstructionAssetsAction.setDisableCompanyCondition(true); this.formingPaymentInstructionAssetsAction.setDisableCompanyCondition(true);
} }

View file

@ -0,0 +1,258 @@
package ru.spcex.clearing.config.state_machine_2.specific;
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.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.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.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.FormingPaymentInstructionAssetsAction;
import ru.spcex.clearing.session.state.action.InclusionToPoolAction;
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.UpdateWorkflowStatusAction;
import ru.spcex.clearing.session.state.guard.ErroneousRegistriesPresentGuard;
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.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("rsltSessionStateMachineConfig")
@EnableStateMachineFactory(name = "RSLT")
public class RsltSessionStateMachineConfig extends EnumStateMachineConfigurerAdapter<TaskType, SsnEvent> {
private final Imdg<Session> sessionImdg;
private final ReviseStage1Action reviseStage1Action;
private final DealsPrepareAction dealsPrepareAction;
private final RequirementAndObligationCreationAction reqAndOblAction;
private final ObligationAdmissionAction obligationAdmissionAction;
private final InclusionToPoolAction inclusionToPoolAction;
private final InspectionObligationsV2Action inspectionObligationsV2Action;
private final FormingPaymentInstructionAssetsAction formingPaymentInstructionAssetsAction;
private final AgainReviseStage3Action againRevise;
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 StashedRegistriesPresentGuard oblAdmGuard = new StashedRegistriesPresentGuard(
DataEnum.obligationAdmissionStashedRgs
);
private final ErroneousRegistriesPresentGuard inspErrGuard = new ErroneousRegistriesPresentGuard();
private final Guard<TaskType, SsnEvent> reviseSuccessGuard = guardCheckCtxForFlag(DataEnum.againReviseSuccess);
private final SessionType SESSION_TYPE = SessionType.RSLT;
private final Section SECTION = Section.CURR;
public RsltSessionStateMachineConfig(ImdgProvider imdgProvider,
ReviseStage1Action reviseStage1Action,
DealsPrepareAction dealsPrepare,
@Qualifier("requirementAndObligationCreationAction")
RequirementAndObligationCreationAction reqAndOblAction,
ObligationAdmissionAction obligationsAdmission,
InclusionToPoolAction inclusionToPoolAction,
InspectionObligationsV2Action inspectionObligations,
FormingPaymentInstructionAssetsAction formingPaymentInstructionAssets,
AgainReviseStage3Action againReviseStage3Action,
FinishingSessionAction finishingSession,
@Qualifier("marketCodesForCurr")
Supplier<List<String>> marketCodes,
SaveRegistriesAndContinueAction obligationAdmissionContinueAction,
SaveRegistriesAfterInspectionAndContinueAction saveRegistriesAfterInspectionAndContinueAction,
@Qualifier("pauseWorkflowStatusAction")
UpdateWorkflowStatusAction pauseWsAction,
@Qualifier("activeWorkflowStatusAction")
UpdateWorkflowStatusAction activeWsAction) {
this.sessionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Session, Session.class);
this.saveRegistriesAfterInspectionAndContinueAction = saveRegistriesAfterInspectionAndContinueAction;
this.pauseWsAction = pauseWsAction;
this.activeWsAction = activeWsAction;
Imdg<ExecutionCurrency> executionCurrencyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionCurrency, ExecutionCurrency.class);
this.reviseStage1Action = reviseStage1Action;
this.dealsPrepareAction = dealsPrepare;
this.reqAndOblAction = reqAndOblAction;
this.obligationAdmissionAction = obligationsAdmission;
this.inclusionToPoolAction = inclusionToPoolAction;
this.inspectionObligationsV2Action = inspectionObligations;
this.formingPaymentInstructionAssetsAction = formingPaymentInstructionAssets;
this.againRevise = againReviseStage3Action;
this.finishingSessionAction = finishingSession;
this.obligationAdmissionContinueAction = obligationAdmissionContinueAction;
this.finishingSessionAction.setPr("1");
dealsPrepareAction.searchForExecutions(ExecutionType.ExecutionCurrency);
ImdgPredicateBuilder execFondPb = executionCurrencyImdg.predicateBuilder();
dealsPrepareAction.addExecutionCurrencyCondition(execFondPb.in("market", marketCodes.get().toArray(new String[0])));
this.obligationAdmissionContinueAction.setDataEnum(DataEnum.obligationAdmissionStashedRgs);
this.formingPaymentInstructionAssetsAction.setDisableCompanyCondition(true);
}
@Override
public void configure(StateMachineStateConfigurer<TaskType, SsnEvent> states) throws Exception {
states
.withStates()
.initial(TaskType.StartRevise, new CreateSessionAction(sessionImdg, SESSION_TYPE, SECTION))
.states(new HashSet<>(Arrays.asList(
TaskType.StartRevise,
TaskType.StartRevisePart1,
TaskType.DealsPrepare,
TaskType.RequirementsAndObligationsCreate,
TaskType.ObligationsAdmission,
TaskType.InclusionToPool,
TaskType.InspectionObligations,
TaskType.FormingPaymentInstruction,
TaskType.FinishingSession,
TaskType.PSEUDO_waitAfterObligationAdmissionError,
TaskType.AgainRevise,
TaskType.PSEUDO_waitAfterInspectionError,
TaskType.PSEUDO_waitAfterObligationAdmissionRestore,
TaskType.PSEUDO_waitAfterInspectionRestore
)))
.end(TaskType.FinishingSession);
}
@Override
public void configure(StateMachineTransitionConfigurer<TaskType, SsnEvent> transitions) throws Exception {
transitions
.withExternal()
.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)
.and()
.withExternal()
.source(TaskType.FormingPaymentInstruction)
.target(TaskType.AgainRevise)
.action(againRevise)
.and()
.withExternal()
.source(TaskType.AgainRevise)
.target(TaskType.FinishingSession)
.action(finishingSessionAction)
.guard(reviseSuccessGuard);
sourceObligationAdmission(transitions);
sourcePseudoAfterOAPause(transitions);
sourcePseudoAfterIOPause(transitions);
sourceInspection(transitions);
}
private void sourceObligationAdmission(StateMachineTransitionConfigurer<TaskType, SsnEvent> 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<TaskType, SsnEvent> 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(formingPaymentInstructionAssetsAction);
}
private void sourcePseudoAfterOAPause(StateMachineTransitionConfigurer<TaskType, SsnEvent> 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<TaskType, SsnEvent> transitions) throws Exception {
transitions
//continue and repeat after InspectionObligations
.withExternal()
.source(TaskType.PSEUDO_waitAfterInspectionError).target(TaskType.FormingPaymentInstruction)
.action(activeWsAction)
.action(saveRegistriesAfterInspectionAndContinueAction)
.action(formingPaymentInstructionAssetsAction)
.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);
}
}
@Override
public void configure(StateMachineConfigurationConfigurer<TaskType, SsnEvent> config) throws Exception {
StateMachineListenerAdapter<TaskType, SsnEvent> loggingChangeStateListener
= new MachineMonitoringListener(SESSION_TYPE.getKey());
config
.withConfiguration()
.machineId(SESSION_TYPE.getKey())
.listener(loggingChangeStateListener);
}
}

View file

@ -182,7 +182,7 @@ public class FinishingSessionAction extends AbstractSessionActionForOkErrorHandl
notAllowed, notAllowed,
executions.size() - (allowed + notAllowed)); executions.size() - (allowed + notAllowed));
} }
if (IEnumKey.contains(sessionType, SessionType.CURR, SessionType.PAYM, 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.IPO0, SessionType.IPOT, SessionType.UNIT)) {
Collection<? extends ExecutionCommon> executions = findExecutionFondBySessionId(sessionId, sessionType); Collection<? extends ExecutionCommon> executions = findExecutionFondBySessionId(sessionId, sessionType);
Map<Long, ExecutionCurrency> execCurr = new HashMap<>(); Map<Long, ExecutionCurrency> execCurr = new HashMap<>();
Map<Long, ExecutionFond> execFond = new HashMap<>(); Map<Long, ExecutionFond> execFond = new HashMap<>();
@ -244,7 +244,7 @@ public class FinishingSessionAction extends AbstractSessionActionForOkErrorHandl
throw new RuntimeException(msgResolver.resolve(sResult.get())); throw new RuntimeException(msgResolver.resolve(sResult.get()));
} }
} }
if (!SessionType.PAYM.equals(sessionType)) { if (!SessionType.PAYM.equals(sessionType) && !SessionType.RSLT.equals(sessionType)) {
sdf05Sender.sendSdf05(pr); sdf05Sender.sendSdf05(pr);
} }
if (Section.FOND.equals(section) || Section.MULT.equals(section)) { if (Section.FOND.equals(section) || Section.MULT.equals(section)) {
@ -332,7 +332,7 @@ public class FinishingSessionAction extends AbstractSessionActionForOkErrorHandl
return res; return res;
} else { } else {
Imdg<? extends ExecutionCommon> excImdg; Imdg<? extends ExecutionCommon> excImdg;
if (sessionType.equals(SessionType.CURR) || sessionType.equals(SessionType.PAYM)) { if (sessionType.equals(SessionType.CURR) || sessionType.equals(SessionType.PAYM)|| sessionType.equals(SessionType.RSLT)) {
excImdg = executionCurrencyImdg; excImdg = executionCurrencyImdg;
} else { } else {
excImdg = executionFondImdg; excImdg = executionFondImdg;

View file

@ -475,7 +475,7 @@ public class FormingPaymentInstructionAssetsAction extends AbstractSessionAction
Registry rgs = pair.getSecond(); Registry rgs = pair.getSecond();
Account account = accountImdg.getSingleObjectByID(paymentInstruction.getCreditLeg_accountId()); Account account = accountImdg.getSingleObjectByID(paymentInstruction.getCreditLeg_accountId());
Security security = securityImdg.getSingleObjectByID(paymentInstruction.getCreditLeg_securityId()); Security security = securityImdg.getSingleObjectByID(paymentInstruction.getCreditLeg_securityId());
if (SessionType.CURR.equals(sessionType) || SessionType.PAYM.equals(sessionType) || (rgs != null if (SessionType.CURR.equals(sessionType) || SessionType.PAYM.equals(sessionType) || SessionType.RSLT.equals(sessionType) || (rgs != null
&& RegistryInstrumentType.M.equalsByKey(rgs.getRegistryInstrumentType()) && RegistryInstrumentType.M.equalsByKey(rgs.getRegistryInstrumentType())
&& !CurrencyCode.isRub(rgs.getSecuritySymbol()))) { && !CurrencyCode.isRub(rgs.getSecuritySymbol()))) {
boolean madeStatements = statementsWereMade(paymentInstruction, rgs); boolean madeStatements = statementsWereMade(paymentInstruction, rgs);
@ -564,7 +564,7 @@ public class FormingPaymentInstructionAssetsAction extends AbstractSessionAction
private boolean statementsWereMade(PaymentInstruction pmt, Registry am_b) { private boolean statementsWereMade(PaymentInstruction pmt, Registry am_b) {
ImdgPredicateBuilder pb = stlmHPropsImdg.predicateBuilder(); ImdgPredicateBuilder pb = stlmHPropsImdg.predicateBuilder();
String curCode = pmt.getCreditLeg_currencyCode(); String curCode = pmt.getCreditLeg_currencyCode();
if (!SessionType.PAYM.equals(sessionType)) { if (!SessionType.PAYM.equals(sessionType) && !SessionType.RSLT.equals(sessionType)) {
SettlementHouseProperties sttHs = stlmHPropsImdg.getFirstObjectByPredicate( SettlementHouseProperties sttHs = stlmHPropsImdg.getFirstObjectByPredicate(
pb.and( pb.and(
pb.in("currencyCode", curCode), pb.in("currencyCode", curCode),

View file

@ -165,7 +165,7 @@ public class InclusionToPoolAction extends AbstractSessionActionForOkErrorHandli
switch (ssnTpe) { switch (ssnTpe) {
case MEDM, FINL, XDEP -> execImdg = (Imdg<T>) executionDepositImdg; case MEDM, FINL, XDEP -> execImdg = (Imdg<T>) executionDepositImdg;
case IPO0, IPOB, TRDT, IPOT -> execImdg = (Imdg<T>) executionFondImdg; case IPO0, IPOB, TRDT, IPOT -> execImdg = (Imdg<T>) executionFondImdg;
case CURR, PAYM -> execImdg = (Imdg<T>) executionCurrImdg; case CURR, PAYM, RSLT -> execImdg = (Imdg<T>) executionCurrImdg;
default -> { default -> {
//кейс для "общих" сессий (напр. UNIT) в которых сочетаются разные сделки //кейс для "общих" сессий (напр. UNIT) в которых сочетаются разные сделки
//смотрим на секцию регистра. //смотрим на секцию регистра.
@ -211,6 +211,11 @@ public class InclusionToPoolAction extends AbstractSessionActionForOkErrorHandli
rgsPb.equals("sessionType", SessionType.PREP.getKey()), rgsPb.equals("sessionType", SessionType.PREP.getKey()),
rgsPb.equals("sessionType", SessionType.PAYM.getKey()) rgsPb.equals("sessionType", SessionType.PAYM.getKey())
); );
} else if (SessionType.RSLT.equals(sessionType)) {
return rgsPb.or(
rgsPb.equals("sessionType", SessionType.PREP.getKey()),
rgsPb.equals("sessionType", SessionType.RSLT.getKey())
);
} else { } else {
return rgsPb.equals("sessionType", sessionType.getKey()); return rgsPb.equals("sessionType", sessionType.getKey());
} }

View file

@ -154,7 +154,7 @@ public class InspectionObligationsV2Action extends ReviseStage1Action {
SessionType.MEDM.equals(sessionType) || SessionType.MEDM.equals(sessionType) ||
(SessionType.UNIT.equals(sessionType) && !Section.FOND.equalsByKey(obligation.getSection())); (SessionType.UNIT.equals(sessionType) && !Section.FOND.equalsByKey(obligation.getSection()));
boolean S_InstrTypeRegistry = RegistryInstrumentType.S.equalsByKey(obligation.getRegistryInstrumentType()); boolean S_InstrTypeRegistry = RegistryInstrumentType.S.equalsByKey(obligation.getRegistryInstrumentType());
if ((sessTypesBySecuritiesReg && S_InstrTypeRegistry) || SessionType.PAYM.equals(sessionType)) { if ((sessTypesBySecuritiesReg && S_InstrTypeRegistry) || SessionType.PAYM.equals(sessionType) || SessionType.RSLT.equals(sessionType)) {
checkResults.add(new CheckResult(obligation, false)); checkResults.add(new CheckResult(obligation, false));
continue; continue;
} }

View file

@ -243,7 +243,7 @@ public class RequirementAndObligationCreationAction extends AbstractSessionActio
} }
private boolean isCk() { private boolean isCk() {
return IEnumKey.contains(sessionType, SessionType.PREP, SessionType.PAYM); return IEnumKey.contains(sessionType, SessionType.PREP, SessionType.PAYM, SessionType.RSLT);
} }
private void createRegistryForCK( private void createRegistryForCK(

View file

@ -6,7 +6,7 @@ public enum SessionType implements IEnumKey {
IPOB("IPOB"), IPO0("IPO0"), IPOT("IPOT"), TRDT("TRDT"), IPOB("IPOB"), IPO0("IPO0"), IPOT("IPOT"), TRDT("TRDT"),
MEDM("MEDM"), FINL("FINL"), XDEP("XDEP"), LIQU("LIQU"), MEDM("MEDM"), FINL("FINL"), XDEP("XDEP"), LIQU("LIQU"),
CURR("CURR"), UNIT("UNIT"), CURR("CURR"), UNIT("UNIT"),
PREP("PREP"), PAYM("PAYM"), PREP("PREP"), PAYM("PAYM"), RSLT("RSLT"),
; ;
SessionType(String key) { SessionType(String key) {