ialbert 2026-03-12 16:35:47 +03:00
parent 2ef1e04430
commit ecdf62ac13
8 changed files with 521 additions and 10 deletions

View file

@ -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);
}
}

View file

@ -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 {

View file

@ -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;
}
}

View file

@ -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(

View file

@ -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();
}

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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) {