diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/state_machine_2/specific/PrecSessionStateMachineConfig.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/state_machine_2/specific/PrecSessionStateMachineConfig.java new file mode 100644 index 000000000..7912a5a04 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/state_machine_2/specific/PrecSessionStateMachineConfig.java @@ -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 { + private final static Logger log = LoggerFactory.getLogger(PrecSessionStateMachineConfig.class); + private final Imdg 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 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> 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 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 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 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 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 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 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 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 config) throws Exception { + StateMachineListenerAdapter loggingChangeStateListener + = new MachineMonitoringListener(SESSION_TYPE.getKey()); + config + .withConfiguration() + .machineId(SESSION_TYPE.getKey()) + .listener(loggingChangeStateListener); + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/action/InclusionToPoolAction.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/action/InclusionToPoolAction.java index ae652a6df..9b0a55818 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/action/InclusionToPoolAction.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/action/InclusionToPoolAction.java @@ -165,7 +165,7 @@ public class InclusionToPoolAction extends AbstractSessionActionForOkErrorHandli switch (ssnTpe) { case MEDM, FINL, XDEP -> execImdg = (Imdg) executionDepositImdg; case IPO0, IPOB, TRDT, IPOT -> execImdg = (Imdg) executionFondImdg; - case CURR, PAYM, RSLT -> execImdg = (Imdg) executionCurrImdg; + case CURR, PAYM, RSLT, PREC -> execImdg = (Imdg) 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 { diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/action/InspectionObligationsPrecAction.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/action/InspectionObligationsPrecAction.java new file mode 100644 index 000000000..c96b723c2 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/action/InspectionObligationsPrecAction.java @@ -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 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 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>> 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 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 registriesToProcess = registryImdg.getCollectionObjectsBySQL(sqlCondition); + List errs = new ArrayList<>(); + Map rgssToStore = new HashMap<>(registriesToProcess.size()); //вторые ноги у сделок - нужна ли оптимизация? + List>> 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> 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> 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> entry : registriesByGroupSorted) { + List 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> 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; + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/action/RequirementAndObligationCreationAction.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/action/RequirementAndObligationCreationAction.java index b8cbe2bd2..9be38801b 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/action/RequirementAndObligationCreationAction.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/state/action/RequirementAndObligationCreationAction.java @@ -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( diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/util/ClearingUtil.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/util/ClearingUtil.java index c04d428a4..85874fdf3 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/util/ClearingUtil.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/util/ClearingUtil.java @@ -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(); } diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/RegistryDesignation.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/RegistryDesignation.java index fbef0e535..1e730de59 100644 --- a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/RegistryDesignation.java +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/RegistryDesignation.java @@ -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; diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/RegistryTradingParams.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/RegistryTradingParams.java index 5cd67d4d8..477bf94e9 100644 --- a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/RegistryTradingParams.java +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/RegistryTradingParams.java @@ -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); } } diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/SessionType.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/SessionType.java index b99d1ea47..097309fd7 100644 --- a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/SessionType.java +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/SessionType.java @@ -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) {