This commit is contained in:
parent
2ef1e04430
commit
ecdf62ac13
8 changed files with 521 additions and 10 deletions
|
|
@ -0,0 +1,242 @@
|
|||
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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.statemachine.action.Action;
|
||||
import org.springframework.statemachine.config.EnableStateMachineFactory;
|
||||
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
|
||||
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
|
||||
import ru.clearing.classes.statics.data.execution.ExecutionCurrency;
|
||||
import ru.clearing.classes.statics.data.misc.Session;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.session.stage.TaskType;
|
||||
import ru.spcex.clearing.session.state.DataEnum;
|
||||
import ru.spcex.clearing.session.state.SsnEvent;
|
||||
import ru.spcex.clearing.session.state.action.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.InspectionObligationsPrecAction;
|
||||
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.chain;
|
||||
import static ru.spcex.clearing.util.StateMachineUtil.invert;
|
||||
import ru.spcex.platform.classes.base.interfaces.ExecutionType;
|
||||
import ru.spcex.platform.enumeration.Section;
|
||||
import ru.spcex.platform.enumeration.SessionType;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
|
||||
|
||||
@Configuration("precSessionStateMachineConfig")
|
||||
@EnableStateMachineFactory(name = "PREC")
|
||||
public class PrecSessionStateMachineConfig extends EnumStateMachineConfigurerAdapter<TaskType, SsnEvent> {
|
||||
private final static Logger log = LoggerFactory.getLogger(PrecSessionStateMachineConfig.class);
|
||||
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 InspectionObligationsPrecAction inspectionObligationsV2Action;
|
||||
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 SessionType SESSION_TYPE = SessionType.PREC;
|
||||
private final Section SECTION = Section.CURR;
|
||||
private static final Action<TaskType, SsnEvent> finishAction = context ->
|
||||
log.info("changing state to CL10; interceptor should update session status automatically.");
|
||||
|
||||
public PrecSessionStateMachineConfig(ImdgProvider imdgProvider,
|
||||
ReviseStage1Action reviseStage1Action,
|
||||
DealsPrepareAction dealsPrepare,
|
||||
@Qualifier("requirementAndObligationCreationAction")
|
||||
RequirementAndObligationCreationAction reqAndOblAction,
|
||||
ObligationAdmissionAction obligationsAdmission,
|
||||
InclusionToPoolAction inclusionToPoolAction,
|
||||
InspectionObligationsPrecAction 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.obligationAdmissionContinueAction = obligationAdmissionContinueAction;
|
||||
|
||||
dealsPrepareAction.searchForExecutions(ExecutionType.ExecutionCurrency);
|
||||
ImdgPredicateBuilder execFondPb = executionCurrencyImdg.predicateBuilder();
|
||||
dealsPrepareAction.addExecutionCurrencyCondition(execFondPb.in("market", marketCodes.get().toArray(new String[0])));
|
||||
this.obligationAdmissionContinueAction.setDataEnum(DataEnum.obligationAdmissionStashedRgs);
|
||||
}
|
||||
|
||||
@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.FinishingSession,
|
||||
TaskType.PSEUDO_waitAfterObligationAdmissionError,
|
||||
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);
|
||||
|
||||
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.FinishingSession)
|
||||
.guard(invert(inspErrGuard))
|
||||
.action(saveRegistriesAfterInspectionAndContinueAction)
|
||||
.action(finishAction);
|
||||
}
|
||||
|
||||
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.FinishingSession)
|
||||
.action(activeWsAction)
|
||||
.action(saveRegistriesAfterInspectionAndContinueAction)
|
||||
.action(finishAction)
|
||||
.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);
|
||||
}
|
||||
}
|
||||
|
|
@ -165,7 +165,7 @@ public class InclusionToPoolAction extends AbstractSessionActionForOkErrorHandli
|
|||
switch (ssnTpe) {
|
||||
case MEDM, FINL, XDEP -> execImdg = (Imdg<T>) executionDepositImdg;
|
||||
case IPO0, IPOB, TRDT, IPOT -> execImdg = (Imdg<T>) executionFondImdg;
|
||||
case CURR, PAYM, RSLT -> execImdg = (Imdg<T>) executionCurrImdg;
|
||||
case CURR, PAYM, RSLT, PREC -> execImdg = (Imdg<T>) executionCurrImdg;
|
||||
default -> {
|
||||
//кейс для "общих" сессий (напр. UNIT) в которых сочетаются разные сделки
|
||||
//смотрим на секцию регистра.
|
||||
|
|
@ -206,14 +206,11 @@ public class InclusionToPoolAction extends AbstractSessionActionForOkErrorHandli
|
|||
rgsPb.equals("sessionType", SessionType.XDEP.getKey()),
|
||||
rgsPb.equals("sessionType", SessionType.UNIT.getKey())
|
||||
);
|
||||
} else if (SessionType.PAYM.equals(sessionType)) {
|
||||
return rgsPb.or(
|
||||
rgsPb.equals("sessionType", SessionType.PREP.getKey()),
|
||||
rgsPb.equals("sessionType", SessionType.PAYM.getKey())
|
||||
);
|
||||
} else if (SessionType.RSLT.equals(sessionType)) {
|
||||
} else if (IEnumKey.contains(sessionType, SessionType.PAYM, SessionType.RSLT, SessionType.PREC)) {
|
||||
return rgsPb.or(
|
||||
rgsPb.equals("sessionType", SessionType.PREP.getKey()),
|
||||
rgsPb.equals("sessionType", SessionType.PREC.getKey()),
|
||||
rgsPb.equals("sessionType", SessionType.PAYM.getKey()),
|
||||
rgsPb.equals("sessionType", SessionType.RSLT.getKey())
|
||||
);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,244 @@
|
|||
package ru.spcex.clearing.session.state.action;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
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.registry.Registry;
|
||||
import ru.spcex.clearing.component.GroupRgsKey;
|
||||
import ru.spcex.clearing.component.predicate.cash.registry.AssetByTcrCompanyAccountCashedPredicate;
|
||||
import ru.spcex.clearing.error.RgsError;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.service.cash.impl.RegistryCashAssetCash;
|
||||
import ru.spcex.clearing.service.registry.RegistryManager;
|
||||
import ru.spcex.clearing.session.stage.TaskType;
|
||||
import ru.spcex.clearing.session.stage.util.RegistryUtil;
|
||||
import ru.spcex.clearing.session.state.DataEnum;
|
||||
import ru.spcex.clearing.session.state.SsnEvent;
|
||||
import ru.spcex.clearing.session.state.model.RgsErr;
|
||||
import static ru.spcex.clearing.util.ClearingUtil.paramsFromRegistry;
|
||||
import ru.spcex.platform.enumeration.RegistryDesignation;
|
||||
import ru.spcex.platform.enumeration.RegistryStatus;
|
||||
import ru.spcex.platform.enumeration.RegistryTradingParams;
|
||||
import static ru.spcex.platform.enumeration.RegistryTradingParams.*;
|
||||
import ru.spcex.platform.enumeration.SessionType;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgId;
|
||||
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 static ru.spcex.platform.utils.enumeration.IEnumKey.getEnumByKey;
|
||||
import ru.spcex.platform.utils.enumeration.IMessageResolver;
|
||||
import ru.spcex.platform.utils.enumeration.SimpleMessageResolver;
|
||||
import ru.spcex.platform.utils.number.BigDecimalUtil;
|
||||
import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD;
|
||||
|
||||
@Service
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
public class InspectionObligationsPrecAction extends ReviseStage1Action {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
private final Imdg<Registry> registryImdg;
|
||||
private final ImdgId idGen;
|
||||
private final IMessageResolver msgResolver = new SimpleMessageResolver();
|
||||
private SessionType sessionType;
|
||||
private Long sessionId;
|
||||
|
||||
@Autowired
|
||||
public InspectionObligationsPrecAction(ImdgProvider imdgProvider) {
|
||||
super(imdgProvider);
|
||||
this.registryImdg = imdgProvider.getCashingImdg(IMDGDistributedNames.Map_Registry, Registry.class, null);
|
||||
this.idGen = imdgProvider.getImdgIdGenerator();
|
||||
}
|
||||
|
||||
private final RegistryCashAssetCash a___Cash = new RegistryCashAssetCash("[all assets]");
|
||||
|
||||
@Override
|
||||
public void actualExecute(StateContext<TaskType, SsnEvent> ctx) {
|
||||
try {
|
||||
super.actualExecute(ctx);
|
||||
this.sessionId = ctx.getExtendedState().get(DataEnum.sessionId, Long.class);
|
||||
this.sessionType = ctx.getExtendedState().get(DataEnum.sessionType, SessionType.class);
|
||||
inspectionObligations(ctx);
|
||||
} finally {
|
||||
a___Cash.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private static final Comparator<Map.Entry<GroupRgsKey, List<Registry>>> groupComparatorByMinId =
|
||||
(entry1, entry2) -> {
|
||||
long minId1 = entry1.getValue().stream()
|
||||
.mapToLong(Registry::getId)
|
||||
.min()
|
||||
.orElse(Long.MIN_VALUE);
|
||||
|
||||
long minId2 = entry2.getValue().stream()
|
||||
.mapToLong(Registry::getId)
|
||||
.min()
|
||||
.orElse(Long.MIN_VALUE);
|
||||
|
||||
return Long.compare(minId1, minId2);
|
||||
};
|
||||
|
||||
private BigDecimal changeBalance(Registry asset, BigDecimal amount, Instant now) {
|
||||
asset.setBalance(BigDecimal.ZERO);
|
||||
asset.setUpdated(now);
|
||||
return BigDecimalUtil.safeSumBD(asset.getBalance(), amount);
|
||||
}
|
||||
|
||||
private void inspectionObligations(StateContext<TaskType, SsnEvent> ctx) {
|
||||
Instant now = Instant.now();
|
||||
String sqlCondition = String.format("(%s) and registryStatus = '%s'",
|
||||
RegistryCodeSqlBuilder.getInstance(OS_T, OM_T, TS_T, TM_T).build(),
|
||||
RegistryStatus.POOL.getKey());
|
||||
|
||||
Collection<Registry> registriesToProcess = registryImdg.getCollectionObjectsBySQL(sqlCondition);
|
||||
List<RgsErr> errs = new ArrayList<>();
|
||||
Map<Long, Registry> rgssToStore = new HashMap<>(registriesToProcess.size()); //вторые ноги у сделок - нужна ли оптимизация?
|
||||
List<Map.Entry<GroupRgsKey, List<Registry>>> registriesByGroupSorted = registriesToProcess.stream()
|
||||
.collect(Collectors.groupingBy(
|
||||
registry -> new GroupRgsKey(registry.getGroupId(), registry.getMarket())))
|
||||
.entrySet()
|
||||
.stream()
|
||||
.sorted(groupComparatorByMinId)
|
||||
.toList();
|
||||
|
||||
log.info("found {} ({} groups) registries by sql: {}", registriesToProcess.size(), registriesByGroupSorted.size(), sqlCondition);
|
||||
ImdgPredicateBuilder rgsPb = registryImdg.predicateBuilder();
|
||||
Consumer<List<Registry>> setGroupStatus = (group) -> group
|
||||
.forEach(registry -> {
|
||||
registry.setRegistryStatus(RegistryStatus.OK.getKey());
|
||||
registry.setUpdated(now);
|
||||
registry.setSessionId(sessionId);
|
||||
registry.setSessionType(sessionType.getKey());
|
||||
rgssToStore.put(registry.getId(), registry);
|
||||
});
|
||||
Consumer<List<Registry>> setGroupStatusError = group -> group
|
||||
.forEach(registry -> {
|
||||
String err = msgResolver.resolve(RgsError.A__tNotFound);
|
||||
registry.setComment(err);
|
||||
registry.setRegistryStatus(RegistryStatus.FAIL.getKey());
|
||||
registry.setUpdated(now);
|
||||
registry.setSessionId(sessionId);
|
||||
registry.setSessionType(sessionType.getKey());
|
||||
rgssToStore.put(registry.getId(), registry);
|
||||
errs.add(new RgsErr(registry, err));
|
||||
});
|
||||
|
||||
for (Map.Entry<GroupRgsKey, List<Registry>> entry : registriesByGroupSorted) {
|
||||
List<Registry> group = entry.getValue();
|
||||
for (Registry rgs : group) {
|
||||
RegistryTradingParams rgsParams = paramsFromRegistry(rgs);
|
||||
if (!OM_T.equalByParams(rgsParams) && !TM_T.equalByParams(rgsParams)) {
|
||||
log.debug("rgs.id={} code={} is not {}/{} - skipping AM*B change",
|
||||
rgs.getId(), rgs.getRegistryCode(), OM_T, TM_T);
|
||||
continue;
|
||||
}
|
||||
ImdgPredicate am_bPrdct = AssetByTcrCompanyAccountCashedPredicate
|
||||
.getPredicate(rgs, AM_B)
|
||||
.cashed(rgsPb, a___Cash);
|
||||
ImdgPredicate am_tPrdct = AssetByTcrCompanyAccountCashedPredicate
|
||||
.getPredicate(rgs, AM_T)
|
||||
.cashed(rgsPb, a___Cash);
|
||||
ImdgPredicate dm_tPrdct = AssetByTcrCompanyAccountCashedPredicate
|
||||
.getPredicate(rgs, DM_T)
|
||||
.cashed(rgsPb, a___Cash);
|
||||
Registry am_t = registryImdg.getFirstObjectByPredicate(am_tPrdct);
|
||||
if (am_t == null) {
|
||||
log.debug("groupId {}, {}.id={} - A**T not found. settings FAIL to group",
|
||||
entry.getKey(), rgs.getRegistryCode(), rgs.getId());
|
||||
setGroupStatusError.accept(group);
|
||||
continue;
|
||||
}
|
||||
Registry am_b = Optional.ofNullable(
|
||||
registryImdg.getFirstObjectByPredicate(am_bPrdct)
|
||||
).orElseGet(() -> copyRgs(am_t, now, RegistryTradingParams.A__B));
|
||||
BigDecimal am_bOldBalance = am_b.getBalance();
|
||||
|
||||
RegistryDesignation designation = getEnumByKey(RegistryDesignation.class, rgs.getRegistryDesignation());
|
||||
BigDecimal am_bDelta;
|
||||
if (designation.equals(RegistryDesignation.O)) {
|
||||
am_bDelta = changeBalance(am_b, rgs.getBalance(), now);
|
||||
} else {
|
||||
am_bDelta = changeBalance(am_b, safeBD(rgs.getBalance()).negate(), now);
|
||||
}
|
||||
rgssToStore.put(am_b.getId(), am_b);
|
||||
|
||||
Registry dm_t = registryImdg.getFirstObjectByPredicate(dm_tPrdct);
|
||||
BigDecimal dm_tBalance = dm_t != null ? safeBD(dm_t.getBalance()) : BigDecimal.ZERO;
|
||||
|
||||
BigDecimal difference = am_t.getBalance()
|
||||
.subtract(am_bDelta)
|
||||
.subtract(dm_tBalance);
|
||||
logChanges(entry, am_b, am_t, dm_t, rgs, am_bOldBalance, am_bDelta, difference);
|
||||
|
||||
if (difference.compareTo(BigDecimal.ZERO) < 0) {
|
||||
Registry pm_t = copyRgs(am_t, now, RegistryTradingParams.P___);
|
||||
pm_t.setSessionId(sessionId);
|
||||
pm_t.setSessionType(sessionType.getKey());
|
||||
pm_t.setBalance(difference);
|
||||
rgssToStore.put(pm_t.getId(), pm_t);
|
||||
}
|
||||
}
|
||||
setGroupStatus.accept(group);
|
||||
}
|
||||
ctx.getExtendedState().getVariables().put(DataEnum.erroneousRegistries, errs);
|
||||
ctx.getExtendedState().getVariables().put(DataEnum.inspectionObligationStashedRgs, rgssToStore);
|
||||
}
|
||||
|
||||
private void logChanges(Map.Entry<GroupRgsKey, List<Registry>> entry,
|
||||
Registry am_b, Registry am_t, Registry dm_t,
|
||||
Registry rgs,
|
||||
BigDecimal am_bOldBalance,
|
||||
BigDecimal am_bDelta,
|
||||
BigDecimal difference) {
|
||||
log.debug("group id={}; {}.id={} found by {}.id={}: balance " +
|
||||
"was changed from {} to {}; balance diff {}[{}] - {}[{}]* - {}[{}] = {}",
|
||||
entry.getKey().groupId(),
|
||||
am_b.getRegistryCode(),
|
||||
am_b.getId(),
|
||||
rgs.getRegistryCode(),
|
||||
rgs.getId(),
|
||||
am_bOldBalance,
|
||||
am_b.getBalance(),
|
||||
am_t.getRegistryCode(),
|
||||
am_t.getId(),
|
||||
am_b.getRegistryCode(),
|
||||
am_b.getId(),
|
||||
DM_T,
|
||||
dm_t != null ? dm_t.getId() : null,
|
||||
difference
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
private Registry copyRgs(Registry rgs, Instant now, RegistryTradingParams params) {
|
||||
Registry pm_t = rgs.clone();
|
||||
RegistryManager.zeroState(pm_t);
|
||||
if (params.registryDesignation() != null) {
|
||||
pm_t.setRegistryDesignation(params.registryDesignation().getKey());
|
||||
}
|
||||
if (params.registryUnit() != null) {
|
||||
pm_t.setRegistryUnit(params.registryUnit().getKey());
|
||||
}
|
||||
pm_t.setRegistryCode(RegistryUtil.clearingCode(pm_t));
|
||||
pm_t.setId(idGen.nextId());
|
||||
pm_t.setCreated(now);
|
||||
log.debug("created {}.id={} by {}.id={}", pm_t.getRegistryCode(), pm_t.getId(), rgs.getRegistryCode(), rgs.getId());
|
||||
return pm_t;
|
||||
}
|
||||
}
|
||||
|
|
@ -243,7 +243,7 @@ public class RequirementAndObligationCreationAction extends AbstractSessionActio
|
|||
}
|
||||
|
||||
private boolean isCk() {
|
||||
return IEnumKey.contains(sessionType, SessionType.PREP, SessionType.PAYM, SessionType.RSLT);
|
||||
return IEnumKey.contains(sessionType, SessionType.PREP, SessionType.PAYM, SessionType.RSLT, SessionType.PREC);
|
||||
}
|
||||
|
||||
private void createRegistryForCK(
|
||||
|
|
|
|||
|
|
@ -6,6 +6,12 @@ import java.util.Map;
|
|||
import java.util.function.Function;
|
||||
import ru.clearing.classes.statics.data.execution.ExecutionCommon;
|
||||
import ru.clearing.classes.statics.data.registry.Registry;
|
||||
import ru.spcex.platform.enumeration.RegistryCapacity;
|
||||
import ru.spcex.platform.enumeration.RegistryDesignation;
|
||||
import ru.spcex.platform.enumeration.RegistryInstrumentType;
|
||||
import ru.spcex.platform.enumeration.RegistryTradingParams;
|
||||
import ru.spcex.platform.enumeration.RegistryUnit;
|
||||
import static ru.spcex.platform.utils.enumeration.IEnumKey.getEnumByKey;
|
||||
import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD;
|
||||
|
||||
public class ClearingUtil {
|
||||
|
|
@ -25,6 +31,14 @@ public class ClearingUtil {
|
|||
// }
|
||||
}
|
||||
|
||||
public static RegistryTradingParams paramsFromRegistry(Registry rgs) {
|
||||
RegistryDesignation dsgn = getEnumByKey(RegistryDesignation.class, rgs.getRegistryDesignation());
|
||||
RegistryInstrumentType inst = getEnumByKey(RegistryInstrumentType.class, rgs.getRegistryInstrumentType());
|
||||
RegistryCapacity cpct = getEnumByKey(RegistryCapacity.class, rgs.getRegistryCapacity());
|
||||
RegistryUnit unit = getEnumByKey(RegistryUnit.class, rgs.getRegistryUnit());
|
||||
return new RegistryTradingParams(dsgn, inst, cpct, unit);
|
||||
}
|
||||
|
||||
public static String biErr(Registry rgs) {
|
||||
return "Недостаточно средств по инструменту " + rgs.getSecuritySymbol();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ public enum RegistryDesignation implements IEnumKey {
|
|||
T("T"),
|
||||
D("D"),
|
||||
L("L"),
|
||||
C("C")
|
||||
C("C"),
|
||||
P("P"),
|
||||
;
|
||||
|
||||
private final String key;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,14 @@ public record RegistryTradingParams(RegistryDesignation registryDesignation,
|
|||
return isEqualDesignation && isEqualInstrumentType && isEqualCapacity && isEqualUnit;
|
||||
}
|
||||
|
||||
public boolean equalByParams(RegistryTradingParams other) {
|
||||
boolean isEqualDesignation = this.registryDesignation == null || other.registryDesignation == this.registryDesignation;
|
||||
boolean isEqualInstrumentType = this.registryInstrumentType == null || other.registryInstrumentType == this.registryInstrumentType;
|
||||
boolean isEqualCapacity = this.registryCapacity == null || other.registryCapacity == this.registryCapacity;
|
||||
boolean isEqualUnit = this.registryUnit == null || other.registryUnit == this.registryUnit;
|
||||
return isEqualDesignation && isEqualInstrumentType && isEqualCapacity && isEqualUnit;
|
||||
}
|
||||
|
||||
public static RegistryTradingParams of(String dsgn, String insType, String cap, String unit) {
|
||||
return new RegistryTradingParams(
|
||||
IEnumKey.getEnumByKey(RegistryDesignation.class, dsgn),
|
||||
|
|
@ -123,6 +131,7 @@ public record RegistryTradingParams(RegistryDesignation registryDesignation,
|
|||
public final static RegistryTradingParams D__V;
|
||||
public final static RegistryTradingParams _S_T;
|
||||
public final static RegistryTradingParams AMAT;
|
||||
public final static RegistryTradingParams P___;
|
||||
|
||||
static {
|
||||
OS_T = new RegistryTradingParams(RegistryDesignation.O,
|
||||
|
|
@ -274,6 +283,10 @@ public record RegistryTradingParams(RegistryDesignation registryDesignation,
|
|||
RegistryInstrumentType.M,
|
||||
RegistryCapacity.A,
|
||||
RegistryUnit.T);
|
||||
P___ = new RegistryTradingParams(RegistryDesignation.P,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ public enum SessionType implements IEnumKey {
|
|||
IPOB("IPOB"), IPO0("IPO0"), IPOT("IPOT"), TRDT("TRDT"),
|
||||
MEDM("MEDM"), FINL("FINL"), XDEP("XDEP"), LIQU("LIQU"),
|
||||
CURR("CURR"), UNIT("UNIT"),
|
||||
PREP("PREP"), PAYM("PAYM"), RSLT("RSLT"),
|
||||
PREP("PREP"), PREC("PREC"), PAYM("PAYM"), RSLT("RSLT"),
|
||||
;
|
||||
|
||||
SessionType(String key) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue