currency session fix

This commit is contained in:
ialbert 2025-07-04 12:32:25 +03:00
parent 767347dbed
commit bc8c030714
6 changed files with 117 additions and 25 deletions

View file

@ -1,11 +1,10 @@
package ru.spcex.clearing.config.state_machine_2.specific; package ru.spcex.clearing.config.state_machine_2.specific;
import java.util.Arrays; import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.config.EnableStateMachineFactory; import org.springframework.statemachine.config.EnableStateMachineFactory;
@ -35,11 +34,13 @@ import ru.spcex.clearing.session.state.action.RequirementAndObligationCreationAc
import ru.spcex.clearing.session.state.action.ReviseStage1Action; import ru.spcex.clearing.session.state.action.ReviseStage1Action;
import ru.spcex.clearing.session.state.action.SaveRegistriesAndContinueAction; import ru.spcex.clearing.session.state.action.SaveRegistriesAndContinueAction;
import ru.spcex.clearing.session.state.action.Sdf56Action; import ru.spcex.clearing.session.state.action.Sdf56Action;
import ru.spcex.clearing.session.state.action.SdfReceivedAction;
import ru.spcex.clearing.session.state.guard.PaymentsWereCreatedGuard; import ru.spcex.clearing.session.state.guard.PaymentsWereCreatedGuard;
import ru.spcex.clearing.session.state.guard.PaymentsWereNotCreatedGuard; import ru.spcex.clearing.session.state.guard.PaymentsWereNotCreatedGuard;
import ru.spcex.clearing.session.state.guard.SdfGuard; import ru.spcex.clearing.session.state.guard.SdfGuard;
import ru.spcex.clearing.session.state.guard.SdfGuardExtractorAfterAgainRevise; import ru.spcex.clearing.session.state.guard.SdfGuardExtractorAfterAgainRevise;
import ru.spcex.clearing.session.state.guard.SdfGuardExtractorAfterAssets; 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.guard.StashedRegistriesPresentGuard;
import ru.spcex.clearing.session.state.listener.MachineMonitoringListener; import ru.spcex.clearing.session.state.listener.MachineMonitoringListener;
import static ru.spcex.clearing.util.StateMachineUtil.*; import static ru.spcex.clearing.util.StateMachineUtil.*;
@ -53,7 +54,6 @@ import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
@Configuration("intermediateMkrSessionStateMachineFactoryConfig") @Configuration("intermediateMkrSessionStateMachineFactoryConfig")
@EnableStateMachineFactory(name = "CURR") @EnableStateMachineFactory(name = "CURR")
public class CurrencySessionStateMachineConfig extends EnumStateMachineConfigurerAdapter<TaskType, SsnEvent> { public class CurrencySessionStateMachineConfig extends EnumStateMachineConfigurerAdapter<TaskType, SsnEvent> {
private final Logger log = LoggerFactory.getLogger(getClass());
private final Imdg<Session> sessionImdg; private final Imdg<Session> sessionImdg;
private final Sdf56Action sendSdf56Action; private final Sdf56Action sendSdf56Action;
private final ReviseStage1Action reviseStage1Action; private final ReviseStage1Action reviseStage1Action;
@ -66,7 +66,6 @@ public class CurrencySessionStateMachineConfig extends EnumStateMachineConfigure
private final AgainReviseStage3Action againRevise; private final AgainReviseStage3Action againRevise;
private final FinishingSessionAction finishingSessionAction; private final FinishingSessionAction finishingSessionAction;
private final EndStageNotificationAction endStageNotificationAction; private final EndStageNotificationAction endStageNotificationAction;
private final Imdg<ExecutionCurrency> executionCurrencyImdg;
private final SaveRegistriesAndContinueAction obligationAdmissionContinueAction; private final SaveRegistriesAndContinueAction obligationAdmissionContinueAction;
private final DiscardRegistriesAction discardOblAdmStash = private final DiscardRegistriesAction discardOblAdmStash =
new DiscardRegistriesAction(DataEnum.obligationAdmissionStashedRgs); new DiscardRegistriesAction(DataEnum.obligationAdmissionStashedRgs);
@ -74,7 +73,8 @@ public class CurrencySessionStateMachineConfig extends EnumStateMachineConfigure
DataEnum.obligationAdmissionStashedRgs DataEnum.obligationAdmissionStashedRgs
); );
private final Guard<TaskType, SsnEvent> reviseSuccessGuard = guardCheckCtxForFlag(DataEnum.againReviseSuccess); private final Guard<TaskType, SsnEvent> reviseSuccessGuard = guardCheckCtxForFlag(DataEnum.againReviseSuccess);
private final SessionType SESSION_TYPE = SessionType.MEDM; private final SessionType SESSION_TYPE = SessionType.CURR;
private final Section SECTION = Section.CURR;
public CurrencySessionStateMachineConfig(ImdgProvider imdgProvider, public CurrencySessionStateMachineConfig(ImdgProvider imdgProvider,
Sdf56Action sendSdf56Action, Sdf56Action sendSdf56Action,
@ -93,7 +93,6 @@ public class CurrencySessionStateMachineConfig extends EnumStateMachineConfigure
Supplier<List<String>> marketCodes, Supplier<List<String>> marketCodes,
SaveRegistriesAndContinueAction obligationAdmissionContinueAction) { SaveRegistriesAndContinueAction obligationAdmissionContinueAction) {
this.sessionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Session, Session.class); this.sessionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Session, Session.class);
this.executionCurrencyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionCurrency, ExecutionCurrency.class);
this.sendSdf56Action = sendSdf56Action; this.sendSdf56Action = sendSdf56Action;
this.reviseStage1Action = reviseStage1Action; this.reviseStage1Action = reviseStage1Action;
this.dealsPrepareAction = dealsPrepare; this.dealsPrepareAction = dealsPrepare;
@ -108,6 +107,7 @@ public class CurrencySessionStateMachineConfig extends EnumStateMachineConfigure
this.obligationAdmissionContinueAction = obligationAdmissionContinueAction; this.obligationAdmissionContinueAction = obligationAdmissionContinueAction;
this.finishingSessionAction.setPr("1"); this.finishingSessionAction.setPr("1");
Imdg<ExecutionCurrency> executionCurrencyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionCurrency, ExecutionCurrency.class);
dealsPrepareAction.searchForExecutions(ExecutionType.ExecutionCurrency); dealsPrepareAction.searchForExecutions(ExecutionType.ExecutionCurrency);
ImdgPredicateBuilder execFondPb = executionCurrencyImdg.predicateBuilder(); ImdgPredicateBuilder execFondPb = executionCurrencyImdg.predicateBuilder();
dealsPrepareAction.addExecutionCurrencyCondition(execFondPb.regex("settlementCode", "^T0.*$")); dealsPrepareAction.addExecutionCurrencyCondition(execFondPb.regex("settlementCode", "^T0.*$"));
@ -120,7 +120,7 @@ public class CurrencySessionStateMachineConfig extends EnumStateMachineConfigure
states states
.withStates() .withStates()
.initial(TaskType.StartRevise, chain( .initial(TaskType.StartRevise, chain(
new CreateSessionAction(sessionImdg, SessionType.MEDM, Section.MKR), new CreateSessionAction(sessionImdg, SESSION_TYPE, SECTION),
sendSdf56Action)) sendSdf56Action))
.states(new HashSet<>(Arrays.asList( .states(new HashSet<>(Arrays.asList(
TaskType.StartRevise, TaskType.StartRevise,
@ -167,12 +167,6 @@ public class CurrencySessionStateMachineConfig extends EnumStateMachineConfigure
.source(TaskType.InspectionObligations).target(TaskType.FormingPaymentInstruction) .source(TaskType.InspectionObligations).target(TaskType.FormingPaymentInstruction)
.action(formingPaymentInstructionAssetsAction) .action(formingPaymentInstructionAssetsAction)
.and() .and()
.withExternal()
.source(TaskType.PSEUDO_waitSdfAfterPaymentInstructions)
.target(TaskType.AgainRevise)
.guard(new SdfGuard(SdfGuardExtractorAfterAssets.instance))
.action(againRevise)
.and()
.withExternal() .withExternal()
.source(TaskType.PSEUDO_waitSdfAfterAgainRevise) .source(TaskType.PSEUDO_waitSdfAfterAgainRevise)
.target(TaskType.AgainRevise) .target(TaskType.AgainRevise)
@ -186,6 +180,7 @@ public class CurrencySessionStateMachineConfig extends EnumStateMachineConfigure
sourceObligationAdmission(transitions); sourceObligationAdmission(transitions);
sourcePseudoAfterOAError(transitions); sourcePseudoAfterOAError(transitions);
sourceFormingPaymentInstruction(transitions); sourceFormingPaymentInstruction(transitions);
sourcePseudoWaitSdfAfterPaymentInstructions(transitions);
sourceAgainRevise(transitions); sourceAgainRevise(transitions);
} }
@ -231,6 +226,23 @@ public class CurrencySessionStateMachineConfig extends EnumStateMachineConfigure
.guard(PaymentsWereCreatedGuard.instance); .guard(PaymentsWereCreatedGuard.instance);
} }
private void sourcePseudoWaitSdfAfterPaymentInstructions(StateMachineTransitionConfigurer<TaskType, SsnEvent> transitions) throws Exception {
EnumSet<SsnEvent> 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<TaskType, SsnEvent> transitions) throws Exception { private void sourceAgainRevise(StateMachineTransitionConfigurer<TaskType, SsnEvent> transitions) throws Exception {
transitions transitions
.withExternal() .withExternal()

View file

@ -4,6 +4,9 @@ public enum SsnEvent {
SDF_01, SDF_01,
SDF_57, SDF_57,
SDF_04, SDF_04,
SDF_13,
SDF_08,
SDF_21,
PAUSE, PAUSE,
CONTINUE, CONTINUE,
REPEAT REPEAT

View file

@ -56,10 +56,10 @@ import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD;
public class FormingPaymentInstructionSecuritiesAction extends AbstractSessionActionForOkErrorHandling { public class FormingPaymentInstructionSecuritiesAction extends AbstractSessionActionForOkErrorHandling {
private final Logger log = LoggerFactory.getLogger(getClass()); private final Logger log = LoggerFactory.getLogger(getClass());
private ImdgProvider imdgProvider; private final ImdgProvider imdgProvider;
private Imdg<Registry> registryImdg; private final Imdg<Registry> registryImdg;
private Imdg<PaymentInstruction> paymentInstructionImdg; private final Imdg<PaymentInstruction> paymentInstructionImdg;
private Imdg<Account> accountImdg; private final Imdg<Account> accountImdg;
private final RegistryManager rgsMng; private final RegistryManager rgsMng;
private final Sdf03And12Sender sdf03And12Sender; private final Sdf03And12Sender sdf03And12Sender;

View file

@ -1,6 +1,5 @@
package ru.spcex.clearing.session.state.guard; package ru.spcex.clearing.session.state.guard;
import java.util.Collections;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.Set; import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
@ -8,7 +7,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.statemachine.StateContext; import org.springframework.statemachine.StateContext;
import ru.spcex.clearing.session.stage.TaskType; import ru.spcex.clearing.session.stage.TaskType;
import ru.spcex.clearing.session.stage.impl.PaymentInfo;
import ru.spcex.clearing.session.state.DataEnum; import ru.spcex.clearing.session.state.DataEnum;
import ru.spcex.clearing.session.state.SsnEvent; import ru.spcex.clearing.session.state.SsnEvent;
import ru.spcex.platform.enumeration.SdfTable; import ru.spcex.platform.enumeration.SdfTable;
@ -26,11 +24,11 @@ public class SdfGuardExtractorAfterAssets implements Function<StateContext<TaskT
if (section == null) { if (section == null) {
throw new IllegalStateException("section is null"); throw new IllegalStateException("section is null");
} }
PaymentInfo pmts = ctx.getExtendedState().get(DataEnum.paymentInfo, PaymentInfo.class); // PaymentInfo pmts = ctx.getExtendedState().get(DataEnum.paymentInfo, PaymentInfo.class);
if (pmts == null || pmts.getPaymentInstructions().isEmpty()) { // if (pmts == null || pmts.getPaymentInstructions().isEmpty()) {
log.warn("SdfGuard defined, but no DataEnum.paymentInfo present in extended state"); // log.warn("SdfGuard defined, but no DataEnum.paymentInfo present in extended state");
return Collections.emptySet(); // return Collections.emptySet();
} // }
switch (section) { switch (section) {
case MKR -> { case MKR -> {
return EnumSet.of( return EnumSet.of(

View file

@ -0,0 +1,31 @@
package ru.spcex.clearing.session.state.guard;
import java.util.EnumSet;
import ru.spcex.clearing.session.state.SsnEvent;
import ru.spcex.platform.enumeration.Section;
public class SdfGuardUtil {
public static EnumSet<SsnEvent> bySectionAfter7Step(Section section) {
switch (section) {
case MKR -> {
return EnumSet.of(
SsnEvent.SDF_04,
SsnEvent.SDF_01,
SsnEvent.SDF_57
);
}
case FOND, MULT -> {
return EnumSet.of(
SsnEvent.SDF_04,
SsnEvent.SDF_13,
SsnEvent.SDF_08,
SsnEvent.SDF_21,
SsnEvent.SDF_01,
SsnEvent.SDF_57
);
}
default -> throw new IllegalStateException("unknown wait conditions for section " + section);
}
}
}

View file

@ -0,0 +1,48 @@
package ru.spcex.clearing.session.state.guard;
import java.util.EnumSet;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.statemachine.ExtendedState;
import org.springframework.statemachine.StateContext;
import org.springframework.statemachine.guard.Guard;
import ru.spcex.clearing.session.stage.TaskType;
import ru.spcex.clearing.session.state.SsnEvent;
public class SdfSetGuard implements Guard<TaskType, SsnEvent> {
private final Logger log = LoggerFactory.getLogger(getClass());
private final EnumSet<SsnEvent> sdfs;
public SdfSetGuard(SsnEvent first, SsnEvent... rest) {
this.sdfs = EnumSet.of(first, rest);
}
public SdfSetGuard(EnumSet<SsnEvent> sdfs) {
this.sdfs = sdfs;
}
@Override
public boolean evaluate(StateContext<TaskType, SsnEvent> ctx) {
ExtendedState state = ctx.getExtendedState();
Function<SsnEvent, Boolean> was = sdf -> state.get(sdf.name(), Object.class) != null;
boolean everySdfConditionMet = sdfs
.stream()
.allMatch(was::apply);
if (everySdfConditionMet) {
log.info("all of {} conditions were met", sdfs);
sdfs.forEach(sdf -> state.getVariables().remove(sdf.name()));
return true;
} else {
log.info("conditions: {}",
sdfs
.stream()
.map(sdf -> "%s: %s".formatted(sdf.name(), was.apply(sdf) ? "received" : "waiting"))
.collect(Collectors.joining(";", "[", "]"))
);
return false;
}
}
}