From e40a8dc724817a8ed4254310e48998ac8b3985f6 Mon Sep 17 00:00:00 2001 From: ialbert Date: Mon, 25 Sep 2023 17:43:43 +0300 Subject: [PATCH 1/4] =?UTF-8?q?1.=20planBalance=20=D0=BF=D1=80=D0=BE=D1=81?= =?UTF-8?q?=D1=82=D0=B0=D0=B2=D0=BB=D1=8F=D0=B5=D1=82=D1=81=D1=8F=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=205=20=D1=88=D0=B0=D0=B3=D0=B0=20=D0=B2=D0=BE?= =?UTF-8?q?=D0=B7=D0=B2=D1=80=D0=B0=D1=82=D0=B0=20=D0=B4=D0=B5=D0=BF=D0=BE?= =?UTF-8?q?=D0=B7=D0=B8=D1=82=D0=BE=D0=B2=202.=20=D0=BF=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=D0=B5=D1=80=D0=BA=D0=B8,=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5(=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5)=20dm=5Fx=20->=20dm=5Fx/dm=5Ft?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../clearing/config/ValidationConfig.java | 5 +- .../spcex/clearing/error/ClearingError.java | 1 + .../clearing/service/RegistryService.java | 46 +++++----- .../ReturnDepositValidationRule.java | 86 ++++++++++++++++--- .../service/validation/ValidationStored.java | 2 +- .../session/stage/ReturnDepositSession.java | 1 + .../stage/impl/InspectionObligations.java | 49 +---------- .../InspectionObligationsDepositReturn.java | 11 ++- .../session/stage/impl/PlanBalanceCalc.java | 73 ++++++++++++++++ 9 files changed, 191 insertions(+), 83 deletions(-) create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/PlanBalanceCalc.java diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java index 1c33fe8fa..d152890b4 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java @@ -329,9 +329,10 @@ public class ValidationConfig { context.setLogPrefix(LogPrefixId.INSTANCE); return new ValidatorImpl<>(context, new PresentById(IMDGDistributedNames.Map_Registry, ClearingError.RecordNotFound, true), - ReturnDepositValidationRule.RegistryCodeCheck, + ReturnDepositValidationRule.RgsWronCodeCheck, + ReturnDepositValidationRule.CategoryCheck, ReturnDepositValidationRule.BalanceCheck, - ReturnDepositValidationRule.DmxCheck + ReturnDepositValidationRule.Dm_Check ); }; } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingError.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingError.java index b3ca256ca..21fabb227 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingError.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/error/ClearingError.java @@ -23,6 +23,7 @@ public enum ClearingError implements IErrorEnumId { SuchRecordAlreadyExists(5405L), TradingClearingRegistryNotFound(5418L), TradingClearingRegistryNotActive(5419L), + CategoryNotFound(5420L), ClearingUnavailableForCompany(5421L), InsecurityObligation(5422L), NewDealsNotFound(5423L), diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java index 5b7d00041..6bcbedd89 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java @@ -166,28 +166,34 @@ public class RegistryService { msgResolver.resolve(err.get())); return new RequestInfoUpdate(req.getId(), Status.Error, msgResolver.resolve(err.get())); } - Registry tm_t = validator.getStored(Stored.PresentById); - Registry dm_x = validator.getStored(ValidationStored.ReturnDepositDmx); - if (dm_x != null) { - dm_x.setSessionId(null); - dm_x.setSessionType(null); - dm_x.setBalance(requestPayload.getBalance()); - dm_x.setUpdated(Instant.now()); - registryImdg.update(dm_x); - log.debug("updated dm*x.id={} by RegistryReturnDepositRequest.id={}", - dm_x.getId(), + Registry _m_t = validator.getStored(Stored.PresentById); + Registry dm__ = validator.getStored(ValidationStored.ReturnDepositDm__); + if (dm__ != null) { + dm__.setSessionId(null); + dm__.setSessionType(null); + dm__.setBalance(requestPayload.getBalance()); + dm__.setUpdated(Instant.now()); + registryImdg.update(dm__); + log.debug("updated {}.id={} by RegistryReturnDepositRequest.id={}", + dm__.getRegistryCode(), + dm__.getId(), req.getId()); } else { - dm_x = tm_t.clone(); - dm_x.setRegistryDesignation(RegistryDesignation.D.getKey()); - dm_x.setRegistryUnit(RegistryUnit.X.getKey()); - dm_x.setRegistryCode(RegistryUtil.clearingCode(dm_x)); - dm_x.setBalance(requestPayload.getBalance()); - dm_x.setSessionId(null); - dm_x.setSessionType(null); - registryImdg.insert(dm_x); - log.debug("created dm*x.id={} by RegistryReturnDepositRequest.id={}", - dm_x.getId(), + dm__ = _m_t.clone(); + dm__.setRegistryDesignation(RegistryDesignation.D.getKey()); + if (RegistryDesignation.T.equalsByKey(_m_t.getRegistryDesignation())) { + dm__.setRegistryUnit(RegistryUnit.X.getKey()); + } else { + dm__.setRegistryUnit(RegistryUnit.T.getKey()); + } + dm__.setRegistryCode(RegistryUtil.clearingCode(dm__)); + dm__.setBalance(requestPayload.getBalance()); + dm__.setSessionId(null); + dm__.setSessionType(null); + registryImdg.insert(dm__); + log.debug("created {}.id={} by RegistryReturnDepositRequest.id={}", + dm__.getRegistryCode(), + dm__.getId(), req.getId()); } return new RequestInfoUpdate(req.getId(), Status.Success, null); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ReturnDepositValidationRule.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ReturnDepositValidationRule.java index 31b1c6a28..421b59e1f 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ReturnDepositValidationRule.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ReturnDepositValidationRule.java @@ -1,23 +1,68 @@ package ru.spcex.clearing.service.validation; +import ru.clearing.classes.statics.data.company.ClearingMemberCategory; import ru.clearing.classes.statics.data.registry.Registry; import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryReturnDepositRequest; -import ru.spcex.clearing.service.registry.RegistryManager; -import ru.spcex.platform.enumeration.RegistryDesignation; -import ru.spcex.platform.enumeration.RegistryInstrumentType; -import ru.spcex.platform.enumeration.RegistryStatus; -import ru.spcex.platform.enumeration.RegistryUnit; +import ru.spcex.platform.enumeration.*; import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.predicate.specific.RegistryCodeSqlBuilder; import ru.spcex.platform.imdg.validation.ImdgValidationContext; import ru.spcex.platform.imdg.validation.Stored; import ru.spcex.platform.utils.enumeration.EnumMessage; +import ru.spcex.platform.utils.text.TextUtil; import ru.spcex.platform.utils.validation.IValidationRule; +import java.math.BigDecimal; import java.util.Optional; +import static ru.spcex.clearing.service.registry.RegistryManager.equalsByCode; + +//1. Проверки +//1.1 Проверить, в запросе у регистра код: +// 1.1.1 Если регистр TM-T: +// Проверить, что у registry.companyId существует категория I, иначе ошибка: 5420 - "Доступ к клирингу на «%s» не найден для компании %s."/> Где %s = категории И +// Проверить, что найденного регистра DM*X: registry.status!=OK, иначе ошибка: 5425 - "Запрещена идентификация средства по рассчитанным обязательствам". +// Создать/добавить в баланс DM-X на базе TM-T +// 1.1.2 Если регистр OM-T: +// Проверить, что у registry.companyId существует категория V, иначе ошибка: 5420 - "Доступ к клирингу на «%s» не найден для компании %s."/> Где %s = категории В +// Проверить, что найденного регистра DM*T: registry.status!=OK, иначе ошибка: 5425 - "Запрещена идентификация средства по рассчитанным обязательствам". +// Создать/добавить в баланс DM-T на базе OM-T +//1.2 Проверить, баланс в запросе +// Баланс должен быть положительный public enum ReturnDepositValidationRule implements IValidationRule> { + RgsWronCodeCheck() { + @Override + public Optional validate(ImdgValidationContext context) { + Registry rgs = context.getStoredObject(Stored.PresentById); + if (!equalsByCode(RegistryTradingParams.TM_T, rgs) && !equalsByCode(RegistryTradingParams.OM_T, rgs)) { + return of(ClearingError.RgsWrongCode, "{}.id={}", rgs.getRegistryCode(), rgs.getId()); + } + return empty(); + } + }, + CategoryCheck() { + @Override + public Optional validate(ImdgValidationContext context) { + Registry rgs = context.getStoredObject(Stored.PresentById); + ClearingCategory ctgr = null; + if (equalsByCode(RegistryTradingParams.TM_T, rgs)) { + ctgr = ClearingCategory.I; + } else { + ctgr = ClearingCategory.V; + } + Imdg ctgImdg = context.obtainMap(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class); + ClearingMemberCategory category = + ctgImdg.getFirstObjectBySQL("companyId = %d and clearingMemberCategory = '%s'" + .formatted(rgs.getCompanyId(), ctgr.getKey())); + if (category == null) { + return of(ClearingError.CategoryNotFound, ctgr.getKey(), rgs.getCompanyId()); + } + return empty(); + } + }, + @Deprecated RegistryCodeCheck() { @Override public Optional validate(ImdgValidationContext context) { @@ -34,23 +79,40 @@ public enum ReturnDepositValidationRule implements IValidationRule validate(ImdgValidationContext context) { Registry rgs = context.getStoredObject(Stored.PresentById); RegistryReturnDepositRequest request = context.getValidatedObject(); - if (request.getBalance() == null || request.getBalance().compareTo(rgs.getBalance()) > 0) { + if (request.getBalance() == null || request.getBalance().compareTo(BigDecimal.ZERO) < 0) { + return of(ClearingError.WrongField, "balance"); + } + if (request.getBalance().compareTo(rgs.getBalance()) > 0) { return of(ClearingError.IdentifiedFundsExceedObligations); } return Optional.empty(); } - }, DmxCheck() { + }, Dm_Check() { @Override public Optional validate(ImdgValidationContext context) { Registry rgs = context.getStoredObject(Stored.PresentById); Imdg rgsImdg = context.obtainMap(IMDGDistributedNames.Map_Registry, Registry.class); - RegistryManager rgsMng = new RegistryManager(rgsImdg); - Optional dmx = rgsMng.searchDmxByCompanyId(rgs); - if (dmx.isPresent() && RegistryStatus.OK.equalsByKey(dmx.get().getRegistryStatus()) ) { + if (TextUtil.isEmpty(rgs.getContract())) { + return empty(); + } + RegistryTradingParams rgsCode; + if (equalsByCode(RegistryTradingParams.TM_T, rgs)) { + rgsCode = RegistryTradingParams.DM_X; + } else { + rgsCode = RegistryTradingParams.DM_T; + } + String sqlCondition = String.format("(%s) and companyId = %d and contract = '%s'", + RegistryCodeSqlBuilder.getInstance(rgsCode).build(), + rgs.getCompanyId(), + rgs.getContract()); + Registry dm__ = rgsImdg.getFirstObjectBySQL(sqlCondition); + if (dm__ != null && RegistryStatus.OK.equalsByKey(dm__.getRegistryStatus()) ) { return of(ClearingError.ObligationsAlreadyCalculated); } - dmx.ifPresent(dmxRgs -> context.storeObject(ValidationStored.ReturnDepositDmx, dmxRgs)); - return Optional.empty(); + if (dm__ != null) { + context.storeObject(ValidationStored.ReturnDepositDm__, dm__); + } + return empty(); } }; diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java index 471106a79..a0ad7e8a8 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java @@ -18,7 +18,7 @@ public enum ValidationStored { Sdf06Company, Sdf06Account, Sdf06Tcr, - ReturnDepositDmx, + ReturnDepositDm__, IdentificationFundsTcrSearch, IdentificationFundsAssetTrio, diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/ReturnDepositSession.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/ReturnDepositSession.java index 4eadca2cb..5913b209e 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/ReturnDepositSession.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/ReturnDepositSession.java @@ -160,6 +160,7 @@ public class ReturnDepositSession extends AbstractSession implements Initializin { InspectionPoolPayload companyIdPayload = new InspectionPoolPayload(); companyIdPayload.setProcessedCompanyId(currSession.getCompanyId()); + companyIdPayload.setSessionId(currSession.getId()); runStage(TaskType.InspectionObligations, companyIdPayload, inspectionObligationsDepositReturn); } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InspectionObligations.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InspectionObligations.java index 327b6d8b2..a4161430a 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InspectionObligations.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InspectionObligations.java @@ -1,7 +1,5 @@ package ru.spcex.clearing.session.stage.impl; -import org.apache.commons.lang3.tuple.MutableTriple; -import org.apache.commons.lang3.tuple.Triple; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -55,16 +53,18 @@ public class InspectionObligations implements ISessionStage { private final AssetTBFProcessing assets; private final GatewayRequester gateway; private final TradingTimeService tradingTimeService; + private final PlanBalanceCalc planBalanceCalc; @Autowired public InspectionObligations(ImdgProvider imdgProvider, RegistryManager registryManager, AssetTBFProcessing assets, - GatewayRequester gateway) { + GatewayRequester gateway, PlanBalanceCalc planBalanceCalc) { this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); this.registryManager = registryManager; this.assets = assets; this.gateway = gateway; + this.planBalanceCalc = planBalanceCalc; this.gateway.setName("InspectionObligations|OM*T"); this.tradingTimeService = new TradingTimeService(imdgProvider); } @@ -204,52 +204,11 @@ public class InspectionObligations implements ISessionStage { } } - stageRevision2(sessionId); + planBalanceCalc.stageRevision2(sessionId); return new StageResult(null, true); } - protected void stageRevision2(Long sessionId) { - /* todo logic - Collection rgsAT = findRegistryATBySession // registry_disignation=A and registry_unit=T -Collection rgsAB = findRegistryATBySession // registry_disignation=A and registry_unit=B and sessionId = current - -foreach( at: rgsAT) - foreach (ab: rgsAB) - if (at.companyId=ab.companyId and at.accountId=ab.accountId and at.securityId=ab.securityId) - at.plannecBallance -= ab.balance - */ - String sqlAT = RegistryCodeSqlBuilder.getInstance(A__T).build(); - String sqlAB = String.format("(%s) and sessionId = %d", - RegistryCodeSqlBuilder.getInstance(A__B).build(), - sessionId - ); - Collection registriesAT = registryImdg.getCollectionObjectsBySQL(sqlAT); - Collection registriesAB = registryImdg.getCollectionObjectsBySQL(sqlAB); - log.debug("Select {} registers by \"{}\", {} registers by \"{}\" for revision step 2", - registriesAT.size(), sqlAT, registriesAB.size(), sqlAB); - Map, List> regABIndex = registriesAB.stream().collect(Collectors.groupingBy( - (Registry reg) -> new MutableTriple(reg.getCompanyId(), reg.getAccountId(), reg.getSecurityId()) - )); - int updateCount = 0; - Instant now = Instant.now(); - for (Registry regT : registriesAT) { - Triple key = new MutableTriple(regT.getCompanyId(), regT.getAccountId(), regT.getSecurityId()); - List regsB = regABIndex.get(key); - if (regsB == null) { - log.debug("Registry A__B for registry[{}] (A__T key {}) not found", regT, key); - } else { - for (Registry regB : regsB) { - regT.setPlanBalance(safeBD(regT.getPlanBalance()).subtract(safeBD(regB.getBalance()))); - } - regT.setUpdated(now); - registryImdg.update(regT); - updateCount++; - } - } - log.debug("Updated {} registers A__T with planBalance at {}", updateCount, now); - } - private String searchAssetsByObligationSql(Registry obligation) { RegistryTradingParams counterRegistryTradingParams = null; if (IEnumKey.getEnumByKey(RegistryInstrumentType.class, obligation.getRegistryInstrumentType()) == RegistryInstrumentType.S) { diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InspectionObligationsDepositReturn.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InspectionObligationsDepositReturn.java index 0e9742fb9..4d6df6934 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InspectionObligationsDepositReturn.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InspectionObligationsDepositReturn.java @@ -16,6 +16,7 @@ import ru.spcex.clearing.service.schedule.TradingTimeService; import ru.spcex.clearing.session.stage.ISessionStage; import ru.spcex.clearing.session.stage.StageResult; import ru.spcex.clearing.session.stage.Task; +import ru.spcex.clearing.session.stage.task.InspectionPoolPayload; import ru.spcex.platform.enumeration.*; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; @@ -44,23 +45,26 @@ public class InspectionObligationsDepositReturn implements ISessionStage { private final AssetTBFProcessing assets; private final TradingTimeService tradingTimeService; private final GatewayRequester gateway; + private final PlanBalanceCalc planBalanceCalc; @Autowired - public InspectionObligationsDepositReturn(ImdgProvider imdgProvider, RegistryManager rgsMng, AssetTBFProcessing assets, TradingTimeService tradingTimeService, GatewayRequester gateway) { + public InspectionObligationsDepositReturn(ImdgProvider imdgProvider, RegistryManager rgsMng, AssetTBFProcessing assets, TradingTimeService tradingTimeService, GatewayRequester gateway, PlanBalanceCalc planBalanceCalc) { this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); this.categoryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class); this.rgsMng = rgsMng; this.assets = assets; this.tradingTimeService = tradingTimeService; this.gateway = gateway; + this.planBalanceCalc = planBalanceCalc; this.gateway.setName("InspectionObligationsDepositReturn|OM*T"); } @Override public StageResult submit(Task task) { + InspectionPoolPayload payload = (InspectionPoolPayload) task.getData(); switch (task.getTaskType()) { case InspectionObligations -> { - return inspectionObligations(); + return inspectionObligations(payload.getSessionId()); } default -> throw new IllegalStateException("Unknown task type: " + task.getTaskType()); } @@ -81,7 +85,7 @@ public class InspectionObligationsDepositReturn implements ISessionStage { } } - private StageResult inspectionObligations() { + private StageResult inspectionObligations(Long sessionId) { String sqlCondition = String.format("(%s) and registryStatus = '%s'", RegistryCodeSqlBuilder.getInstance(OS_T, OM_T, TS_T, TM_T).build(), RegistryStatus.POOL.getKey()); @@ -196,6 +200,7 @@ public class InspectionObligationsDepositReturn implements ISessionStage { group.forEach(rgs -> updateStatus(rgs, registryStatusFailed(rgs))); } } + planBalanceCalc.stageRevision2(sessionId); return new StageResult<>(null, true); } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/PlanBalanceCalc.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/PlanBalanceCalc.java new file mode 100644 index 000000000..c1c51a30c --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/PlanBalanceCalc.java @@ -0,0 +1,73 @@ +package ru.spcex.clearing.session.stage.impl; + +import org.apache.commons.lang3.tuple.MutableTriple; +import org.apache.commons.lang3.tuple.Triple; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import ru.clearing.classes.statics.data.registry.Registry; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.predicate.specific.RegistryCodeSqlBuilder; + +import java.time.Instant; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static ru.spcex.platform.enumeration.RegistryTradingParams.A__B; +import static ru.spcex.platform.enumeration.RegistryTradingParams.A__T; +import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD; + +@Component +public class PlanBalanceCalc { + private final Logger log = LoggerFactory.getLogger(getClass()); + private final Imdg rgsImdg; + + public PlanBalanceCalc(ImdgProvider imdgProvider) { + this.rgsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); + } + + public void stageRevision2(Long sessionId) { + /* todo logic + Collection rgsAT = findRegistryATBySession // registry_disignation=A and registry_unit=T +Collection rgsAB = findRegistryATBySession // registry_disignation=A and registry_unit=B and sessionId = current + +foreach( at: rgsAT) + foreach (ab: rgsAB) + if (at.companyId=ab.companyId and at.accountId=ab.accountId and at.securityId=ab.securityId) + at.plannecBallance -= ab.balance + */ + String sqlAT = RegistryCodeSqlBuilder.getInstance(A__T).build(); + String sqlAB = String.format("(%s) and sessionId = %d", + RegistryCodeSqlBuilder.getInstance(A__B).build(), + sessionId + ); + Collection registriesAT = rgsImdg.getCollectionObjectsBySQL(sqlAT); + Collection registriesAB = rgsImdg.getCollectionObjectsBySQL(sqlAB); + log.debug("Select {} registers by \"{}\", {} registers by \"{}\" for revision step 2", + registriesAT.size(), sqlAT, registriesAB.size(), sqlAB); + Map, List> regABIndex = registriesAB.stream().collect(Collectors.groupingBy( + (Registry reg) -> new MutableTriple(reg.getCompanyId(), reg.getAccountId(), reg.getSecurityId()) + )); + int updateCount = 0; + Instant now = Instant.now(); + for (Registry regT : registriesAT) { + Triple key = new MutableTriple(regT.getCompanyId(), regT.getAccountId(), regT.getSecurityId()); + List regsB = regABIndex.get(key); + if (regsB == null) { + log.debug("Registry A__B for registry[{}] (A__T key {}) not found", regT, key); + } else { + for (Registry regB : regsB) { + regT.setPlanBalance(safeBD(regT.getPlanBalance()).subtract(safeBD(regB.getBalance()))); + } + regT.setUpdated(now); + rgsImdg.update(regT); + updateCount++; + } + } + log.debug("Updated {} registers A__T with planBalance at {}", updateCount, now); + } +} From c940316494b1dce7d6298eec9c1826e1d7e15650 Mon Sep 17 00:00:00 2001 From: ialbert Date: Tue, 26 Sep 2023 13:15:18 +0300 Subject: [PATCH 2/4] RegistryService#returnDeposit validator imdg bugfix --- .../main/java/ru/spcex/clearing/config/ValidationConfig.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java index d152890b4..dcf29e677 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java @@ -5,6 +5,7 @@ import org.springframework.context.annotation.Configuration; import ru.clearing.classes.statics.data.account.Account; import ru.clearing.classes.statics.data.account.AccountBalance; import ru.clearing.classes.statics.data.account.DepoAccount; +import ru.clearing.classes.statics.data.company.ClearingMemberCategory; import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.company.CompanySymbols; import ru.clearing.classes.statics.data.company.relation.Relation; @@ -69,6 +70,7 @@ public class ValidationConfig { Imdg sDf55Imdg; Imdg sDf54Imdg; Imdg pmtImdg; + Imdg ctgrImdg; ImdgProvider imdgProvider; public ValidationConfig(ImdgProvider imdgProvider) { @@ -91,6 +93,7 @@ public class ValidationConfig { this.sDf55Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf55, SDf55.class); this.sDf54Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf54, SDf54.class); this.pmtImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_PaymentInstruction, PaymentInstruction.class); + this.ctgrImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class); this.imdgProvider = imdgProvider; } @@ -326,6 +329,7 @@ public class ValidationConfig { ImdgValidationContext context = new ImdgValidationContext<>(); context.setValidatedObject(returnDepositRequest); context.addImdg(IMDGDistributedNames.Map_Registry, imdgRegistry); + context.addImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ctgrImdg); context.setLogPrefix(LogPrefixId.INSTANCE); return new ValidatorImpl<>(context, new PresentById(IMDGDistributedNames.Map_Registry, ClearingError.RecordNotFound, true), From b7498399635b5c706a5e88de39bf6853ba4e14d5 Mon Sep 17 00:00:00 2001 From: ialbert Date: Tue, 26 Sep 2023 15:06:22 +0300 Subject: [PATCH 3/4] return deposit dm*x/dm*t --- .../clearing/service/RegistryService.java | 10 +++- .../service/registry/RegistryManager.java | 2 + .../ReturnDepositValidationRule.java | 58 ++++++++++--------- .../service/validation/ValidationStored.java | 2 +- 4 files changed, 41 insertions(+), 31 deletions(-) diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java index 619695f8f..d1d05f9ef 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java @@ -20,6 +20,7 @@ import ru.spcex.clearing.platform.messaging.service.Status; import ru.spcex.clearing.service.builder.PaymentInstructionBuilderV2; import ru.spcex.clearing.service.integration.GatewayRequestCreator; import ru.spcex.clearing.service.registry.AssetTBFProcessing; +import ru.spcex.clearing.service.registry.RegistryManager; import ru.spcex.clearing.service.schedule.TradingTimeService; import ru.spcex.clearing.service.validation.ValidationStored; import ru.spcex.clearing.session.stage.impl.GatewayRequester; @@ -166,12 +167,14 @@ public class RegistryService { msgResolver.resolve(err.get())); return new RequestInfoUpdate(req.getId(), Status.Error, msgResolver.resolve(err.get())); } - Registry _m_t = validator.getStored(Stored.PresentById); + Registry _m_t = validator.getStored(ValidationStored.ReturnDepositOm_t); + if (_m_t == null) _m_t = validator.getStored(Stored.PresentById); + Registry dm__ = validator.getStored(ValidationStored.ReturnDepositDm__); if (dm__ != null) { dm__.setSessionId(null); dm__.setSessionType(null); - dm__.setBalance(requestPayload.getBalance()); + dm__.setBalance(safeBD(dm__.getBalance()).add(requestPayload.getBalance())); dm__.setUpdated(Instant.now()); registryImdg.update(dm__); log.debug("updated {}.id={} by RegistryReturnDepositRequest.id={}", @@ -181,13 +184,14 @@ public class RegistryService { } else { dm__ = _m_t.clone(); dm__.setRegistryDesignation(RegistryDesignation.D.getKey()); + RegistryManager.zeroState(dm__); if (RegistryDesignation.T.equalsByKey(_m_t.getRegistryDesignation())) { dm__.setRegistryUnit(RegistryUnit.X.getKey()); } else { dm__.setRegistryUnit(RegistryUnit.T.getKey()); } dm__.setRegistryCode(RegistryUtil.clearingCode(dm__)); - dm__.setBalance(requestPayload.getBalance()); + dm__.setBalance(safeBD(dm__.getBalance()).add(requestPayload.getBalance())); dm__.setSessionId(null); dm__.setSessionType(null); registryImdg.insert(dm__); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/registry/RegistryManager.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/registry/RegistryManager.java index 5f316cc29..69c6ecba4 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/registry/RegistryManager.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/registry/RegistryManager.java @@ -183,6 +183,8 @@ public class RegistryManager { //балансы rgs.setBalance(BigDecimal.ZERO); rgs.setDebit(BigDecimal.ZERO); + rgs.setSettledDebit(BigDecimal.ZERO); + rgs.setSettledCredit(BigDecimal.ZERO); rgs.setCredit(BigDecimal.ZERO); rgs.setDiffBalance(BigDecimal.ZERO); rgs.setCheckBalance(BigDecimal.ZERO); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ReturnDepositValidationRule.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ReturnDepositValidationRule.java index 421b59e1f..13b32dbe5 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ReturnDepositValidationRule.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ReturnDepositValidationRule.java @@ -5,16 +5,20 @@ import ru.clearing.classes.statics.data.registry.Registry; import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistryReturnDepositRequest; -import ru.spcex.platform.enumeration.*; +import ru.spcex.platform.enumeration.ClearingCategory; +import ru.spcex.platform.enumeration.RegistryStatus; +import ru.spcex.platform.enumeration.RegistryTradingParams; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.predicate.specific.RegistryCodeSqlBuilder; import ru.spcex.platform.imdg.validation.ImdgValidationContext; import ru.spcex.platform.imdg.validation.Stored; import ru.spcex.platform.utils.enumeration.EnumMessage; +import ru.spcex.platform.utils.enumeration.IEnumKey; import ru.spcex.platform.utils.text.TextUtil; import ru.spcex.platform.utils.validation.IValidationRule; import java.math.BigDecimal; +import java.util.Collection; import java.util.Optional; import static ru.spcex.clearing.service.registry.RegistryManager.equalsByCode; @@ -36,7 +40,7 @@ public enum ReturnDepositValidationRule implements IValidationRule validate(ImdgValidationContext context) { Registry rgs = context.getStoredObject(Stored.PresentById); - if (!equalsByCode(RegistryTradingParams.TM_T, rgs) && !equalsByCode(RegistryTradingParams.OM_T, rgs)) { + if (!equalsByCode(RegistryTradingParams.TM_T, rgs)) { //!equalsByCode(RegistryTradingParams.OM_T, rgs) return of(ClearingError.RgsWrongCode, "{}.id={}", rgs.getRegistryCode(), rgs.getId()); } return empty(); @@ -46,35 +50,34 @@ public enum ReturnDepositValidationRule implements IValidationRule validate(ImdgValidationContext context) { Registry rgs = context.getStoredObject(Stored.PresentById); - ClearingCategory ctgr = null; - if (equalsByCode(RegistryTradingParams.TM_T, rgs)) { - ctgr = ClearingCategory.I; - } else { - ctgr = ClearingCategory.V; - } Imdg ctgImdg = context.obtainMap(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class); - ClearingMemberCategory category = - ctgImdg.getFirstObjectBySQL("companyId = %d and clearingMemberCategory = '%s'" - .formatted(rgs.getCompanyId(), ctgr.getKey())); - if (category == null) { - return of(ClearingError.CategoryNotFound, ctgr.getKey(), rgs.getCompanyId()); + Collection category = ctgImdg.getCollectionObjectsBySQL( + "companyId = %d".formatted(rgs.getCompanyId())); + + Optional ctgr = category.stream() + .map(c -> IEnumKey.getEnumByKey(ClearingCategory.class, c.getClearingMemberCategory())) + .filter(c -> ClearingCategory.V.equals(c) || ClearingCategory.I.equals(c)) + .findFirst(); + + if (ctgr.isEmpty()) { + return of(ClearingError.CategoryNotFound, "I/V", rgs.getCompanyId()); + } + if (ctgr.get().equals(ClearingCategory.V)) { + Imdg rgsImdg = context.obtainMap(IMDGDistributedNames.Map_Registry, Registry.class); + Collection group = rgsImdg.getCollectionObjectsBySQL("groupId = %d".formatted(rgs.getGroupId())); + Optional om_t = group.stream() + .filter(r -> r.getSettlementDate() != null) + .filter(r -> r.getValueDate() != null) + .filter(r -> r.getSettlementDate().isAfter(r.getValueDate())) + .filter(r -> equalsByCode(RegistryTradingParams.OM_T, r)) + .findFirst(); + if (om_t.isEmpty()) return of(ClearingError.RecordNotFound, "OM*T.groupId=%d".formatted(rgs.getGroupId())); + context.storeObject(ValidationStored.ReturnDepositOm_t, om_t.get()); } return empty(); } }, - @Deprecated - RegistryCodeCheck() { - @Override - public Optional validate(ImdgValidationContext context) { - Registry rgs = context.getStoredObject(Stored.PresentById); - if (!RegistryDesignation.T.equalsByKey(rgs.getRegistryDesignation()) - || !RegistryInstrumentType.M.equalsByKey(rgs.getRegistryInstrumentType()) - || !RegistryUnit.T.equalsByKey(rgs.getRegistryUnit())) { - return of(ClearingError.RecordNotFoundInDictionary, "TM*T", "Registry"); - } - return empty(); - } - }, BalanceCheck() { + BalanceCheck() { @Override public Optional validate(ImdgValidationContext context) { Registry rgs = context.getStoredObject(Stored.PresentById); @@ -90,7 +93,8 @@ public enum ReturnDepositValidationRule implements IValidationRule validate(ImdgValidationContext context) { - Registry rgs = context.getStoredObject(Stored.PresentById); + Registry rgs = context.getStoredObject(ValidationStored.ReturnDepositOm_t); + if (rgs == null) rgs = context.getStoredObject(Stored.PresentById); Imdg rgsImdg = context.obtainMap(IMDGDistributedNames.Map_Registry, Registry.class); if (TextUtil.isEmpty(rgs.getContract())) { return empty(); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java index a0ad7e8a8..057aecc58 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java @@ -18,7 +18,7 @@ public enum ValidationStored { Sdf06Company, Sdf06Account, Sdf06Tcr, - ReturnDepositDm__, + ReturnDepositDm__, ReturnDepositOm_t, IdentificationFundsTcrSearch, IdentificationFundsAssetTrio, From 43911cbb589d8c4884224b2554948c46717c167d Mon Sep 17 00:00:00 2001 From: ialbert Date: Thu, 28 Sep 2023 17:25:04 +0300 Subject: [PATCH 4/4] TCR registry update, AM*F/AM*T/AM*B creation --- .../clearing/service/RegistryService.java | 55 +++++++++++++++++++ .../service/registry/AssetTBFProcessing.java | 40 ++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java index d1d05f9ef..f1d97ade4 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java @@ -5,6 +5,8 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.account.Account; +import ru.clearing.classes.statics.data.company.Company; +import ru.clearing.classes.statics.data.misc.Currency; import ru.clearing.classes.statics.data.payment.PaymentInstruction; import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.registry.TradingClearingRegistry; @@ -47,6 +49,7 @@ import java.util.Map; import java.util.Optional; import java.util.function.Function; import java.util.function.Supplier; +import java.util.stream.Stream; import static ru.spcex.clearing.session.stage.impl.GatewayRequester.mapError; import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD; @@ -58,6 +61,9 @@ public class RegistryService { private final ImdgProvider imdgProvider; private final Imdg tradingClearingRegistryImdg; private final Imdg registryImdg; + private final Imdg accImdg; + private final Imdg currImdg; + private final Imdg cmpImdg; private final Imdg pmtImdg; private final Function returnDepositVal; private final Function refundDateVal; @@ -90,6 +96,9 @@ public class RegistryService { this.tradingClearingRegistryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class); this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); this.pmtImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_PaymentInstruction, PaymentInstruction.class); + this.accImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class); + this.currImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Currency, Currency.class); + this.cmpImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class); this.returnDepositVal = returnDepositVal; this.refundDateVal = refundDateVal; this.identificationFundsVal = identificationFundsVal; @@ -155,6 +164,52 @@ public class RegistryService { registryImdg.update(rgs); log.trace("TCR#id={} registry#id={} updated", tcr.getId(), rgs.getId()); }); + + if (registries.size() > 0) { + log.info("assets size {} updated by TCR#id={}, will not create new assets", + registries.size(), tcr.getId()); + return; + } + + Account acc = accImdg.getSingleObjectByID(tcr.getMoneyAccountId()); + Currency currency = currImdg.getFirstObjectBySQL("currencyCode = '%s'".formatted(CurrencyCode.RUB.getKey())); + Company cmp = cmpImdg.getSingleObjectByID(tcr.getCompanyId()); + + if (acc == null) { + log.warn("TCR#id={} account {} not found", tcr.getId(), tcr.getMoneyAccountId()); + return; + } + if (currency == null) { + log.warn("TCR#id={} currency {} not found", tcr.getId(), CurrencyCode.RUB.getKey()); + return; + } + if (cmp == null) { + log.warn("TCR#id={} company {} not found", tcr.getId(), tcr.getCompanyId()); + return; + } + log.debug("TCR#id={} account#id={} company#id={}, creating assets", tcr.getId(), acc.getId(), cmp.getId()); + + AssetTrio assets = this.assets.createMAssets(acc, + CurrencyCode.RUB.getKey(), + currency.getId(), + tcr.getTradingClearingRegistryType(), + tcr.getId(), + tcr.getCode(), + cmp); + + + Stream.of(assets.a__t(), assets.a__b(), assets.a__f()) + .forEach(a -> { + a.setRegistryStatus(RegistryStatus.PROC.getKey()); + registryImdg.insert(a); + }); + + log.debug("TCR#id={} created {}#id={} {}#id={} {}#id={}", + tcr.getId(), + assets.a__f().getRegistryCode(), assets.a__f().getId(), + assets.a__t().getRegistryCode(), assets.a__t().getId(), + assets.a__b().getRegistryCode(), assets.a__b().getId()); + } public RequestInfoUpdate returnDeposit(BaseRequest req) { diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/registry/AssetTBFProcessing.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/registry/AssetTBFProcessing.java index 3b5c3ac62..a8aa42d54 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/registry/AssetTBFProcessing.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/registry/AssetTBFProcessing.java @@ -162,6 +162,46 @@ public class AssetTBFProcessing { return new AssetTrio(asf, asb, ast); } + public AssetTrio createMAssets(Account acc, + String securitySymbol, + Long securityId, + String tcrType, + Long tcrId, + String tcr, + Company company) { + Registry ast = new Registry(); + ast.setCreated(Instant.now()); + ast.setSecuritySymbol(securitySymbol); + ast.setSecurityId(securityId); + ast.setAccountId(acc.getId()); + ast.setAccount(acc.getAccount()); + ast.setAccountType(acc.getAccountType()); + ast.setRegistryDesignation(RegistryDesignation.A.getKey()); + ast.setRegistryInstrumentType(RegistryInstrumentType.M.getKey()); + ast.setRegistryCapacity(tcrType); + ast.setRegistryUnit(RegistryUnit.T.getKey()); + ast.setRegistryCode(RegistryUtil.clearingCode(ast)); + ast.setClearingCode(company.getClearingCode()); + ast.setTradingCode(company.getClearingCode()); + ast.setCompanyId(company.getId()); + ast.setShortName(company.getShortName()); + ast.setFullName(company.getFullName()); + ast.setTradingClearingRegistryId(tcrId); + ast.setTradingClearingRegistry(tcr); + ast.setRegistryStatus(RegistryStatus.OK.getKey()); + ast.setBalanceDimension(BalanceDimension.MONY.getKey()); + RegistryManager.zeroState(ast); + Registry asf = ast.clone(); + asf.setRegistryUnit(RegistryUnit.F.getKey()); + asf.setRegistryCode(RegistryUtil.clearingCode(asf)); + RegistryManager.zeroState(asf); + Registry asb = ast.clone(); + asb.setRegistryUnit(RegistryUnit.B.getKey()); + asb.setRegistryCode(RegistryUtil.clearingCode(asb)); + RegistryManager.zeroState(asb); + return new AssetTrio(asf, asb, ast); + } + public Optional searchByTcrCompanyAccount(Registry rgs, RegistryTradingParams params) { ImdgPredicateBuilder pb = rgsImdg.predicateBuilder();