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..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,12 +329,14 @@ 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), - 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 fe40c2381..18e15fab6 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 3bb4deeaf..4c4455891 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; @@ -23,6 +25,7 @@ import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; 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; @@ -49,6 +52,8 @@ import java.util.List; 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.platform.utils.number.BigDecimalUtil.safeBD; @@ -59,6 +64,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; @@ -92,6 +100,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; @@ -158,6 +169,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) { @@ -170,28 +227,37 @@ 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(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(safeBD(dm__.getBalance()).add(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()); + 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(safeBD(dm__.getBalance()).add(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/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(); 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 31b1c6a28..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 @@ -1,56 +1,122 @@ 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.ClearingCategory; import ru.spcex.platform.enumeration.RegistryStatus; -import ru.spcex.platform.enumeration.RegistryUnit; +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; + +//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> { - RegistryCodeCheck() { + RgsWronCodeCheck() { @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"); + if (!equalsByCode(RegistryTradingParams.TM_T, rgs)) { //!equalsByCode(RegistryTradingParams.OM_T, rgs) + return of(ClearingError.RgsWrongCode, "{}.id={}", rgs.getRegistryCode(), rgs.getId()); } return empty(); } - }, BalanceCheck() { + }, + CategoryCheck() { + @Override + public Optional validate(ImdgValidationContext context) { + Registry rgs = context.getStoredObject(Stored.PresentById); + Imdg ctgImdg = context.obtainMap(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class); + 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(); + } + }, + BalanceCheck() { @Override public Optional 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); + Registry rgs = context.getStoredObject(ValidationStored.ReturnDepositOm_t); + if (rgs == null) 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..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, - ReturnDepositDmx, + ReturnDepositDm__, ReturnDepositOm_t, 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 1b3ec1989..227555640 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); + } +}