FinalMkrSession spring state machine
This commit is contained in:
parent
05d1135ae2
commit
68496730c6
19 changed files with 940 additions and 93 deletions
|
|
@ -2,13 +2,9 @@ package ru.spcex.clearing.config.state_machine_2.specific;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
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.function.Supplier;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
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;
|
||||||
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
|
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
|
||||||
|
|
@ -16,7 +12,6 @@ import org.springframework.statemachine.config.builders.StateMachineConfiguratio
|
||||||
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
|
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
|
||||||
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
|
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
|
||||||
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
|
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
|
||||||
import org.springframework.statemachine.state.State;
|
|
||||||
import ru.clearing.classes.statics.data.misc.Session;
|
import ru.clearing.classes.statics.data.misc.Session;
|
||||||
import ru.clearing.classes.statics.data.registry.Registry;
|
import ru.clearing.classes.statics.data.registry.Registry;
|
||||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||||
|
|
@ -24,6 +19,8 @@ import ru.spcex.clearing.session.stage.TaskType;
|
||||||
import ru.spcex.clearing.session.state.SsnEvent;
|
import ru.spcex.clearing.session.state.SsnEvent;
|
||||||
import ru.spcex.clearing.session.state.action.CreateSessionAction;
|
import ru.spcex.clearing.session.state.action.CreateSessionAction;
|
||||||
import ru.spcex.clearing.session.state.action.DealsPrepareAction;
|
import ru.spcex.clearing.session.state.action.DealsPrepareAction;
|
||||||
|
import ru.spcex.clearing.session.state.action.EndStageNotificationAction;
|
||||||
|
import ru.spcex.clearing.session.state.action.FinishingSessionAction;
|
||||||
import ru.spcex.clearing.session.state.action.FormingPaymentInstructionAssetsAction;
|
import ru.spcex.clearing.session.state.action.FormingPaymentInstructionAssetsAction;
|
||||||
import ru.spcex.clearing.session.state.action.FormingPaymentInstructionReturnMkrAction;
|
import ru.spcex.clearing.session.state.action.FormingPaymentInstructionReturnMkrAction;
|
||||||
import ru.spcex.clearing.session.state.action.InclusionToPoolAction;
|
import ru.spcex.clearing.session.state.action.InclusionToPoolAction;
|
||||||
|
|
@ -33,9 +30,16 @@ import ru.spcex.clearing.session.state.action.ObligationAdmissionAction;
|
||||||
import ru.spcex.clearing.session.state.action.RequirementAndObligationCreationAction;
|
import ru.spcex.clearing.session.state.action.RequirementAndObligationCreationAction;
|
||||||
import ru.spcex.clearing.session.state.action.ReviseStage1;
|
import ru.spcex.clearing.session.state.action.ReviseStage1;
|
||||||
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.PaymentsWereNotCreatedGuard;
|
||||||
|
import ru.spcex.clearing.session.state.guard.SdfGuard;
|
||||||
|
import ru.spcex.clearing.session.state.guard.SdfGuardExtractorAfterAssets;
|
||||||
|
import ru.spcex.clearing.session.state.listener.MachineMonitoringListener;
|
||||||
import ru.spcex.clearing.util.StateMachineUtil;
|
import ru.spcex.clearing.util.StateMachineUtil;
|
||||||
import ru.spcex.platform.classes.base.interfaces.ExecutionType;
|
import ru.spcex.platform.classes.base.interfaces.ExecutionType;
|
||||||
import ru.spcex.platform.enumeration.RegistryStatus;
|
import ru.spcex.platform.enumeration.RegistryStatus;
|
||||||
|
import ru.spcex.platform.enumeration.Section;
|
||||||
import ru.spcex.platform.enumeration.SessionType;
|
import ru.spcex.platform.enumeration.SessionType;
|
||||||
import ru.spcex.platform.imdg.api.Imdg;
|
import ru.spcex.platform.imdg.api.Imdg;
|
||||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||||
|
|
@ -45,10 +49,8 @@ import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
|
||||||
@EnableStateMachineFactory(name = "FINL")
|
@EnableStateMachineFactory(name = "FINL")
|
||||||
public class FinalSessionStateMachineConfig
|
public class FinalSessionStateMachineConfig
|
||||||
extends EnumStateMachineConfigurerAdapter<TaskType, SsnEvent> {
|
extends EnumStateMachineConfigurerAdapter<TaskType, SsnEvent> {
|
||||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
|
||||||
|
|
||||||
private final Imdg<Session> sessionImdg;
|
private final Imdg<Session> sessionImdg;
|
||||||
private final Imdg<Registry> rgsImdg;
|
|
||||||
private final Sdf56Action sendSdf56Action;
|
private final Sdf56Action sendSdf56Action;
|
||||||
private final ReviseStage1 reviseStage1Action;
|
private final ReviseStage1 reviseStage1Action;
|
||||||
private final DealsPrepareAction dealsPrepareAction;
|
private final DealsPrepareAction dealsPrepareAction;
|
||||||
|
|
@ -59,13 +61,16 @@ public class FinalSessionStateMachineConfig
|
||||||
private final InspectionObligationsV2Action inspectionObligationsV2Action;
|
private final InspectionObligationsV2Action inspectionObligationsV2Action;
|
||||||
private final FormingPaymentInstructionReturnMkrAction formingPaymentInstructionReturnMkrAction;
|
private final FormingPaymentInstructionReturnMkrAction formingPaymentInstructionReturnMkrAction;
|
||||||
private final FormingPaymentInstructionAssetsAction formingPaymentInstructionAssetsAction;
|
private final FormingPaymentInstructionAssetsAction formingPaymentInstructionAssetsAction;
|
||||||
|
private final FinishingSessionAction finishingSessionAction;
|
||||||
|
private final EndStageNotificationAction endStageNotificationAction;
|
||||||
|
|
||||||
|
private final SessionType SESSION_TYPE = SessionType.FINL;
|
||||||
|
private final Section SECTION = Section.MKR;
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public FinalSessionStateMachineConfig(
|
public FinalSessionStateMachineConfig(
|
||||||
ImdgProvider imdgProvider,
|
ImdgProvider imdgProvider,
|
||||||
@Qualifier("marketCodesForBn")
|
|
||||||
Supplier<List<String>> marketCodes,
|
|
||||||
Sdf56Action sendSdf56Action,
|
Sdf56Action sendSdf56Action,
|
||||||
ReviseStage1 reviseStage1Action,
|
ReviseStage1 reviseStage1Action,
|
||||||
DealsPrepareAction dealsPrepareAction,
|
DealsPrepareAction dealsPrepareAction,
|
||||||
|
|
@ -75,11 +80,12 @@ public class FinalSessionStateMachineConfig
|
||||||
InspectionObligationsDepositReturnAction inspOblDepositReturnAction,
|
InspectionObligationsDepositReturnAction inspOblDepositReturnAction,
|
||||||
InspectionObligationsV2Action inspectionObligationsV2Action,
|
InspectionObligationsV2Action inspectionObligationsV2Action,
|
||||||
FormingPaymentInstructionReturnMkrAction formingPaymentInstructionReturnMkrAction,
|
FormingPaymentInstructionReturnMkrAction formingPaymentInstructionReturnMkrAction,
|
||||||
FormingPaymentInstructionAssetsAction formingPaymentInstructionAssetsAction
|
FormingPaymentInstructionAssetsAction formingPaymentInstructionAssetsAction,
|
||||||
|
FinishingSessionAction finishingSessionAction, EndStageNotificationAction endStageNotificationAction
|
||||||
) {
|
) {
|
||||||
this.sendSdf56Action = sendSdf56Action;
|
this.sendSdf56Action = sendSdf56Action;
|
||||||
this.sessionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Session, Session.class);
|
this.sessionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Session, Session.class);
|
||||||
this.rgsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
|
Imdg<Registry> rgsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
|
||||||
this.reviseStage1Action = reviseStage1Action;
|
this.reviseStage1Action = reviseStage1Action;
|
||||||
this.dealsPrepareAction = dealsPrepareAction;
|
this.dealsPrepareAction = dealsPrepareAction;
|
||||||
this.reqAndOblAction = reqAndOblAction;
|
this.reqAndOblAction = reqAndOblAction;
|
||||||
|
|
@ -89,6 +95,10 @@ public class FinalSessionStateMachineConfig
|
||||||
this.inspectionObligationsV2Action = inspectionObligationsV2Action;
|
this.inspectionObligationsV2Action = inspectionObligationsV2Action;
|
||||||
this.formingPaymentInstructionReturnMkrAction = formingPaymentInstructionReturnMkrAction;
|
this.formingPaymentInstructionReturnMkrAction = formingPaymentInstructionReturnMkrAction;
|
||||||
this.formingPaymentInstructionAssetsAction = formingPaymentInstructionAssetsAction;
|
this.formingPaymentInstructionAssetsAction = formingPaymentInstructionAssetsAction;
|
||||||
|
this.finishingSessionAction = finishingSessionAction;
|
||||||
|
this.endStageNotificationAction = endStageNotificationAction;
|
||||||
|
this.finishingSessionAction.setSessionType(SESSION_TYPE);
|
||||||
|
this.finishingSessionAction.setSection(SECTION);
|
||||||
|
|
||||||
//stages settings:
|
//stages settings:
|
||||||
ImdgPredicateBuilder rgsPrctBuilder = rgsImdg.predicateBuilder();
|
ImdgPredicateBuilder rgsPrctBuilder = rgsImdg.predicateBuilder();
|
||||||
|
|
@ -102,16 +112,19 @@ public class FinalSessionStateMachineConfig
|
||||||
rgsPrctBuilder.lessEqual("valueDate", LocalDate.now())
|
rgsPrctBuilder.lessEqual("valueDate", LocalDate.now())
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
this.inspOblDepositReturnAction.setSessionType(SessionType.FINL);
|
this.inspOblDepositReturnAction.setSessionType(SESSION_TYPE);
|
||||||
this.inspectionObligationsV2Action.setSessionType(SessionType.FINL);
|
this.inspectionObligationsV2Action.setSessionType(SESSION_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configure(StateMachineStateConfigurer<TaskType, SsnEvent> states) throws Exception {
|
public void configure(StateMachineStateConfigurer<TaskType, SsnEvent> states) throws Exception {
|
||||||
states
|
states
|
||||||
.withStates()
|
.withStates()
|
||||||
.initial(TaskType.StartRevise, StateMachineUtil.chain(new CreateSessionAction(sessionImdg), sendSdf56Action))
|
.initial(TaskType.StartRevise, StateMachineUtil.chain(
|
||||||
//.state(TaskType.StartRevise, sendSdf56Action) //entry action
|
new CreateSessionAction(sessionImdg)
|
||||||
|
.sessionType(SESSION_TYPE)
|
||||||
|
.section(SECTION),
|
||||||
|
sendSdf56Action))
|
||||||
.states(new HashSet<>(Arrays.asList(
|
.states(new HashSet<>(Arrays.asList(
|
||||||
TaskType.StartRevise,
|
TaskType.StartRevise,
|
||||||
TaskType.StartRevisePart1,
|
TaskType.StartRevisePart1,
|
||||||
|
|
@ -125,7 +138,8 @@ public class FinalSessionStateMachineConfig
|
||||||
TaskType.FormingPaymentInstruction,
|
TaskType.FormingPaymentInstruction,
|
||||||
TaskType.FormingPaymentInstruction,
|
TaskType.FormingPaymentInstruction,
|
||||||
TaskType.FinishingSession,
|
TaskType.FinishingSession,
|
||||||
TaskType.EndStageNotification
|
TaskType.EndStageNotification,
|
||||||
|
TaskType.PSEUDO_waitingForSdf
|
||||||
)))
|
)))
|
||||||
.end(TaskType.EndStageNotification);
|
.end(TaskType.EndStageNotification);
|
||||||
}
|
}
|
||||||
|
|
@ -164,26 +178,46 @@ public class FinalSessionStateMachineConfig
|
||||||
.source(TaskType.InspectionObligations).target(TaskType.FormingPaymentInstruction)
|
.source(TaskType.InspectionObligations).target(TaskType.FormingPaymentInstruction)
|
||||||
.action(formingPaymentInstructionReturnMkrAction)
|
.action(formingPaymentInstructionReturnMkrAction)
|
||||||
.action(formingPaymentInstructionAssetsAction)
|
.action(formingPaymentInstructionAssetsAction)
|
||||||
;
|
.and()
|
||||||
|
//если не создалось paymentInstruction'ов
|
||||||
|
.withExternal()
|
||||||
|
.source(TaskType.FormingPaymentInstruction)
|
||||||
//TaskType.RequirementsAndObligationsCreate
|
.target(TaskType.FinishingSession)
|
||||||
|
.guard(PaymentsWereNotCreatedGuard.instance)
|
||||||
|
.action(finishingSessionAction)
|
||||||
|
.and()
|
||||||
|
//если создались paymentInstruction, переходим в режим ожидания
|
||||||
|
.withExternal()
|
||||||
|
.source(TaskType.FormingPaymentInstruction)
|
||||||
|
.target(TaskType.PSEUDO_waitingForSdf)
|
||||||
|
.guard(PaymentsWereCreatedGuard.instance)
|
||||||
|
.and()
|
||||||
|
.withExternal()
|
||||||
|
.source(TaskType.PSEUDO_waitingForSdf)
|
||||||
|
.target(TaskType.FinishingSession)
|
||||||
|
.guard(new SdfGuard(SdfGuardExtractorAfterAssets.instance))
|
||||||
|
.action(finishingSessionAction)
|
||||||
|
.and()
|
||||||
|
.withExternal()
|
||||||
|
.source(TaskType.FinishingSession)
|
||||||
|
.target(TaskType.EndStageNotification)
|
||||||
|
.action(endStageNotificationAction);
|
||||||
|
for (var event: EnumSet.of(SsnEvent.SDF_01, SsnEvent.SDF_57, SsnEvent.SDF_04)) {
|
||||||
|
transitions
|
||||||
|
.withInternal()
|
||||||
|
.source(TaskType.PSEUDO_waitingForSdf)
|
||||||
|
.event(event)
|
||||||
|
.action(SdfReceivedAction.instance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configure(StateMachineConfigurationConfigurer<TaskType, SsnEvent> config) throws Exception {
|
public void configure(StateMachineConfigurationConfigurer<TaskType, SsnEvent> config) throws Exception {
|
||||||
StateMachineListenerAdapter<TaskType, SsnEvent> loggingChangeStateListener = new StateMachineListenerAdapter<>() {
|
StateMachineListenerAdapter<TaskType, SsnEvent> loggingChangeStateListener
|
||||||
@Override
|
= new MachineMonitoringListener(SESSION_TYPE.getKey());
|
||||||
public void stateEntered(State<TaskType, SsnEvent> state) {
|
|
||||||
TaskType enteredState = state != null ? state.getId() : null;
|
|
||||||
log.info("State entered: {}", enteredState);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
config
|
config
|
||||||
.withConfiguration()
|
.withConfiguration()
|
||||||
.machineId(SessionType.FINL.getKey())
|
.machineId(SESSION_TYPE.getKey())
|
||||||
.listener(loggingChangeStateListener)
|
.listener(loggingChangeStateListener)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,9 @@ public enum TaskType implements IEnumKey {
|
||||||
/**
|
/**
|
||||||
* Step 11
|
* Step 11
|
||||||
*/
|
*/
|
||||||
EndStageNotification("CL11");
|
EndStageNotification("CL11"),
|
||||||
|
PSEUDO_waitingForSdf("PSEUDO_waitingForSdf")
|
||||||
|
;
|
||||||
|
|
||||||
private String key;
|
private String key;
|
||||||
|
|
||||||
|
|
@ -67,4 +69,8 @@ public enum TaskType implements IEnumKey {
|
||||||
public String getKey() {
|
public String getKey() {
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPseudoStatus() {
|
||||||
|
return this.key.startsWith("PSEUDO");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
package ru.spcex.clearing.session.state;
|
package ru.spcex.clearing.session.state;
|
||||||
|
|
||||||
public enum ActionHeader {
|
public enum ActionHeader {
|
||||||
sdf56FromTime;
|
sdf56FromTime, pr;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package ru.spcex.clearing.session.state;
|
||||||
public enum DataEnum {
|
public enum DataEnum {
|
||||||
sessionId, //Long
|
sessionId, //Long
|
||||||
sessionType, //Session
|
sessionType, //Session
|
||||||
|
section,
|
||||||
session, //Session
|
session, //Session
|
||||||
dealsPrepared, //List<ExecutionCommon>
|
dealsPrepared, //List<ExecutionCommon>
|
||||||
counterPartyId, //Long
|
counterPartyId, //Long
|
||||||
|
|
|
||||||
|
|
@ -4,4 +4,7 @@ public enum SsnEvent {
|
||||||
Revise,
|
Revise,
|
||||||
Sdf57Processed,
|
Sdf57Processed,
|
||||||
SdfReceived,
|
SdfReceived,
|
||||||
|
SDF_01,
|
||||||
|
SDF_57,
|
||||||
|
SDF_04,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,27 +17,43 @@ import ru.spcex.platform.imdg.api.Imdg;
|
||||||
public class CreateSessionAction extends AbstractSessionActionForOkErrorHandling {
|
public class CreateSessionAction extends AbstractSessionActionForOkErrorHandling {
|
||||||
private final Imdg<Session> sessionImdg;
|
private final Imdg<Session> sessionImdg;
|
||||||
private final Logger log = LoggerFactory.getLogger(CreateSessionAction.class);
|
private final Logger log = LoggerFactory.getLogger(CreateSessionAction.class);
|
||||||
|
private SessionType sessionType;
|
||||||
|
private Section section;
|
||||||
|
|
||||||
public CreateSessionAction(Imdg<Session> sessionImdg) {
|
public CreateSessionAction(Imdg<Session> sessionImdg) {
|
||||||
this.sessionImdg = sessionImdg;
|
this.sessionImdg = sessionImdg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CreateSessionAction sessionType(SessionType sessionType) {
|
||||||
|
this.sessionType = sessionType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CreateSessionAction section(Section section) {
|
||||||
|
this.section = section;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actualExecute(StateContext<TaskType, SsnEvent> context) {
|
public void actualExecute(StateContext<TaskType, SsnEvent> context) {
|
||||||
Session existActiveSession = sessionImdg.getFirstObjectByFieldValues(Map.of("workflowStatus", SessionStatus.ACTV.getKey()));
|
Session existActiveSession = sessionImdg.getFirstObjectByFieldValues(Map.of("workflowStatus", SessionStatus.ACTV.getKey()));
|
||||||
if (existActiveSession != null) {
|
if (existActiveSession != null) {
|
||||||
throw new RuntimeException("ActiveSessionIsPresent " + existActiveSession);
|
throw new RuntimeException("ActiveSessionIsPresent " + existActiveSession);
|
||||||
}
|
}
|
||||||
|
if (section == null | sessionType == null) {
|
||||||
|
throw new RuntimeException("CreateSessionAction is misconfigured: no section/sessionType");
|
||||||
|
}
|
||||||
Session newSession = new Session();
|
Session newSession = new Session();
|
||||||
newSession.setSection(Section.FOND.getKey());//fixme
|
newSession.setSection(section.getKey());
|
||||||
newSession.setSessionType(SessionType.IPOB.getKey());//fixme
|
newSession.setSessionType(sessionType.getKey());
|
||||||
newSession.setSessionStatus(TaskType.StartRevise.getKey());
|
newSession.setSessionStatus(TaskType.StartRevise.getKey());
|
||||||
newSession.setWorkflowStatus(SessionStatus.ACTV.getKey());
|
newSession.setWorkflowStatus(SessionStatus.ACTV.getKey());
|
||||||
newSession.setClearingDate(LocalDate.now());
|
newSession.setClearingDate(LocalDate.now());
|
||||||
sessionImdg.insert(newSession);
|
sessionImdg.insert(newSession);
|
||||||
log.info("started new session.id={}", newSession.getId());
|
log.info("started new session.id={}", newSession.getId());
|
||||||
context.getExtendedState().getVariables().put(DataEnum.sessionId.name(), newSession.getId());
|
context.getExtendedState().getVariables().put(DataEnum.sessionId.name(), newSession.getId());
|
||||||
context.getExtendedState().getVariables().put(DataEnum.sessionType.name(), SessionType.IPOB);
|
context.getExtendedState().getVariables().put(DataEnum.sessionType.name(), sessionType);
|
||||||
|
context.getExtendedState().getVariables().put(DataEnum.section.name(), section);
|
||||||
context.getExtendedState().getVariables().put(DataEnum.session.name(), newSession);
|
context.getExtendedState().getVariables().put(DataEnum.session.name(), newSession);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,123 @@
|
||||||
|
package ru.spcex.clearing.session.state.action;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.springframework.statemachine.StateContext;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import ru.clearing.classes.statics.data.misc.Session;
|
||||||
|
import ru.clearing.classes.statics.data.registry.Registry;
|
||||||
|
import static ru.spcex.clearing.error.ClearingErrorInternal.SessionGeneralError;
|
||||||
|
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||||
|
import ru.spcex.clearing.platform.messaging.domain.Consts;
|
||||||
|
import ru.spcex.clearing.platform.messaging.domain.cud.clearing.SdfClearingRequest;
|
||||||
|
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
|
||||||
|
import ru.spcex.clearing.session.stage.TaskType;
|
||||||
|
import ru.spcex.clearing.session.state.DataEnum;
|
||||||
|
import ru.spcex.clearing.session.state.SsnEvent;
|
||||||
|
import ru.spcex.platform.enumeration.RegistryStatus;
|
||||||
|
import ru.spcex.platform.enumeration.Section;
|
||||||
|
import ru.spcex.platform.enumeration.SessionStatus;
|
||||||
|
import ru.spcex.platform.imdg.api.Imdg;
|
||||||
|
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||||
|
import ru.spcex.platform.utils.enumeration.EnumMessage;
|
||||||
|
import ru.spcex.platform.utils.enumeration.IMessageResolver;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||||
|
public class EndStageNotificationAction extends AbstractSessionActionForOkErrorHandling {
|
||||||
|
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
|
private final Imdg<Registry> registryImdg;
|
||||||
|
private final Imdg<Session> sessionImdg;
|
||||||
|
private final KafkaSender kafkaSender;
|
||||||
|
private final IMessageResolver msgResolver;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public EndStageNotificationAction(ImdgProvider imdgProvider, KafkaSender kafkaSender, IMessageResolver msgResolver) {
|
||||||
|
this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
|
||||||
|
this.sessionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Session, Session.class);
|
||||||
|
this.kafkaSender = kafkaSender;
|
||||||
|
this.msgResolver = msgResolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void actualExecute(StateContext<TaskType, SsnEvent> ctx) {
|
||||||
|
Long sessionId = ctx.getExtendedState().get(DataEnum.sessionId, Long.class);
|
||||||
|
String section = ctx.getExtendedState().get(DataEnum.section, String.class);
|
||||||
|
// 1. Изменить статус
|
||||||
|
Session theSession = sessionImdg.getSingleObjectByID(sessionId);
|
||||||
|
if (theSession == null) {
|
||||||
|
log.warn("Session {} not found", sessionId);
|
||||||
|
} else {
|
||||||
|
log.info("Finish status for session {}", sessionId);
|
||||||
|
theSession.setUpdated(Instant.now());
|
||||||
|
theSession.setSessionStatus(SessionStatus.CLOS.getKey());
|
||||||
|
sessionImdg.update(theSession);
|
||||||
|
log.trace("Session {} was updated", theSession.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection<Registry> forRegistries = selectRegistry();
|
||||||
|
Collection<Long> groups = forRegistries.stream()
|
||||||
|
.map(Registry::getGroupId)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.distinct().collect(Collectors.toList());
|
||||||
|
log.debug("Sending notifications for {} groups ({} registers) on section {}",
|
||||||
|
groups, forRegistries.size(), section);
|
||||||
|
for (Long groupId : groups) {
|
||||||
|
log.trace("For registry group {} send notification",
|
||||||
|
groupId);
|
||||||
|
Optional<EnumMessage> sResult;
|
||||||
|
if (Section.FOND.equalsByKey(section)) {
|
||||||
|
sResult = notificationDF14(groupId);
|
||||||
|
} else if (Section.MKR.equalsByKey(section)) {
|
||||||
|
sResult = notificationDF05(groupId);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Unsupported section " + section);
|
||||||
|
}
|
||||||
|
sResult.ifPresent(enumMessage ->
|
||||||
|
log.error("When sending groupId={} has error: {}", groupId, msgResolver.resolve(enumMessage)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Collection<Registry> selectRegistry() {
|
||||||
|
String registrySQL = "registryStatus='" + RegistryStatus.OK.getKey() + "'";
|
||||||
|
Collection<Registry> result = registryImdg.getCollectionObjectsBySQL(registrySQL);
|
||||||
|
log.trace("Selected {} registry's by sql: {}", result.size(), registrySQL);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Optional<EnumMessage> notificationDF14(Long groupId) {
|
||||||
|
SdfClearingRequest sdf14Request = new SdfClearingRequest();
|
||||||
|
sdf14Request.setGroupId(groupId);
|
||||||
|
Long msgKey = kafkaSender.sendRequestToQueue(Consts.SDF14_PROCESS, sdf14Request);
|
||||||
|
if (msgKey == null) {
|
||||||
|
log.error("failed to put SDF14 request to kafka queue");
|
||||||
|
return Optional.of(new EnumMessage(SessionGeneralError));
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Optional<EnumMessage> notificationDF05(Long groupId) {
|
||||||
|
SdfClearingRequest sdf05Request = new SdfClearingRequest();
|
||||||
|
sdf05Request.setGroupId(groupId);
|
||||||
|
Long msgKey = kafkaSender.sendRequestToQueue(Consts.SDF05_PROCESS, sdf05Request);
|
||||||
|
if (msgKey == null) {
|
||||||
|
log.error("failed to put SDF05 request to kafka queue");
|
||||||
|
return Optional.of(new EnumMessage(SessionGeneralError));
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,376 @@
|
||||||
|
package ru.spcex.clearing.session.state.action;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.springframework.statemachine.StateContext;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import ru.clearing.classes.statics.data.execution.ExecutionCommon;
|
||||||
|
import ru.clearing.classes.statics.data.execution.ExecutionCurrency;
|
||||||
|
import ru.clearing.classes.statics.data.execution.ExecutionDeposit;
|
||||||
|
import ru.clearing.classes.statics.data.execution.ExecutionFond;
|
||||||
|
import ru.clearing.classes.statics.data.misc.Session;
|
||||||
|
import ru.clearing.classes.statics.data.registry.Registry;
|
||||||
|
import ru.clearing.classes.statics.data.sdf.SDf05;
|
||||||
|
import static ru.spcex.clearing.error.ClearingErrorInternal.SessionGeneralError;
|
||||||
|
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||||
|
import ru.spcex.clearing.platform.messaging.domain.Consts;
|
||||||
|
import ru.spcex.clearing.platform.messaging.domain.cud.reports.ReportRequestWithRegistryId;
|
||||||
|
import ru.spcex.clearing.platform.messaging.domain.cud.reports.ReportRequestWithSessionId;
|
||||||
|
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
|
||||||
|
import ru.spcex.clearing.service.Sdf05Sender;
|
||||||
|
import ru.spcex.clearing.service.Sdf14Sender;
|
||||||
|
import ru.spcex.clearing.session.stage.TaskType;
|
||||||
|
import ru.spcex.clearing.session.state.ActionHeader;
|
||||||
|
import ru.spcex.clearing.session.state.DataEnum;
|
||||||
|
import ru.spcex.clearing.session.state.SsnEvent;
|
||||||
|
import ru.spcex.platform.classes.base.interfaces.ExecutionType;
|
||||||
|
import ru.spcex.platform.enumeration.CoverageStatus;
|
||||||
|
import ru.spcex.platform.enumeration.RegistryDesignation;
|
||||||
|
import ru.spcex.platform.enumeration.RegistryStatus;
|
||||||
|
import ru.spcex.platform.enumeration.RegistryTradingParams;
|
||||||
|
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.ImdgPredicate;
|
||||||
|
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
|
||||||
|
import ru.spcex.platform.imdg.api.predicate.specific.RegistryCodeSqlBuilder;
|
||||||
|
import ru.spcex.platform.utils.collection.Pair;
|
||||||
|
import ru.spcex.platform.utils.enumeration.EnumMessage;
|
||||||
|
import ru.spcex.platform.utils.enumeration.IEnumKey;
|
||||||
|
import static ru.spcex.platform.utils.enumeration.IEnumKey.getEnumByKey;
|
||||||
|
import ru.spcex.platform.utils.enumeration.IMessageResolver;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||||
|
public class FinishingSessionAction extends AbstractSessionActionForOkErrorHandling {
|
||||||
|
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
|
private final ImdgProvider imdgProvider;
|
||||||
|
private final Imdg<Registry> registryImdg;
|
||||||
|
private final Imdg<ExecutionFond> executionFondImdg;
|
||||||
|
private final Imdg<ExecutionDeposit> executionDepositImdg;
|
||||||
|
private final Imdg<ExecutionCurrency> executionCurrencyImdg;
|
||||||
|
private final Imdg<Session> sessionImdg;
|
||||||
|
private final Imdg<SDf05> sDf05Imdg;
|
||||||
|
private final KafkaSender kafkaSender;
|
||||||
|
private final IMessageResolver msgResolver;
|
||||||
|
private final Sdf05Sender sdf05Sender;
|
||||||
|
private final Sdf14Sender sdf14Sender;
|
||||||
|
private SessionType sessionType;
|
||||||
|
private Section section;
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public FinishingSessionAction(ImdgProvider imdgProvider,
|
||||||
|
KafkaSender kafkaSender,
|
||||||
|
IMessageResolver msgResolver,
|
||||||
|
Sdf05Sender sdf05Sender,
|
||||||
|
Sdf14Sender sdf14Sender) {
|
||||||
|
this.imdgProvider = imdgProvider;
|
||||||
|
this.sessionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Session, Session.class);
|
||||||
|
this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
|
||||||
|
this.executionFondImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionFond, ExecutionFond.class);
|
||||||
|
this.executionDepositImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionDeposit, ExecutionDeposit.class);
|
||||||
|
this.executionCurrencyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionCurrency, ExecutionCurrency.class);
|
||||||
|
this.sDf05Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf05, SDf05.class);
|
||||||
|
this.kafkaSender = kafkaSender;
|
||||||
|
this.msgResolver = msgResolver;
|
||||||
|
this.sdf05Sender = sdf05Sender;
|
||||||
|
this.sdf14Sender = sdf14Sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSection(Section section) {
|
||||||
|
this.section = section;
|
||||||
|
}
|
||||||
|
public void setSessionType(SessionType sessionType) {
|
||||||
|
this.sessionType = sessionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void actualExecute(StateContext<TaskType, SsnEvent> ctx) {
|
||||||
|
Long sessionId = ctx.getExtendedState().get(DataEnum.sessionId, Long.class);
|
||||||
|
String pr = (String) ctx.getMessageHeader(ActionHeader.pr);
|
||||||
|
Instant now = Instant.now();
|
||||||
|
//установка CLRD для обработанных регистров
|
||||||
|
Collection<Registry> allLiabilitiesAndOKClaims = selectClaimsAndLiabilities(sessionId);
|
||||||
|
Collection<Registry> claimsAndLiabilities = allLiabilitiesAndOKClaims
|
||||||
|
.stream()
|
||||||
|
.filter(rgs -> RegistryDesignation.T.equalsByKey(rgs.getRegistryDesignation())
|
||||||
|
|| RegistryStatus.OK.equalsByKey(rgs.getRegistryStatus()))
|
||||||
|
.toList();
|
||||||
|
{
|
||||||
|
Map<Long, Registry> rgsToUpdate = new HashMap<>();
|
||||||
|
claimsAndLiabilities.forEach(rgs -> {
|
||||||
|
rgs.setRegistryStatus(RegistryStatus.CLRD.getKey());
|
||||||
|
rgs.setUpdated(now);
|
||||||
|
// registryImdg.update(rgs);
|
||||||
|
rgsToUpdate.put(rgs.getId(), rgs);
|
||||||
|
});
|
||||||
|
registryImdg.putAll(rgsToUpdate, 200);
|
||||||
|
}
|
||||||
|
log.debug("For sessionId={} was updated {} registers for status={}", sessionId, claimsAndLiabilities.size(), RegistryStatus.CLRD.getKey());
|
||||||
|
|
||||||
|
// Отметка статуса в Execution*
|
||||||
|
Session session = sessionImdg.getSingleObjectByID(sessionId);
|
||||||
|
if (session == null) {
|
||||||
|
log.error("Session id={} not found. Can not update Execution's.", sessionId);
|
||||||
|
} else {
|
||||||
|
Collection<Registry> oRegs = findORegistryBySessionId(allLiabilitiesAndOKClaims);
|
||||||
|
Map<Long, RegistryStatus> obligationStatusByGroupId;
|
||||||
|
obligationStatusByGroupId = oRegs.stream()
|
||||||
|
.map(rgs -> new Pair<>(rgs.getGroupId(), getEnumByKey(RegistryStatus.class, rgs.getRegistryStatus())))
|
||||||
|
.filter(pair -> pair.getSecond() != null)
|
||||||
|
.collect(Collectors.toMap(Pair::getFirst, Pair::getSecond, (o1, o2) -> o1));
|
||||||
|
Function<Long, CoverageStatus> statusByExchangeId = id -> {
|
||||||
|
RegistryStatus obligationStatus = obligationStatusByGroupId.get(id);
|
||||||
|
if (obligationStatus == null) return null;
|
||||||
|
return switch (obligationStatus) {
|
||||||
|
case CLRD -> CoverageStatus.ALWD;
|
||||||
|
case FAIL, UNCV, NACK, NACC -> CoverageStatus.DEND;
|
||||||
|
default -> null;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
Set<Long> exchangeExecutionIdsPreviousDay = oRegs.stream()
|
||||||
|
//.filter(rgs -> Objects.nonNull(rgs.getSettlementDate()))
|
||||||
|
.filter(rgs -> Objects.nonNull(rgs.getTradingDate()))
|
||||||
|
.filter(rgs -> rgs.getSettlementDate().isAfter(rgs.getTradingDate()))
|
||||||
|
.map(Registry::getGroupId)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
log.trace("obligations number with second leg in the past: {}", exchangeExecutionIdsPreviousDay.size());
|
||||||
|
int allowed = 0;
|
||||||
|
int notAllowed = 0;
|
||||||
|
SessionType sessionType = getEnumByKey(SessionType.class, session.getSessionType());
|
||||||
|
if (IEnumKey.contains(sessionType, SessionType.FINL, SessionType.MEDM, SessionType.UNIT)) {
|
||||||
|
Map<Long, ExecutionDeposit> depos = new HashMap<>();
|
||||||
|
Collection<ExecutionDeposit> executions = findExecutionDepositBySessionId(sessionId);
|
||||||
|
log.trace("loaded {} ExecutionDeposits for sessionId {}", executions.size(), sessionId);
|
||||||
|
for (ExecutionDeposit execution : executions) {
|
||||||
|
CoverageStatus toStatus = statusByExchangeId.apply(execution.getExchangeExecutionId());
|
||||||
|
if (toStatus == null) {
|
||||||
|
log.trace("CoverageStatus not defined for execution.id={}", execution.getId());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (toStatus == CoverageStatus.DEND) {
|
||||||
|
notAllowed++;
|
||||||
|
}
|
||||||
|
if (toStatus == CoverageStatus.ALWD) {
|
||||||
|
allowed++;
|
||||||
|
}
|
||||||
|
execution.setCoverageStatus(toStatus.getKey());
|
||||||
|
execution.setUpdated(Instant.now());
|
||||||
|
depos.put(execution.getId(), execution);
|
||||||
|
// executionDepositImdg.update(execution);
|
||||||
|
}
|
||||||
|
executionDepositImdg.putAll(depos, 200);
|
||||||
|
log.trace("By sessionId={} processed {} ExecutionDeposit: {} allowed, {} denied, skipped {}",
|
||||||
|
sessionId,
|
||||||
|
executions.size(),
|
||||||
|
allowed,
|
||||||
|
notAllowed,
|
||||||
|
executions.size() - (allowed + notAllowed));
|
||||||
|
}
|
||||||
|
if (IEnumKey.contains(sessionType, SessionType.CURR, SessionType.TRDT, SessionType.IPOB, SessionType.IPO0, SessionType.IPOT, SessionType.UNIT)) {
|
||||||
|
Collection<? extends ExecutionCommon> executions = findExecutionFondBySessionId(sessionId, sessionType);
|
||||||
|
Map<Long, ExecutionCurrency> execCurr = new HashMap<>();
|
||||||
|
Map<Long, ExecutionFond> execFond = new HashMap<>();
|
||||||
|
log.trace("loaded {} Executions for sessionId {}", executions.size(), sessionId);
|
||||||
|
for (ExecutionCommon execution : executions) {
|
||||||
|
CoverageStatus toStatus = statusByExchangeId.apply(execution.getExchangeExecutionId());
|
||||||
|
if (toStatus == null) {
|
||||||
|
log.trace("CoverageStatus not defined for execution.id={}", execution.getId());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (toStatus == CoverageStatus.DEND) {
|
||||||
|
notAllowed++;
|
||||||
|
}
|
||||||
|
if (toStatus == CoverageStatus.ALWD) {
|
||||||
|
allowed++;
|
||||||
|
}
|
||||||
|
execution.setCoverageStatus(toStatus.getKey());
|
||||||
|
execution.setUpdated(Instant.now());
|
||||||
|
if (execution.type().equals(ExecutionType.ExecutionCurrency)) {
|
||||||
|
execCurr.put(execution.getId(), (ExecutionCurrency) execution);
|
||||||
|
//executionCurrencyImdg.update((ExecutionCurrency) execution);
|
||||||
|
} else {
|
||||||
|
execFond.put(execution.getId(), (ExecutionFond) execution);
|
||||||
|
//executionFondImdg.update((ExecutionFond) execution);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
executionCurrencyImdg.putAll(execCurr, 200);
|
||||||
|
executionFondImdg.putAll(execFond, 200);
|
||||||
|
log.trace("By sessionId={} processed {} ExecutionFond: allowed {}, denied {}, skipped {}",
|
||||||
|
sessionId,
|
||||||
|
executions.size(),
|
||||||
|
allowed,
|
||||||
|
notAllowed,
|
||||||
|
executions.size() - (allowed + notAllowed));
|
||||||
|
} else {
|
||||||
|
log.warn("Unsupported session[{}].SessionType={} for update Executions", sessionId, session.getSessionType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Отправка сообщений
|
||||||
|
Collection<Registry> forRegistries = selectRegistry(sessionId);
|
||||||
|
log.debug("Found {} registries for sessionId={}", forRegistries.size(), sessionId);
|
||||||
|
|
||||||
|
Optional<EnumMessage> sResult = toReportSession(sessionId);
|
||||||
|
if (sResult.isPresent()) {
|
||||||
|
String err = msgResolver.resolve(sResult.get());
|
||||||
|
log.error("When sending sessionId={} has error: {}", sessionId, err);
|
||||||
|
throw new RuntimeException(err);
|
||||||
|
}
|
||||||
|
for (Registry registryA : forRegistries) {
|
||||||
|
if (!RegistryDesignation.A.equalsByKey(registryA.getRegistryUnit())) { //fixme Unit -> Designation
|
||||||
|
log.warn("For registry {}.RegistryDesignation is not A.", registryA.getId());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sResult = toReportMoney(sessionId, registryA);
|
||||||
|
if (sResult.isPresent()) {
|
||||||
|
log.warn("When sending sessionId={}, registry.id={} has error: {}", sessionId, registryA.getId(), msgResolver.resolve(sResult.get()));
|
||||||
|
throw new RuntimeException(msgResolver.resolve(sResult.get()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sdf05Sender.sendSdf05(pr);
|
||||||
|
if (Section.FOND.equals(section) || Section.MULT.equals(section)) {
|
||||||
|
sdf14Sender.sendSdf14(sessionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* формирование операционного отчета об обязательствах
|
||||||
|
**/
|
||||||
|
protected Optional<EnumMessage> toReportSession(Long sessionId) {
|
||||||
|
ReportRequestWithSessionId reportSessionRequest = new ReportRequestWithSessionId();
|
||||||
|
reportSessionRequest.setSessionId(sessionId);
|
||||||
|
Long msgKey = kafkaSender.sendRequestToQueue(Consts.CREATE_REPORT_FOR_SESSION_ID, reportSessionRequest);
|
||||||
|
if (msgKey == null) {
|
||||||
|
log.error("failed to put Report Session request to kafka queue");
|
||||||
|
return Optional.of(new EnumMessage(SessionGeneralError));
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* формирование операционного отчета о денежных средствах
|
||||||
|
**/
|
||||||
|
protected Optional<EnumMessage> toReportMoney(Long sessionId, Registry registry) {
|
||||||
|
ReportRequestWithRegistryId reportMoneyRequest = new ReportRequestWithRegistryId();
|
||||||
|
reportMoneyRequest.setSessionId(sessionId);
|
||||||
|
reportMoneyRequest.setRegistryId(registry.getId());
|
||||||
|
Long msgKey = kafkaSender.sendRequestToQueue(Consts.CREATE_REPORT_FOR_REGISTRY, reportMoneyRequest);
|
||||||
|
if (msgKey == null) {
|
||||||
|
log.error("failed to put Report Registry request to kafka queue");
|
||||||
|
return Optional.of(new EnumMessage(SessionGeneralError));
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Collection<Registry> selectRegistry(Long sessionId) {
|
||||||
|
RegistryCodeSqlBuilder registryCodeSqlBuilder = RegistryCodeSqlBuilder.getInstance(
|
||||||
|
new RegistryTradingParams(RegistryDesignation.A, null, null, null)
|
||||||
|
);
|
||||||
|
ImdgPredicateBuilder pb = registryImdg.predicateBuilder();
|
||||||
|
ImdgPredicate condition = registryCodeSqlBuilder.buildPredicate(pb);
|
||||||
|
condition = pb.and(condition, pb.equals("sessionId", sessionId));
|
||||||
|
Collection<Registry> result = registryImdg.getCollectionObjectsByPredicate(condition);
|
||||||
|
log.trace("Selected {} registry's by sql: {}", result.size(), condition);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Collection<Registry> selectClaimsAndLiabilities(Long sessionId) {
|
||||||
|
ImdgPredicateBuilder pb = registryImdg.predicateBuilder();
|
||||||
|
ImdgPredicate prdct = pb.and(
|
||||||
|
pb.equals("sessionId", sessionId),
|
||||||
|
pb.or(
|
||||||
|
pb.and(
|
||||||
|
pb.equals("registryStatus", RegistryStatus.OK.getKey()),
|
||||||
|
pb.equals("registryDesignation", RegistryDesignation.T.getKey())
|
||||||
|
//pb.equals("registryDesignation", RegistryDesignation.C.getKey()),
|
||||||
|
//pb.equals("registryDesignation", RegistryDesignation.L.getKey())
|
||||||
|
),
|
||||||
|
pb.equals("registryDesignation", RegistryDesignation.O.getKey())
|
||||||
|
)
|
||||||
|
);
|
||||||
|
log.debug("searching claims and liabilities by predicate: {}...", prdct);
|
||||||
|
Collection<Registry> result = registryImdg.getCollectionObjectsByPredicate(prdct);
|
||||||
|
log.debug("found {} claims and liabilities", result.size());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Collection<Registry> findORegistryBySessionId(Collection<Registry> rgss) {
|
||||||
|
List<Registry> result = rgss
|
||||||
|
.stream()
|
||||||
|
.filter(rgs -> RegistryDesignation.O.equalsByKey(rgs.getRegistryDesignation()))
|
||||||
|
.filter(registry -> Objects.equals(registry.getSettlementDate(), LocalDate.now()))
|
||||||
|
.filter(registry -> Objects.equals(registry.getValueDate(), registry.getSettlementDate()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
log.debug("{} liabilities", result.size());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Collection<? extends ExecutionCommon> findExecutionFondBySessionId(Long sessionId, SessionType sessionType) {
|
||||||
|
if (sessionType.equals(SessionType.UNIT)) {
|
||||||
|
List<ExecutionCommon> res = new ArrayList<>();
|
||||||
|
res.addAll(findExecutionFondBySessionId(sessionId, executionCurrencyImdg));
|
||||||
|
res.addAll(findExecutionFondBySessionId(sessionId, executionFondImdg));
|
||||||
|
return res;
|
||||||
|
} else {
|
||||||
|
Imdg<? extends ExecutionCommon> excImdg;
|
||||||
|
if (sessionType.equals(SessionType.CURR)) {
|
||||||
|
excImdg = executionCurrencyImdg;
|
||||||
|
} else {
|
||||||
|
excImdg = executionFondImdg;
|
||||||
|
}
|
||||||
|
return findExecutionFondBySessionId(sessionId, excImdg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Collection<? extends ExecutionCommon> findExecutionFondBySessionId(
|
||||||
|
Long sessionId,
|
||||||
|
Imdg<? extends ExecutionCommon> excImdg) {
|
||||||
|
ImdgPredicateBuilder pb = excImdg.predicateBuilder();
|
||||||
|
ImdgPredicate prdct = pb.or(
|
||||||
|
pb.equals("sessionId", sessionId),
|
||||||
|
pb.equals("settlementDate", LocalDate.now())
|
||||||
|
);
|
||||||
|
Collection<? extends ExecutionCommon> result = excImdg.getCollectionObjectsByPredicate(prdct)
|
||||||
|
.stream()
|
||||||
|
.filter(eFond -> Objects.nonNull(eFond.getSessionId()))
|
||||||
|
.filter(eFond -> {
|
||||||
|
if (sessionId.equals(eFond.getSessionId())) return true;
|
||||||
|
Session session = sessionImdg.getSingleObjectByID(eFond.getSessionId());
|
||||||
|
return this.sessionType.equalsByKey(session.getSessionType());
|
||||||
|
})
|
||||||
|
.toList();
|
||||||
|
log.trace("found {} Executions by sessionId={}", result.size(), sessionId);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Collection<ExecutionDeposit> findExecutionDepositBySessionId(Long sessionId) {
|
||||||
|
ImdgPredicateBuilder pb = executionDepositImdg.predicateBuilder();
|
||||||
|
ImdgPredicate prdct = pb.or(
|
||||||
|
pb.equals("sessionId", sessionId),
|
||||||
|
pb.equals("firstLegSettlementDate", LocalDate.now())
|
||||||
|
);
|
||||||
|
Collection<ExecutionDeposit> result = executionDepositImdg.getCollectionObjectsByPredicate(prdct);
|
||||||
|
log.trace("found {} ExecutionDeposit by {}", result.size(), prdct);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package ru.spcex.clearing.session.state.action;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.statemachine.StateContext;
|
||||||
|
import org.springframework.statemachine.action.Action;
|
||||||
|
import ru.spcex.clearing.session.stage.TaskType;
|
||||||
|
import ru.spcex.clearing.session.state.SsnEvent;
|
||||||
|
|
||||||
|
public class SdfReceivedAction implements Action<TaskType, SsnEvent> {
|
||||||
|
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
|
public static final SdfReceivedAction instance = new SdfReceivedAction();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(StateContext<TaskType, SsnEvent> ctx) {
|
||||||
|
log.info("event {} flag saving received", ctx.getEvent().name());
|
||||||
|
ctx.getExtendedState().getVariables().put(ctx.getEvent().name(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package ru.spcex.clearing.session.state.guard;
|
||||||
|
|
||||||
|
import org.springframework.statemachine.StateContext;
|
||||||
|
import org.springframework.statemachine.guard.Guard;
|
||||||
|
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.SsnEvent;
|
||||||
|
|
||||||
|
public class PaymentsWereCreatedGuard implements Guard<TaskType, SsnEvent> {
|
||||||
|
|
||||||
|
public static final PaymentsWereCreatedGuard instance = new PaymentsWereCreatedGuard();
|
||||||
|
|
||||||
|
private PaymentsWereCreatedGuard() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean evaluate(StateContext<TaskType, SsnEvent> ctx) {
|
||||||
|
PaymentInfo pmts = ctx.getExtendedState().get(DataEnum.paymentInfo, PaymentInfo.class);
|
||||||
|
return pmts != null && !pmts.getPaymentInstructions().isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package ru.spcex.clearing.session.state.guard;
|
||||||
|
|
||||||
|
import org.springframework.statemachine.StateContext;
|
||||||
|
import org.springframework.statemachine.guard.Guard;
|
||||||
|
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.SsnEvent;
|
||||||
|
|
||||||
|
public class PaymentsWereNotCreatedGuard implements Guard<TaskType, SsnEvent> {
|
||||||
|
|
||||||
|
public static final PaymentsWereNotCreatedGuard instance = new PaymentsWereNotCreatedGuard();
|
||||||
|
|
||||||
|
private PaymentsWereNotCreatedGuard() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean evaluate(StateContext<TaskType, SsnEvent> ctx) {
|
||||||
|
PaymentInfo pmts = ctx.getExtendedState().get(DataEnum.paymentInfo, PaymentInfo.class);
|
||||||
|
return pmts == null || pmts.getPaymentInstructions().isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
package ru.spcex.clearing.session.state.guard;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
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;
|
||||||
|
import ru.spcex.platform.enumeration.SdfTable;
|
||||||
|
|
||||||
|
public class SdfGuard implements Guard<TaskType, SsnEvent> {
|
||||||
|
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
|
private final Function<StateContext<TaskType, SsnEvent>, Set<SdfTable>> sdfsSetExtractor;
|
||||||
|
|
||||||
|
public SdfGuard(Function<StateContext<TaskType, SsnEvent>, Set<SdfTable>> sdfsSetExtractor) {
|
||||||
|
this.sdfsSetExtractor = sdfsSetExtractor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean evaluate(StateContext<TaskType, SsnEvent> ctx) {
|
||||||
|
ExtendedState state = ctx.getExtendedState();
|
||||||
|
Function<SdfTable, Boolean> was = sdf -> state.get(sdf.getKey(), Object.class) != null;
|
||||||
|
Set<SdfTable> sdfs = sdfsSetExtractor.apply(ctx);
|
||||||
|
boolean everySdfConditionMet = sdfs
|
||||||
|
.stream()
|
||||||
|
.allMatch(was::apply);
|
||||||
|
if (everySdfConditionMet) {
|
||||||
|
log.info("all of {} conditions were met", sdfs);
|
||||||
|
sdfs.forEach(sdf -> state.getVariables().remove(sdf.getKey()));
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
log.info("conditions: {}",
|
||||||
|
sdfs
|
||||||
|
.stream()
|
||||||
|
.map(sdf -> "%s: %s".formatted(sdf.getKey(), was.apply(sdf) ? "received" : "waiting"))
|
||||||
|
.collect(Collectors.joining(";", "[", "]"))
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
package ru.spcex.clearing.session.state.guard;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.statemachine.StateContext;
|
||||||
|
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.SsnEvent;
|
||||||
|
import ru.spcex.platform.enumeration.SdfTable;
|
||||||
|
import ru.spcex.platform.enumeration.Section;
|
||||||
|
|
||||||
|
public class SdfGuardExtractorAfterAssets implements Function<StateContext<TaskType, SsnEvent>, Set<SdfTable>> {
|
||||||
|
|
||||||
|
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
|
public static final SdfGuardExtractorAfterAssets instance = new SdfGuardExtractorAfterAssets();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<SdfTable> apply(StateContext<TaskType, SsnEvent> ctx) {
|
||||||
|
Section section = ctx.getExtendedState().get(DataEnum.section, Section.class);
|
||||||
|
if (section == null) {
|
||||||
|
throw new IllegalStateException("section is null");
|
||||||
|
}
|
||||||
|
PaymentInfo pmts = ctx.getExtendedState().get(DataEnum.paymentInfo, PaymentInfo.class);
|
||||||
|
if (pmts == null || pmts.getPaymentInstructions().isEmpty()) {
|
||||||
|
log.warn("SdfGuard defined, but no DataEnum.paymentInfo present in extended state");
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
switch (section) {
|
||||||
|
case MKR -> {
|
||||||
|
return EnumSet.of(
|
||||||
|
SdfTable.SDF_04,
|
||||||
|
SdfTable.SDF_01,
|
||||||
|
SdfTable.SDF_57
|
||||||
|
);
|
||||||
|
}
|
||||||
|
case FOND, MULT -> {
|
||||||
|
return EnumSet.of(
|
||||||
|
SdfTable.SDF_04,
|
||||||
|
SdfTable.SDF_13,
|
||||||
|
SdfTable.SDF_08,
|
||||||
|
SdfTable.SDF_21,
|
||||||
|
SdfTable.SDF_01,
|
||||||
|
SdfTable.SDF_57
|
||||||
|
);
|
||||||
|
}
|
||||||
|
default -> throw new IllegalStateException("unknown wait conditions for section " + section);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//public static SessionMonitor waitStep7(Section section) {
|
||||||
|
// switch (section) {
|
||||||
|
// case MKR -> {
|
||||||
|
// return SessionMonitor.create()
|
||||||
|
// .addCondition(new SdfCondition(SdfTable.SDF_04))
|
||||||
|
// .addCondition(new SdfCondition(SdfTable.SDF_01))
|
||||||
|
// .addCondition(new SdfCondition(SdfTable.SDF_57));
|
||||||
|
// }
|
||||||
|
// case FOND, MULT -> {
|
||||||
|
// return SessionMonitor.create()
|
||||||
|
// .addCondition(new SdfCondition(SdfTable.SDF_04))
|
||||||
|
// .addCondition(new SdfCondition(SdfTable.SDF_13))
|
||||||
|
// .addCondition(new SdfCondition(SdfTable.SDF_08))
|
||||||
|
// .addCondition(new SdfCondition(SdfTable.SDF_21))
|
||||||
|
// .addCondition(new SdfCondition(SdfTable.SDF_01))
|
||||||
|
// .addCondition(new SdfCondition(SdfTable.SDF_57));
|
||||||
|
// }
|
||||||
|
// default -> throw new IllegalStateException("unknown wait conditions for section " + section);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
@ -64,6 +64,8 @@ public class SessionStatusChangingInterceptor extends StateMachineInterceptorAda
|
||||||
source != null ? source.getId() : "unknown",
|
source != null ? source.getId() : "unknown",
|
||||||
target.getId()
|
target.getId()
|
||||||
));
|
));
|
||||||
|
} else if (target.getId().isPseudoStatus()) {
|
||||||
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
String sessionStatus = target.getId().getKey();
|
String sessionStatus = target.getId().getKey();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
package ru.spcex.clearing.session.state.listener;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.messaging.Message;
|
||||||
|
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
|
||||||
|
import org.springframework.statemachine.state.State;
|
||||||
|
import org.springframework.statemachine.transition.Transition;
|
||||||
|
import ru.spcex.clearing.session.stage.TaskType;
|
||||||
|
import ru.spcex.clearing.session.state.SsnEvent;
|
||||||
|
|
||||||
|
public class MachineMonitoringListener extends StateMachineListenerAdapter<TaskType, SsnEvent> {
|
||||||
|
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
|
private final String machineId;
|
||||||
|
|
||||||
|
public MachineMonitoringListener(String machineId) {
|
||||||
|
this.machineId = machineId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stateEntered(State<TaskType, SsnEvent> state) {
|
||||||
|
TaskType enteredState = state != null ? state.getId() : null;
|
||||||
|
log.info("LISTENER {} stateEntered: {}", machineId, enteredState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transitionStarted(Transition<TaskType, SsnEvent> transition) {
|
||||||
|
TaskType source = transition.getSource() != null ? transition.getSource().getId() : null;
|
||||||
|
TaskType target = transition.getTarget().getId();
|
||||||
|
log.info("LISTENER {} transitionStarted: {} => {}", machineId, source, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void eventNotAccepted(Message<SsnEvent> event) {
|
||||||
|
log.info("LISTENER {} eventNotAccepted: {}", machineId, event.getPayload());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,12 +6,8 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.messaging.Message;
|
|
||||||
import org.springframework.statemachine.StateContext;
|
|
||||||
import org.springframework.statemachine.StateMachine;
|
import org.springframework.statemachine.StateMachine;
|
||||||
import org.springframework.statemachine.config.StateMachineFactory;
|
import org.springframework.statemachine.config.StateMachineFactory;
|
||||||
import org.springframework.statemachine.support.StateMachineInterceptorAdapter;
|
|
||||||
import org.springframework.statemachine.transition.Transition;
|
|
||||||
import ru.spcex.clearing.session.teststate.config.Event;
|
import ru.spcex.clearing.session.teststate.config.Event;
|
||||||
import ru.spcex.clearing.session.teststate.config.State;
|
import ru.spcex.clearing.session.teststate.config.State;
|
||||||
import ru.spcex.clearing.session.teststate.config.TestStateMachineConfig;
|
import ru.spcex.clearing.session.teststate.config.TestStateMachineConfig;
|
||||||
|
|
@ -40,55 +36,63 @@ class StateMachineTest {
|
||||||
@Test
|
@Test
|
||||||
void test() {
|
void test() {
|
||||||
log.debug("test???");
|
log.debug("test???");
|
||||||
stateMachine
|
// stateMachine
|
||||||
.getStateMachineAccessor()
|
// .getStateMachineAccessor()
|
||||||
.doWithRegion(function -> function.addStateMachineInterceptor(
|
// .doWithRegion(function -> function.addStateMachineInterceptor(
|
||||||
new StateMachineInterceptorAdapter<>() {
|
// new StateMachineInterceptorAdapter<>() {
|
||||||
@Override
|
// @Override
|
||||||
public Message<Event> preEvent(Message<Event> message, StateMachine<State, Event> stateMachine) {
|
// public Message<Event> preEvent(Message<Event> message, StateMachine<State, Event> stateMachine) {
|
||||||
Event payload = message.getPayload();
|
// Event payload = message.getPayload();
|
||||||
log.info("INTERCEPTOR preEvent catched event {}", payload);
|
// log.info("INTERCEPTOR preEvent catched event {}", payload);
|
||||||
return super.preEvent(message, stateMachine);
|
// return super.preEvent(message, stateMachine);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public void preStateChange(org.springframework.statemachine.state.State<State, Event> state, Message<Event> message, Transition<State, Event> transition, StateMachine<State, Event> stateMachine, StateMachine<State, Event> rootStateMachine) {
|
// public void preStateChange(org.springframework.statemachine.state.State<State, Event> state, Message<Event> message, Transition<State, Event> transition, StateMachine<State, Event> stateMachine, StateMachine<State, Event> rootStateMachine) {
|
||||||
log.info("INTERCEPTOR preStateChange catched");
|
// log.info("INTERCEPTOR preStateChange catched");
|
||||||
super.preStateChange(state, message, transition, stateMachine, rootStateMachine);
|
// super.preStateChange(state, message, transition, stateMachine, rootStateMachine);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public void postStateChange(org.springframework.statemachine.state.State<State, Event> state, Message<Event> message, Transition<State, Event> transition, StateMachine<State, Event> stateMachine, StateMachine<State, Event> rootStateMachine) {
|
// public void postStateChange(org.springframework.statemachine.state.State<State, Event> state, Message<Event> message, Transition<State, Event> transition, StateMachine<State, Event> stateMachine, StateMachine<State, Event> rootStateMachine) {
|
||||||
log.info("INTERCEPTOR postStateChange catched");
|
// log.info("INTERCEPTOR postStateChange catched");
|
||||||
super.postStateChange(state, message, transition, stateMachine, rootStateMachine);
|
// super.postStateChange(state, message, transition, stateMachine, rootStateMachine);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public StateContext<State, Event> preTransition(StateContext<State, Event> stateContext) {
|
// public StateContext<State, Event> preTransition(StateContext<State, Event> stateContext) {
|
||||||
log.info("INTERCEPTOR preTransition catched");
|
// log.info("INTERCEPTOR preTransition catched");
|
||||||
org.springframework.statemachine.state.State<State, Event> target = stateContext.getTarget();
|
// org.springframework.statemachine.state.State<State, Event> target = stateContext.getTarget();
|
||||||
//if (target.getId().equals(State.continueRevise)) {
|
// //if (target.getId().equals(State.continueRevise)) {
|
||||||
// IllegalStateException ex = new IllegalStateException("pre transition interceptor exception!!!");
|
// // IllegalStateException ex = new IllegalStateException("pre transition interceptor exception!!!");
|
||||||
// stateContext.getStateMachine().setStateMachineError(ex);
|
// // stateContext.getStateMachine().setStateMachineError(ex);
|
||||||
// throw ex;
|
// // throw ex;
|
||||||
//}
|
// //}
|
||||||
return super.preTransition(stateContext);
|
// return super.preTransition(stateContext);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public StateContext<State, Event> postTransition(StateContext<State, Event> stateContext) {
|
// public StateContext<State, Event> postTransition(StateContext<State, Event> stateContext) {
|
||||||
log.info("INTERCEPTOR postTransition catched");
|
// log.info("INTERCEPTOR postTransition catched");
|
||||||
return super.postTransition(stateContext);
|
// return super.postTransition(stateContext);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public Exception stateMachineError(StateMachine<State, Event> stateMachine, Exception exception) {
|
// public Exception stateMachineError(StateMachine<State, Event> stateMachine, Exception exception) {
|
||||||
log.info("INTERCEPTOR error caught!!!");
|
// log.info("INTERCEPTOR error caught!!!");
|
||||||
return exception;
|
// return exception;
|
||||||
}
|
// }
|
||||||
}));
|
// }));
|
||||||
|
|
||||||
stateMachine.sendEvent(Event.startSession);
|
stateMachine.sendEvent(Event.startSession);
|
||||||
|
try {
|
||||||
|
Thread.sleep(5000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
stateMachine.sendEvent(Event.SDF_01);
|
||||||
|
stateMachine.sendEvent(Event.SDF_04);
|
||||||
|
stateMachine.sendEvent(Event.SDF_57);
|
||||||
try {
|
try {
|
||||||
Thread.sleep(10000);
|
Thread.sleep(10000);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
|
|
|
||||||
|
|
@ -2,5 +2,6 @@ package ru.spcex.clearing.session.teststate.config;
|
||||||
|
|
||||||
public enum Event {
|
public enum Event {
|
||||||
startSession, continueRevise,
|
startSession, continueRevise,
|
||||||
|
SDF_04, SDF_01, SDF_57,
|
||||||
triggerInternal
|
triggerInternal
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,5 +5,7 @@ public enum State {
|
||||||
startRevise,
|
startRevise,
|
||||||
continueRevise,
|
continueRevise,
|
||||||
stateWithInternalTransition,
|
stateWithInternalTransition,
|
||||||
stateAfterInternalTransition,
|
stateAutoTransitionAfterInternalAutoTransition,
|
||||||
|
stateWaitingForSdf,
|
||||||
|
stateAfterSdfReceived,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
package ru.spcex.clearing.session.teststate.config;
|
package ru.spcex.clearing.session.teststate.config;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.List;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
@ -8,6 +11,7 @@ import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.core.task.TaskExecutor;
|
import org.springframework.core.task.TaskExecutor;
|
||||||
import org.springframework.messaging.Message;
|
import org.springframework.messaging.Message;
|
||||||
import org.springframework.statemachine.StateMachine;
|
import org.springframework.statemachine.StateMachine;
|
||||||
|
import org.springframework.statemachine.action.Action;
|
||||||
import org.springframework.statemachine.config.EnableStateMachineFactory;
|
import org.springframework.statemachine.config.EnableStateMachineFactory;
|
||||||
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
|
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
|
||||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
|
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
|
||||||
|
|
@ -42,7 +46,9 @@ public class TestStateMachineConfig extends EnumStateMachineConfigurerAdapter<St
|
||||||
.state(State.startRevise)
|
.state(State.startRevise)
|
||||||
.state(State.continueRevise, Event.triggerInternal)
|
.state(State.continueRevise, Event.triggerInternal)
|
||||||
.state(State.stateWithInternalTransition)
|
.state(State.stateWithInternalTransition)
|
||||||
.state(State.stateAfterInternalTransition)
|
.state(State.stateAutoTransitionAfterInternalAutoTransition)
|
||||||
|
.state(State.stateWaitingForSdf)
|
||||||
|
.state(State.stateAfterSdfReceived)
|
||||||
;
|
;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -73,7 +79,7 @@ public class TestStateMachineConfig extends EnumStateMachineConfigurerAdapter<St
|
||||||
.target(State.stateWithInternalTransition)
|
.target(State.stateWithInternalTransition)
|
||||||
.action(context -> {
|
.action(context -> {
|
||||||
log.info("ACTION without an event");
|
log.info("ACTION without an event");
|
||||||
// context.getStateMachine().sendEvent(Event.triggerInternal);
|
// context.getStateMachine().sendEvent(Event.triggerInternal);
|
||||||
})
|
})
|
||||||
.and()
|
.and()
|
||||||
.withInternal()
|
.withInternal()
|
||||||
|
|
@ -88,9 +94,61 @@ public class TestStateMachineConfig extends EnumStateMachineConfigurerAdapter<St
|
||||||
.withExternal()
|
.withExternal()
|
||||||
.source(State.stateWithInternalTransition)
|
.source(State.stateWithInternalTransition)
|
||||||
.timerOnce(1)
|
.timerOnce(1)
|
||||||
.target(State.stateAfterInternalTransition)
|
.target(State.stateAutoTransitionAfterInternalAutoTransition)
|
||||||
.action(ctx -> log.info("ACTION after internal transition"))
|
.action(ctx -> {
|
||||||
;
|
log.info("ACTION after internal transition");
|
||||||
|
List<Object> list = new ArrayList<>();
|
||||||
|
list.add("fasdfasdf");
|
||||||
|
ctx.getExtendedState().getVariables().put("payments", list);
|
||||||
|
})
|
||||||
|
.and()
|
||||||
|
.withExternal()
|
||||||
|
.source(State.stateAutoTransitionAfterInternalAutoTransition)
|
||||||
|
.target(State.stateAfterSdfReceived)
|
||||||
|
.action(ctx -> log.info("ACTION stateAutoTransitionAfterInternalAutoTransition to stateAfterSdfReceived without waiting"))
|
||||||
|
.guard(ctx -> {
|
||||||
|
List list = ctx.getExtendedState().get("payments", List.class);
|
||||||
|
return list != null && list.isEmpty();
|
||||||
|
})
|
||||||
|
.and()
|
||||||
|
.withExternal()
|
||||||
|
.source(State.stateAutoTransitionAfterInternalAutoTransition)
|
||||||
|
.target(State.stateWaitingForSdf)
|
||||||
|
.action(ctx -> log.info("ACTION stateAutoTransitionAfterInternalAutoTransition to stateWaitingForSdf"))
|
||||||
|
.guard(ctx -> {
|
||||||
|
List list = ctx.getExtendedState().get("payments", List.class);
|
||||||
|
return list != null && !list.isEmpty();
|
||||||
|
})
|
||||||
|
.and()
|
||||||
|
.withExternal()
|
||||||
|
.source(State.stateWaitingForSdf)
|
||||||
|
.target(State.stateAfterSdfReceived)
|
||||||
|
.guard(ctx -> {
|
||||||
|
Boolean sdf01Received = ctx.getExtendedState().get(Event.SDF_01.name(), Boolean.class);
|
||||||
|
Boolean sdf04Received = ctx.getExtendedState().get(Event.SDF_04.name(), Boolean.class);
|
||||||
|
Boolean sdf57Received = ctx.getExtendedState().get(Event.SDF_57.name(), Boolean.class);
|
||||||
|
log.info("GUARD received sdfs: sdf01={}, sdf04={}, sdf57={}",
|
||||||
|
sdf01Received, sdf04Received, sdf57Received);
|
||||||
|
return Boolean.TRUE.equals(sdf01Received)
|
||||||
|
&& Boolean.TRUE.equals(sdf04Received)
|
||||||
|
&& Boolean.TRUE.equals(sdf57Received);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var event : EnumSet.of(Event.SDF_01, Event.SDF_04, Event.SDF_57)) {
|
||||||
|
transitions
|
||||||
|
.withInternal()
|
||||||
|
.source(State.stateWaitingForSdf)
|
||||||
|
.event(event)
|
||||||
|
.action(eventReceivedAction());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Action<State, Event> eventReceivedAction() {
|
||||||
|
return ctx -> {
|
||||||
|
log.info("event {} flag saving received", ctx.getEvent().name());
|
||||||
|
ctx.getExtendedState().getVariables().put(ctx.getEvent().name(), true);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue