From 09f874204b361ef6681c1dc0844c152d1be882e9 Mon Sep 17 00:00:00 2001 From: ialbert Date: Thu, 18 Jul 2024 12:06:30 +0300 Subject: [PATCH] InspectionObligations united cash InspectionObligationsV2 separated cash RequirementsAndObligationCreation: unnecessary search removed; registry creating for FOND cashed --- .../account/AccountIdCashingPredicate.java | 24 + .../cash/currency/CurrencyCodePredicate.java | 24 + .../clearing/service/cash/RegistryCash.java | 174 ++++++++ .../service/cash/impl/RegistryCashA__F.java | 89 ++++ .../cash/impl/RegistryCashAssetCash.java | 90 ++++ .../service/cash/impl/RegistryCashD___.java | 94 ++++ .../registry/AssetTBFProcessingCashing.java | 114 +++++ .../session/stage/CurrencySession.java | 10 +- .../session/stage/FinalMkrSession.java | 44 +- .../session/stage/IntermediateMkrSession.java | 42 +- .../stage/PrimaryAuctionB0Session.java | 41 +- .../stage/PrimaryAuctionBnSession.java | 41 +- .../stage/PrimaryAuctionT0Session.java | 41 +- .../stage/SecondaryAuctionT0Session.java | 44 +- .../clearing/session/stage/UnitedSession.java | 4 +- .../session/stage/impl/IRegistryBuilder.java | 18 + .../stage/impl/InspectionObligations.java | 59 ++- .../stage/impl/InspectionObligationsV2.java | 420 ++++++++++++++++++ .../stage/impl/RegistryFondBuilder.java | 101 ++++- .../RequirementsAndObligationCreation.java | 99 ++++- ...irementsAndObligationCreationCompound.java | 8 +- ...sAndObligationCreationCompoundPayload.java | 12 +- ...uirementsAndObligationCreationPayload.java | 30 ++ .../session/stage/util/RegistryUtil.java | 35 +- 24 files changed, 1557 insertions(+), 101 deletions(-) create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/component/predicate/cash/account/AccountIdCashingPredicate.java create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/component/predicate/cash/currency/CurrencyCodePredicate.java create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/cash/RegistryCash.java create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/cash/impl/RegistryCashA__F.java create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/cash/impl/RegistryCashAssetCash.java create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/cash/impl/RegistryCashD___.java create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/registry/AssetTBFProcessingCashing.java create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InspectionObligationsV2.java create mode 100644 clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/task/RequirementsAndObligationCreationPayload.java diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/component/predicate/cash/account/AccountIdCashingPredicate.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/component/predicate/cash/account/AccountIdCashingPredicate.java new file mode 100644 index 000000000..dea5f9919 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/component/predicate/cash/account/AccountIdCashingPredicate.java @@ -0,0 +1,24 @@ +package ru.spcex.clearing.component.predicate.cash.account; + +import ru.spcex.platform.classes.base.SpcexObjectBase; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; +import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2; + +public class AccountIdCashingPredicate { + + public static AccountIdCashingPredicate getPredicate(Long accId) { + return new AccountIdCashingPredicate(accId); + } + + private final Long accId; + + private AccountIdCashingPredicate(Long accId) { + this.accId = accId; + } + + public ImdgPredicate cashed(ImdgPredicateBuilder pb, CashV2 cash) { + ImdgPredicate prdct = pb.equals("accountId", accId); + return pb.cashed(prdct, cash, accId); + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/component/predicate/cash/currency/CurrencyCodePredicate.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/component/predicate/cash/currency/CurrencyCodePredicate.java new file mode 100644 index 000000000..470c4c3ee --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/component/predicate/cash/currency/CurrencyCodePredicate.java @@ -0,0 +1,24 @@ +package ru.spcex.clearing.component.predicate.cash.currency; + +import ru.clearing.classes.statics.data.misc.Currency; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; +import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2; + +public class CurrencyCodePredicate { + + public static CurrencyCodePredicate getPredicate(String curCde) { + return new CurrencyCodePredicate(curCde); + } + + private final String curCde; + + private CurrencyCodePredicate(String curCde) { + this.curCde = curCde; + } + + public ImdgPredicate cashed(ImdgPredicateBuilder pb, CashV2 cash) { + ImdgPredicate prdct = pb.equals("currencyCode", curCde); + return pb.cashed(prdct, cash, curCde); + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/cash/RegistryCash.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/cash/RegistryCash.java new file mode 100644 index 000000000..16d8242ec --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/cash/RegistryCash.java @@ -0,0 +1,174 @@ +package ru.spcex.clearing.service.cash; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ru.clearing.classes.statics.data.registry.Registry; +import ru.spcex.clearing.session.stage.util.RegistryUtil; +import ru.spcex.platform.enumeration.RegistryCapacity; +import ru.spcex.platform.enumeration.RegistryInstrumentType; +import ru.spcex.platform.enumeration.RegistryTradingParams; + +public class RegistryCash { + private final Logger log = LoggerFactory.getLogger(getClass()); + private long hitRate = 0; + private long missRate = 0; + private final Map cash1; + private final Map cash2; + + public RegistryCash() { + this.cash1 = new HashMap<>(); + this.cash2 = new HashMap<>(); + } + + public void clear() { + log.info("Registry cash: size {}, hit rate {}, miss rate {}", cash1.size(), hitRate, missRate); + this.hitRate = 0L; + this.missRate = 0L; + this.cash1.clear(); + this.cash2.clear(); + } + + public void store(Registry rgs) { + if (rgs == null) return; + CmpKey1 key1 = new CmpKey1(RegistryUtil.rgsCdeWithoutCapacity(rgs), rgs.getTradingClearingRegistryId(), rgs.getSecuritySymbol(), rgs.getCompanyId()); + CmpKey2 key2 = new CmpKey2(RegistryUtil.rgsCdeWithoutCapacity(rgs), rgs.getTradingClearingRegistryId(), rgs.getSecurityId(), rgs.getCompanyId(), rgs.getAccountId()); + cash1.put(key1, rgs); + cash2.put(key2, rgs); + } + + private Optional getBy(String rgsCde, Long tcrId, String secSymbol, Long cmpId) { + CmpKey1 key = new CmpKey1(rgsCde, tcrId, secSymbol, cmpId); + Registry rgs = cash1.get(key); + if (rgs != null) hitRate++; + else missRate++; + return Optional.ofNullable(rgs); + } + + //AM*F/AS*F + public Optional getBy(Registry obligation) { + if (obligation == null) return Optional.empty(); + RegistryTradingParams rgsCde = null; + + if (RegistryInstrumentType.S.equalsByKey(obligation.getRegistryInstrumentType())) { + rgsCde = RegistryTradingParams.AS_F; + } else if (RegistryInstrumentType.M.equalsByKey(obligation.getRegistryInstrumentType())) { + rgsCde = RegistryTradingParams.AM_F; + } + if (rgsCde == null) return Optional.empty(); + + return getBy( + RegistryUtil.clearingCode(rgsCde), + obligation.getTradingClearingRegistryId(), + obligation.getSecuritySymbol(), + obligation.getCompanyId()); + } + + private Optional getBy(String rgsCde, Long tcrId, Long secId, Long cmpId, Long accId) { + CmpKey2 key = new CmpKey2(rgsCde, tcrId, secId, cmpId, accId); + Registry rgs = cash2.get(key); + if (rgs != null) hitRate++; + else missRate++; + return Optional.ofNullable(rgs); + } + + public Optional getBy(Registry rgs, RegistryTradingParams params) { + if (rgs == null) return Optional.empty(); + return getBy( + RegistryUtil.clearingCode(params.cpcty((RegistryCapacity) null)), + rgs.getTradingClearingRegistryId(), + rgs.getSecurityId(), + rgs.getCompanyId(), + rgs.getAccountId()); + } + + +// public Optional + + + //AM*F/AS*F: RegistryCode, tcrId, securitySymbol, companyId + //для всех: RegistryCode, tcrId, securityId, companyId, accountId + + //в этом шаге: + //a**f только для облигейшенов (всегда будет) + //a**t для всех кроме 'S' бумаг в МКР сессии + + private static class CmpKey1 { + private final String rgsCde; + private final Long tcrId; + private final String secSymbol; + private final Long cmpId; + + private CmpKey1(String rgsCde, Long tcrId, String secSymbol, Long cmpId) { + this.rgsCde = rgsCde; + this.tcrId = tcrId; + this.secSymbol = secSymbol; + this.cmpId = cmpId; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + CmpKey1 cmpKey1 = (CmpKey1) o; + + if (!Objects.equals(rgsCde, cmpKey1.rgsCde)) return false; + if (!Objects.equals(tcrId, cmpKey1.tcrId)) return false; + if (!Objects.equals(secSymbol, cmpKey1.secSymbol)) return false; + return Objects.equals(cmpId, cmpKey1.cmpId); + } + + @Override + public int hashCode() { + int result = rgsCde != null ? rgsCde.hashCode() : 0; + result = 31 * result + (tcrId != null ? tcrId.hashCode() : 0); + result = 31 * result + (secSymbol != null ? secSymbol.hashCode() : 0); + result = 31 * result + (cmpId != null ? cmpId.hashCode() : 0); + return result; + } + } + + private static class CmpKey2 { + private final String rgsCde; + private final Long tcrId; + private final Long secId; + private final Long cmpId; + private final Long accId; + + public CmpKey2(String rgsCde, Long tcrId, Long secId, Long cmpId, Long accId) { + this.rgsCde = rgsCde; + this.tcrId = tcrId; + this.secId = secId; + this.cmpId = cmpId; + this.accId = accId; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + CmpKey2 cmpKey2 = (CmpKey2) o; + + if (!Objects.equals(rgsCde, cmpKey2.rgsCde)) return false; + if (!Objects.equals(tcrId, cmpKey2.tcrId)) return false; + if (!Objects.equals(secId, cmpKey2.secId)) return false; + if (!Objects.equals(cmpId, cmpKey2.cmpId)) return false; + return Objects.equals(accId, cmpKey2.accId); + } + + @Override + public int hashCode() { + int result = rgsCde != null ? rgsCde.hashCode() : 0; + result = 31 * result + (tcrId != null ? tcrId.hashCode() : 0); + result = 31 * result + (secId != null ? secId.hashCode() : 0); + result = 31 * result + (cmpId != null ? cmpId.hashCode() : 0); + result = 31 * result + (accId != null ? accId.hashCode() : 0); + return result; + } + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/cash/impl/RegistryCashA__F.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/cash/impl/RegistryCashA__F.java new file mode 100644 index 000000000..ab4bfeb0d --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/cash/impl/RegistryCashA__F.java @@ -0,0 +1,89 @@ +package ru.spcex.clearing.service.cash.impl; + +import java.util.Objects; +import java.util.Optional; +import java.util.function.Supplier; +import ru.clearing.classes.statics.data.registry.Registry; +import ru.spcex.clearing.session.stage.util.RegistryUtil; +import ru.spcex.platform.enumeration.RegistryInstrumentType; +import ru.spcex.platform.enumeration.RegistryTradingParams; +import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2; + +public class RegistryCashA__F extends CashV2 { + + public RegistryCashA__F(String name) { + super(name); + } + + private RegistryCashA__F.CustomKey key(Registry obligation) { + if (obligation == null) throw new IllegalStateException("cannot obtain cash for null obligation"); + RegistryTradingParams rgsCde = null; + + if (RegistryInstrumentType.S.equalsByKey(obligation.getRegistryInstrumentType())) { + rgsCde = RegistryTradingParams.AS_F; + } else if (RegistryInstrumentType.M.equalsByKey(obligation.getRegistryInstrumentType())) { + rgsCde = RegistryTradingParams.AM_F; + } + if (rgsCde == null) + throw new IllegalStateException("unknown registry instrument type " + obligation.getRegistryInstrumentType()); + + CustomKey key = new CustomKey( + RegistryUtil.clearingCode(rgsCde), + obligation.getTradingClearingRegistryId(), + obligation.getSecuritySymbol(), + obligation.getCompanyId()); + return key; + } + + public Optional get(Registry obligation) { + CustomKey key = key(obligation); + return get(key); + } + + public Registry getOrFind(Registry obligation, Supplier finder) { + CustomKey key = key(obligation); + return getOrFind(key, finder).orElse(null); + } + + @Override + protected CustomKey extractKey(Registry rgs) { + return new CustomKey(RegistryUtil.rgsCdeWithoutCapacity(rgs), rgs.getTradingClearingRegistryId(), rgs.getSecuritySymbol(), rgs.getCompanyId()); + } + + public static class CustomKey { + private final String rgsCde; + private final Long tcrId; + private final String secSymbol; + private final Long cmpId; + + private CustomKey(String rgsCde, Long tcrId, String secSymbol, Long cmpId) { + this.rgsCde = rgsCde; + this.tcrId = tcrId; + this.secSymbol = secSymbol; + this.cmpId = cmpId; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + CustomKey cmpKey1 = (CustomKey) o; + + if (!Objects.equals(rgsCde, cmpKey1.rgsCde)) return false; + if (!Objects.equals(tcrId, cmpKey1.tcrId)) return false; + if (!Objects.equals(secSymbol, cmpKey1.secSymbol)) return false; + return Objects.equals(cmpId, cmpKey1.cmpId); + } + + @Override + public int hashCode() { + int result = rgsCde != null ? rgsCde.hashCode() : 0; + result = 31 * result + (tcrId != null ? tcrId.hashCode() : 0); + result = 31 * result + (secSymbol != null ? secSymbol.hashCode() : 0); + result = 31 * result + (cmpId != null ? cmpId.hashCode() : 0); + return result; + } + } + +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/cash/impl/RegistryCashAssetCash.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/cash/impl/RegistryCashAssetCash.java new file mode 100644 index 000000000..e528a1d62 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/cash/impl/RegistryCashAssetCash.java @@ -0,0 +1,90 @@ +package ru.spcex.clearing.service.cash.impl; + +import java.util.Objects; +import java.util.Optional; +import java.util.function.Supplier; +import ru.clearing.classes.statics.data.registry.Registry; +import ru.spcex.clearing.session.stage.util.RegistryUtil; +import ru.spcex.platform.enumeration.RegistryCapacity; +import ru.spcex.platform.enumeration.RegistryTradingParams; +import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2; + +public class RegistryCashAssetCash extends CashV2 { + + public RegistryCashAssetCash(String name) { + super(name); + } + + private CustomKey key(Registry rgs, RegistryTradingParams params) { + return new CustomKey( + RegistryUtil.clearingCode(params.cpcty((RegistryCapacity) null)), + rgs.getTradingClearingRegistryId(), + rgs.getSecurityId(), + rgs.getCompanyId(), + rgs.getAccountId()); + } + + public Optional get(Registry rgs, RegistryTradingParams params) { + CustomKey key = key(rgs, params); + return get(key); + } + + public Optional getOrFindO(Registry rgs, RegistryTradingParams params, Supplier> finder) { + CustomKey key = key(rgs, params); + return getOrFind(key, () -> { + Optional registry = finder.get(); + return registry.orElse(null); + }); + } + + public Optional getOrFind(Registry rgs, RegistryTradingParams params, Supplier finder) { + CustomKey key = key(rgs, params); + return getOrFind(key, finder); + } + + @Override + protected CustomKey extractKey(Registry rgs) { + return new CustomKey(RegistryUtil.rgsCdeWithoutCapacity(rgs), rgs.getTradingClearingRegistryId(), rgs.getSecurityId(), rgs.getCompanyId(), rgs.getAccountId()); + } + + public static class CustomKey { + private final String rgsCde; + private final Long tcrId; + private final Long secId; + private final Long cmpId; + private final Long accId; + + public CustomKey(String rgsCde, Long tcrId, Long secId, Long cmpId, Long accId) { + this.rgsCde = rgsCde; + this.tcrId = tcrId; + this.secId = secId; + this.cmpId = cmpId; + this.accId = accId; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + CustomKey cmpKey2 = (CustomKey) o; + + if (!Objects.equals(rgsCde, cmpKey2.rgsCde)) return false; + if (!Objects.equals(tcrId, cmpKey2.tcrId)) return false; + if (!Objects.equals(secId, cmpKey2.secId)) return false; + if (!Objects.equals(cmpId, cmpKey2.cmpId)) return false; + return Objects.equals(accId, cmpKey2.accId); + } + + @Override + public int hashCode() { + int result = rgsCde != null ? rgsCde.hashCode() : 0; + result = 31 * result + (tcrId != null ? tcrId.hashCode() : 0); + result = 31 * result + (secId != null ? secId.hashCode() : 0); + result = 31 * result + (cmpId != null ? cmpId.hashCode() : 0); + result = 31 * result + (accId != null ? accId.hashCode() : 0); + return result; + } + } + +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/cash/impl/RegistryCashD___.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/cash/impl/RegistryCashD___.java new file mode 100644 index 000000000..8b4e458f2 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/cash/impl/RegistryCashD___.java @@ -0,0 +1,94 @@ +package ru.spcex.clearing.service.cash.impl; + +import java.util.Collection; +import java.util.Collections; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Supplier; +import ru.clearing.classes.statics.data.registry.Registry; +import ru.spcex.clearing.session.stage.util.RegistryUtil; +import ru.spcex.platform.enumeration.RegistryCapacity; +import ru.spcex.platform.enumeration.RegistryTradingParams; +import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2; + +public class RegistryCashD___ extends CashV2> { + public RegistryCashD___(String name) { + super(name); + } + + private RegistryCashD___.CustomKey key(Registry rgs, RegistryTradingParams params) { + if (rgs == null) throw new IllegalStateException("cannot obtain cash for null registry"); + params = params.type(rgs.getRegistryInstrumentType()).cpcty((RegistryCapacity) null); + return new CustomKey( + RegistryUtil.clearingCode(params), + rgs.getSecuritySymbol(), + rgs.getCompanyId(), + rgs.getAccount()); + } + + public Collection get(Registry rgs, RegistryTradingParams params) { + CustomKey key = key(rgs, params); + Optional> registries = get(key); + return registries.orElse(Collections.emptyList()); + } + + public Collection getOrFind(Registry rgs, RegistryTradingParams params, Supplier> finder) { + CustomKey key = key(rgs, params); + Optional> registries = getOrFind(key, finder); + return registries.orElse(Collections.emptyList()); + } + + @Override + protected boolean needToStore(Collection obj) { + return obj != null; + } + + @Override + protected CustomKey extractKey(Collection rgss) { + Registry rgs = rgss + .stream() + .findFirst() + .orElseThrow(() -> new IllegalStateException("cannot store 0 element collection")); + return new CustomKey(RegistryUtil.rgsCdeWithoutCapacity(rgs), + rgs.getSecuritySymbol(), + rgs.getCompanyId(), + rgs.getAccount()); + } + + public static class CustomKey { + private final String rgsCde; + private final String secSymbol; + private final Long cmpId; + private final String acc; + + private CustomKey(String rgsCde, String secSymbol, Long cmpId, String acc) { + this.rgsCde = rgsCde; + this.secSymbol = secSymbol; + this.cmpId = cmpId; + this.acc = acc; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + CustomKey customKey = (CustomKey) o; + + if (!Objects.equals(rgsCde, customKey.rgsCde)) return false; + if (!Objects.equals(secSymbol, customKey.secSymbol)) return false; + if (!Objects.equals(cmpId, customKey.cmpId)) return false; + return Objects.equals(acc, customKey.acc); + } + + @Override + public int hashCode() { + int result = rgsCde != null ? rgsCde.hashCode() : 0; + result = 31 * result + (secSymbol != null ? secSymbol.hashCode() : 0); + result = 31 * result + (cmpId != null ? cmpId.hashCode() : 0); + result = 31 * result + (acc != null ? acc.hashCode() : 0); + return result; + } + } + +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/registry/AssetTBFProcessingCashing.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/registry/AssetTBFProcessingCashing.java new file mode 100644 index 000000000..875faa6c1 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/registry/AssetTBFProcessingCashing.java @@ -0,0 +1,114 @@ +package ru.spcex.clearing.service.registry; + +import java.math.BigDecimal; +import java.time.Instant; +import java.util.Collection; +import java.util.function.Consumer; +import java.util.function.Supplier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ru.clearing.classes.statics.data.account.Account; +import ru.clearing.classes.statics.data.registry.Registry; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.service.cash.impl.RegistryCashD___; +import ru.spcex.platform.enumeration.RegistryStatus; +import ru.spcex.platform.enumeration.RegistryTradingParams; +import static ru.spcex.platform.enumeration.RegistryTradingParams.D__I; +import static ru.spcex.platform.enumeration.RegistryTradingParams.D__V; +import ru.spcex.platform.imdg.api.Imdg; +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.number.BigDecimalUtil.safeBD; + +public class AssetTBFProcessingCashing { + private final Logger log = LoggerFactory.getLogger(getClass()); + private final Imdg rgsImdg; + private final Imdg accImdg; + private final RegistryCashD___ cash; + + public AssetTBFProcessingCashing(ImdgProvider imdgProvider, RegistryCashD___ cash) { + this.rgsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); + this.accImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class); + this.cash = cash; + } + + /** + * пересчитывает A**F = A**T - A**B + D**I - D**V + * учитываются только D**I с отрицательным balance. + * @param am_b регистр блокированных средств + * @param am_t регистр средств под торги + * @param am_f регистр свободных средств + * @param sum отнимается от блокировки. + */ + public void process(Registry am_b, Registry am_t, Registry am_f, BigDecimal sum) { + boolean am_bExists = am_b != null; + if (!am_bExists) { + am_b = new Registry(); + } + safeWrapField(am_t::getBalance, am_t::setBalance); + safeWrapField(am_b::getBalance, am_b::setBalance); + safeWrapField(am_f::getBalance, am_f::setBalance); + Collection d__is = cash.getOrFind(am_t, D__I, () -> searchByParams(am_t.getAccount(), + am_t.getSecuritySymbol(), + am_t.getCompanyId(), + D__I.type(am_t.getRegistryInstrumentType()))); + BigDecimal d__iSum = d__is.stream() + .filter(d__i -> safeBD(d__i.getBalance()).compareTo(BigDecimal.ZERO) < 0) + .map(rgs -> safeBD(rgs.getBalance())) + .reduce(BigDecimal.ZERO, BigDecimal::add); + Collection d__vs = cash.getOrFind(am_t, D__V, () -> searchByParams(am_t.getAccount(), + am_t.getSecuritySymbol(), + am_t.getCompanyId(), + D__V.type(am_t.getRegistryInstrumentType()))); + BigDecimal d__vSum = d__vs.stream() + .map(rgs -> safeBD(rgs.getBalance())) + .reduce(BigDecimal.ZERO, BigDecimal::add); + Instant now = Instant.now(); + BigDecimal am_fBalanceForLoging = am_f.getBalance(); + BigDecimal am_bBalanceForLoging = am_b.getBalance(); + if (!am_bExists && sum != null && sum.compareTo(BigDecimal.ZERO) != 0) { + log.error("FATAL: A**F.id={}; A**T.id={} A**B is null, yet #sum={}", am_f.getId(), am_t.getId(), sum); + } + am_b.setBalance(am_b.getBalance().subtract(sum)); + am_f.setBalance(am_t.getBalance().subtract(am_b.getBalance()).add(d__iSum).subtract(d__vSum)); + if (am_bExists) { + am_b.setUpdated(now); + //rgsImdg.update(am_b); + } + am_f.setUpdated(now); + + //rgsImdg.update(am_f); + log.debug("assets processing [{}#id={}#balance={} | {}#id={}#balance={} | {}#id={}#balance={}] " + + "D**I.size={} D**V.size={}. {}.balance -> {}, {}.balance -> {}", + am_f.getRegistryCode(), am_f.getId(), am_fBalanceForLoging, + am_t.getRegistryCode(), am_t.getId(), am_t.getBalance(), + am_b.getRegistryCode(), am_b.getId(), am_bBalanceForLoging, + d__is.size(), d__vs.size(), + am_b.getRegistryCode(), am_b.getBalance(), + am_f.getRegistryCode(), am_f.getBalance()); + } + + public Collection searchByParams(String account, + String securitySymbol, + Long companyId, + RegistryTradingParams params) { + ImdgPredicateBuilder pb = rgsImdg.predicateBuilder(); + ImdgPredicate d__iPrdct = pb.and( + pb.equals("account", account), + pb.equals("securitySymbol", securitySymbol), + pb.equals("companyId", companyId), + pb.equals("registryStatus", RegistryStatus.PROC.getKey()), + pb.sql(RegistryCodeSqlBuilder.getInstance(params).build()) + ); + return rgsImdg.getCollectionObjectsByPredicate(d__iPrdct); + } + + + //точно будет аналогично и с другими полями + private void safeWrapField(Supplier getter, Consumer setter) { + BigDecimal fieldValue = getter.get(); + setter.accept(safeBD(fieldValue)); + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/CurrencySession.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/CurrencySession.java index 47485eab1..430c63290 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/CurrencySession.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/CurrencySession.java @@ -36,6 +36,7 @@ import ru.spcex.clearing.session.stage.task.FormingPaymentInstructionPayload; import ru.spcex.clearing.session.stage.task.FormingRegistersOnOSPayload; import ru.spcex.clearing.session.stage.task.InclusionToPoolPayload; import ru.spcex.clearing.session.stage.task.InspectionPoolPayload; +import ru.spcex.clearing.session.stage.task.RequirementsAndObligationCreationPayload; import ru.spcex.platform.classes.base.interfaces.ExecutionType; import ru.spcex.platform.enumeration.Section; import ru.spcex.platform.enumeration.SessionStatus; @@ -179,8 +180,13 @@ public class CurrencySession extends AbstractSession implements InitializingBean payload.setSessionId(currSession.getId()); dealsPreparationResult = runStage(TaskType.DealsPrepare, payload, dealsPrepare); } - //stage 2 - runStage(TaskType.RequirementsAndObligationsCreate, dealsPreparationResult.getStageResult(), requirementsAndObligationCreation); + { + //stage 2 + RequirementsAndObligationCreationPayload payload = new RequirementsAndObligationCreationPayload( + dealsPreparationResult.getStageResult(), currSession.getId() + ); + runStage(TaskType.RequirementsAndObligationsCreate, payload, requirementsAndObligationCreation); + } //stage 3 runStage(TaskType.ObligationsAdmission, currSession.getId(), obligationsAdmission); //stage 4 diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/FinalMkrSession.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/FinalMkrSession.java index cd7f7e05f..1b78c208f 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/FinalMkrSession.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/FinalMkrSession.java @@ -1,5 +1,10 @@ package ru.spcex.clearing.session.stage; +import java.time.Instant; +import java.time.LocalDate; +import java.util.Collection; +import java.util.List; +import java.util.function.Supplier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; @@ -12,10 +17,30 @@ import ru.clearing.classes.statics.data.payment.PaymentInstruction; import ru.clearing.classes.statics.data.registry.Registry; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.BaseRequest; -import ru.spcex.clearing.session.stage.impl.*; +import ru.spcex.clearing.session.stage.impl.BalanceRevise; +import ru.spcex.clearing.session.stage.impl.DealsPrepare; +import ru.spcex.clearing.session.stage.impl.EndStageNotification; +import ru.spcex.clearing.session.stage.impl.FinishingSession; +import ru.spcex.clearing.session.stage.impl.FormingPaymentInstructionAssets; +import ru.spcex.clearing.session.stage.impl.FormingPaymentInstructionReturnMkr; +import ru.spcex.clearing.session.stage.impl.FormingRegistersOnOS; +import ru.spcex.clearing.session.stage.impl.InclusionObligations; +import ru.spcex.clearing.session.stage.impl.InspectionObligations; +import ru.spcex.clearing.session.stage.impl.InspectionObligationsDepositReturn; +import ru.spcex.clearing.session.stage.impl.ObligationAdmission; +import ru.spcex.clearing.session.stage.impl.PaymentInfo; +import ru.spcex.clearing.session.stage.impl.RequirementsAndObligationCreation; +import ru.spcex.clearing.session.stage.impl.UnlockResources; import ru.spcex.clearing.session.stage.monitor.SessionMonitor; import ru.spcex.clearing.session.stage.monitor.SessionMonitorFactory; -import ru.spcex.clearing.session.stage.task.*; +import ru.spcex.clearing.session.stage.task.DealsPreparePayload; +import ru.spcex.clearing.session.stage.task.EndStageNotificationPayload; +import ru.spcex.clearing.session.stage.task.FinishingSessionPayload; +import ru.spcex.clearing.session.stage.task.FormingPaymentInstructionPayload; +import ru.spcex.clearing.session.stage.task.FormingRegistersOnOSPayload; +import ru.spcex.clearing.session.stage.task.InclusionToPoolPayload; +import ru.spcex.clearing.session.stage.task.InspectionPoolPayload; +import ru.spcex.clearing.session.stage.task.RequirementsAndObligationCreationPayload; import ru.spcex.platform.classes.base.interfaces.ExecutionType; import ru.spcex.platform.enumeration.RegistryStatus; import ru.spcex.platform.enumeration.Section; @@ -26,12 +51,6 @@ import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; import ru.spcex.platform.utils.enumeration.IMessageResolver; -import java.time.Instant; -import java.time.LocalDate; -import java.util.Collection; -import java.util.List; -import java.util.function.Supplier; - @Service public class FinalMkrSession extends AbstractSession implements InitializingBean { private final Logger log = LoggerFactory.getLogger(getClass()); @@ -179,8 +198,13 @@ public class FinalMkrSession extends AbstractSession implements InitializingBean payload.setSessionId(currSession.getId()); dealsPreparationResult = runStage(TaskType.DealsPrepare, payload, dealsPrepare); } - //stage 2 - runStage(TaskType.RequirementsAndObligationsCreate, dealsPreparationResult.getStageResult(), requirementsAndObligationCreation); + { + //stage 2 + RequirementsAndObligationCreationPayload payload = new RequirementsAndObligationCreationPayload( + dealsPreparationResult.getStageResult(), currSession.getId() + ); + runStage(TaskType.RequirementsAndObligationsCreate, payload, requirementsAndObligationCreation); + } //stage 3 runStage(TaskType.ObligationsAdmission, currSession.getId(), obligationsAdmission); //stage 4 diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/IntermediateMkrSession.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/IntermediateMkrSession.java index c376df3eb..35f20ce72 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/IntermediateMkrSession.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/IntermediateMkrSession.java @@ -1,5 +1,10 @@ package ru.spcex.clearing.session.stage; +import java.time.Instant; +import java.time.LocalDate; +import java.util.Collections; +import java.util.List; +import java.util.function.Supplier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; @@ -11,10 +16,28 @@ import ru.clearing.classes.statics.data.misc.Session; import ru.clearing.classes.statics.data.registry.Registry; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.BaseRequest; -import ru.spcex.clearing.session.stage.impl.*; +import ru.spcex.clearing.session.stage.impl.BalanceRevise; +import ru.spcex.clearing.session.stage.impl.DealsPrepare; +import ru.spcex.clearing.session.stage.impl.EndStageNotification; +import ru.spcex.clearing.session.stage.impl.FinishingSession; +import ru.spcex.clearing.session.stage.impl.FormingPaymentInstructionAssets; +import ru.spcex.clearing.session.stage.impl.FormingRegistersOnOS; +import ru.spcex.clearing.session.stage.impl.InclusionObligations; +import ru.spcex.clearing.session.stage.impl.InspectionObligations; +import ru.spcex.clearing.session.stage.impl.ObligationAdmission; +import ru.spcex.clearing.session.stage.impl.PaymentInfo; +import ru.spcex.clearing.session.stage.impl.RequirementsAndObligationCreation; +import ru.spcex.clearing.session.stage.impl.UnlockResources; import ru.spcex.clearing.session.stage.monitor.SessionMonitor; import ru.spcex.clearing.session.stage.monitor.SessionMonitorFactory; -import ru.spcex.clearing.session.stage.task.*; +import ru.spcex.clearing.session.stage.task.DealsPreparePayload; +import ru.spcex.clearing.session.stage.task.EndStageNotificationPayload; +import ru.spcex.clearing.session.stage.task.FinishingSessionPayload; +import ru.spcex.clearing.session.stage.task.FormingPaymentInstructionPayload; +import ru.spcex.clearing.session.stage.task.FormingRegistersOnOSPayload; +import ru.spcex.clearing.session.stage.task.InclusionToPoolPayload; +import ru.spcex.clearing.session.stage.task.InspectionPoolPayload; +import ru.spcex.clearing.session.stage.task.RequirementsAndObligationCreationPayload; import ru.spcex.platform.classes.base.interfaces.ExecutionType; import ru.spcex.platform.enumeration.RegistryStatus; import ru.spcex.platform.enumeration.Section; @@ -25,12 +48,6 @@ import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; import ru.spcex.platform.utils.enumeration.IMessageResolver; -import java.time.Instant; -import java.time.LocalDate; -import java.util.Collections; -import java.util.List; -import java.util.function.Supplier; - @Service public class IntermediateMkrSession extends AbstractSession implements InitializingBean { private final Logger log = LoggerFactory.getLogger(getClass()); @@ -173,8 +190,13 @@ public class IntermediateMkrSession extends AbstractSession implements Initializ payload.setSessionId(currSession.getId()); dealsPreparationResult = runStage(TaskType.DealsPrepare, payload, dealsPrepare); } - //stage 2 - runStage(TaskType.RequirementsAndObligationsCreate, dealsPreparationResult.getStageResult(), requirementsAndObligationCreation); + { + //stage 2 + RequirementsAndObligationCreationPayload payload = new RequirementsAndObligationCreationPayload( + dealsPreparationResult.getStageResult(), currSession.getId() + ); + runStage(TaskType.RequirementsAndObligationsCreate, payload, requirementsAndObligationCreation); + } //stage 3 runStage(TaskType.ObligationsAdmission, currSession.getId(), obligationsAdmission); //stage 4 diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionB0Session.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionB0Session.java index fe13068f7..c9940200f 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionB0Session.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionB0Session.java @@ -1,5 +1,10 @@ package ru.spcex.clearing.session.stage; +import java.time.Instant; +import java.time.LocalDate; +import java.util.Collection; +import java.util.List; +import java.util.function.Supplier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; @@ -11,10 +16,27 @@ import ru.clearing.classes.statics.data.misc.Session; import ru.clearing.classes.statics.data.payment.PaymentInstruction; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.BaseRequest; -import ru.spcex.clearing.session.stage.impl.*; +import ru.spcex.clearing.session.stage.impl.BalanceRevise; +import ru.spcex.clearing.session.stage.impl.DealsPrepare; +import ru.spcex.clearing.session.stage.impl.EndStageNotification; +import ru.spcex.clearing.session.stage.impl.FinishingSession; +import ru.spcex.clearing.session.stage.impl.FormingPaymentInstructionSecurities; +import ru.spcex.clearing.session.stage.impl.FormingRegistersOnOS; +import ru.spcex.clearing.session.stage.impl.InclusionObligations; +import ru.spcex.clearing.session.stage.impl.InspectionObligations; +import ru.spcex.clearing.session.stage.impl.ObligationAdmission; +import ru.spcex.clearing.session.stage.impl.RequirementsAndObligationCreation; +import ru.spcex.clearing.session.stage.impl.UnlockResources; import ru.spcex.clearing.session.stage.monitor.SessionMonitor; import ru.spcex.clearing.session.stage.monitor.SessionMonitorFactory; -import ru.spcex.clearing.session.stage.task.*; +import ru.spcex.clearing.session.stage.task.DealsPreparePayload; +import ru.spcex.clearing.session.stage.task.EndStageNotificationPayload; +import ru.spcex.clearing.session.stage.task.FinishingSessionPayload; +import ru.spcex.clearing.session.stage.task.FormingPaymentInstructionPayload; +import ru.spcex.clearing.session.stage.task.FormingRegistersOnOSPayload; +import ru.spcex.clearing.session.stage.task.InclusionToPoolPayload; +import ru.spcex.clearing.session.stage.task.InspectionPoolPayload; +import ru.spcex.clearing.session.stage.task.RequirementsAndObligationCreationPayload; import ru.spcex.platform.classes.base.interfaces.ExecutionType; import ru.spcex.platform.enumeration.Section; import ru.spcex.platform.enumeration.SessionStatus; @@ -24,12 +46,6 @@ import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; import ru.spcex.platform.utils.enumeration.IMessageResolver; -import java.time.Instant; -import java.time.LocalDate; -import java.util.Collection; -import java.util.List; -import java.util.function.Supplier; - @Service public class PrimaryAuctionB0Session extends AbstractSession implements InitializingBean { private final Logger log = LoggerFactory.getLogger(getClass()); @@ -165,8 +181,13 @@ public class PrimaryAuctionB0Session extends AbstractSession implements Initiali payload.setSessionId(currSession.getId()); dealsPreparationResult = runStage(TaskType.DealsPrepare, payload, dealsPrepare); } - //stage 2 - runStage(TaskType.RequirementsAndObligationsCreate, dealsPreparationResult.getStageResult(), requirementsAndObligationCreation); + { + //stage 2 + RequirementsAndObligationCreationPayload payload = new RequirementsAndObligationCreationPayload( + dealsPreparationResult.getStageResult(), currSession.getId() + ); + runStage(TaskType.RequirementsAndObligationsCreate, payload, requirementsAndObligationCreation); + } //stage 3 runStage(TaskType.ObligationsAdmission, currSession.getId(), obligationsAdmission); //stage 4 diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionBnSession.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionBnSession.java index 58acc7656..815bcd903 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionBnSession.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionBnSession.java @@ -1,5 +1,10 @@ package ru.spcex.clearing.session.stage; +import java.time.Instant; +import java.time.LocalDate; +import java.util.Collection; +import java.util.List; +import java.util.function.Supplier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; @@ -11,10 +16,27 @@ import ru.clearing.classes.statics.data.misc.Session; import ru.clearing.classes.statics.data.payment.PaymentInstruction; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.BaseRequest; -import ru.spcex.clearing.session.stage.impl.*; +import ru.spcex.clearing.session.stage.impl.BalanceRevise; +import ru.spcex.clearing.session.stage.impl.DealsPrepare; +import ru.spcex.clearing.session.stage.impl.EndStageNotification; +import ru.spcex.clearing.session.stage.impl.FinishingSession; +import ru.spcex.clearing.session.stage.impl.FormingPaymentInstructionSecurities; +import ru.spcex.clearing.session.stage.impl.FormingRegistersOnOS; +import ru.spcex.clearing.session.stage.impl.InclusionObligations; +import ru.spcex.clearing.session.stage.impl.InspectionObligations; +import ru.spcex.clearing.session.stage.impl.ObligationAdmission; +import ru.spcex.clearing.session.stage.impl.RequirementsAndObligationCreation; +import ru.spcex.clearing.session.stage.impl.UnlockResources; import ru.spcex.clearing.session.stage.monitor.SessionMonitor; import ru.spcex.clearing.session.stage.monitor.SessionMonitorFactory; -import ru.spcex.clearing.session.stage.task.*; +import ru.spcex.clearing.session.stage.task.DealsPreparePayload; +import ru.spcex.clearing.session.stage.task.EndStageNotificationPayload; +import ru.spcex.clearing.session.stage.task.FinishingSessionPayload; +import ru.spcex.clearing.session.stage.task.FormingPaymentInstructionPayload; +import ru.spcex.clearing.session.stage.task.FormingRegistersOnOSPayload; +import ru.spcex.clearing.session.stage.task.InclusionToPoolPayload; +import ru.spcex.clearing.session.stage.task.InspectionPoolPayload; +import ru.spcex.clearing.session.stage.task.RequirementsAndObligationCreationPayload; import ru.spcex.platform.classes.base.interfaces.ExecutionType; import ru.spcex.platform.enumeration.Section; import ru.spcex.platform.enumeration.SessionStatus; @@ -24,12 +46,6 @@ import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; import ru.spcex.platform.utils.enumeration.IMessageResolver; -import java.time.Instant; -import java.time.LocalDate; -import java.util.Collection; -import java.util.List; -import java.util.function.Supplier; - @Service public class PrimaryAuctionBnSession extends AbstractSession implements InitializingBean { private final Logger log = LoggerFactory.getLogger(getClass()); @@ -166,8 +182,13 @@ public class PrimaryAuctionBnSession extends AbstractSession implements Initiali payload.setSessionId(currSession.getId()); dealsPreparationResult = runStage(TaskType.DealsPrepare, payload, dealsPrepare); } - //stage 2 - runStage(TaskType.RequirementsAndObligationsCreate, dealsPreparationResult.getStageResult(), requirementsAndObligationCreation); + { + //stage 2 + RequirementsAndObligationCreationPayload payload = new RequirementsAndObligationCreationPayload( + dealsPreparationResult.getStageResult(), currSession.getId() + ); + runStage(TaskType.RequirementsAndObligationsCreate, payload, requirementsAndObligationCreation); + } //stage 3 runStage(TaskType.ObligationsAdmission, currSession.getId(), obligationsAdmission); //stage 4 diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionT0Session.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionT0Session.java index 2cb7e5e4c..b69820f76 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionT0Session.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/PrimaryAuctionT0Session.java @@ -1,5 +1,10 @@ package ru.spcex.clearing.session.stage; +import java.time.Instant; +import java.time.LocalDate; +import java.util.Collection; +import java.util.List; +import java.util.function.Supplier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; @@ -11,10 +16,27 @@ import ru.clearing.classes.statics.data.misc.Session; import ru.clearing.classes.statics.data.payment.PaymentInstruction; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.BaseRequest; -import ru.spcex.clearing.session.stage.impl.*; +import ru.spcex.clearing.session.stage.impl.BalanceRevise; +import ru.spcex.clearing.session.stage.impl.DealsPrepare; +import ru.spcex.clearing.session.stage.impl.EndStageNotification; +import ru.spcex.clearing.session.stage.impl.FinishingSession; +import ru.spcex.clearing.session.stage.impl.FormingPaymentInstructionSecurities; +import ru.spcex.clearing.session.stage.impl.FormingRegistersOnOS; +import ru.spcex.clearing.session.stage.impl.InclusionObligations; +import ru.spcex.clearing.session.stage.impl.InspectionObligations; +import ru.spcex.clearing.session.stage.impl.ObligationAdmission; +import ru.spcex.clearing.session.stage.impl.RequirementsAndObligationCreation; +import ru.spcex.clearing.session.stage.impl.UnlockResources; import ru.spcex.clearing.session.stage.monitor.SessionMonitor; import ru.spcex.clearing.session.stage.monitor.SessionMonitorFactory; -import ru.spcex.clearing.session.stage.task.*; +import ru.spcex.clearing.session.stage.task.DealsPreparePayload; +import ru.spcex.clearing.session.stage.task.EndStageNotificationPayload; +import ru.spcex.clearing.session.stage.task.FinishingSessionPayload; +import ru.spcex.clearing.session.stage.task.FormingPaymentInstructionPayload; +import ru.spcex.clearing.session.stage.task.FormingRegistersOnOSPayload; +import ru.spcex.clearing.session.stage.task.InclusionToPoolPayload; +import ru.spcex.clearing.session.stage.task.InspectionPoolPayload; +import ru.spcex.clearing.session.stage.task.RequirementsAndObligationCreationPayload; import ru.spcex.platform.classes.base.interfaces.ExecutionType; import ru.spcex.platform.enumeration.Section; import ru.spcex.platform.enumeration.SessionStatus; @@ -24,12 +46,6 @@ import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; import ru.spcex.platform.utils.enumeration.IMessageResolver; -import java.time.Instant; -import java.time.LocalDate; -import java.util.Collection; -import java.util.List; -import java.util.function.Supplier; - @Service public class PrimaryAuctionT0Session extends AbstractSession implements InitializingBean { private final Logger log = LoggerFactory.getLogger(getClass()); @@ -166,8 +182,13 @@ public class PrimaryAuctionT0Session extends AbstractSession implements Initiali payload.setSessionId(currSession.getId()); dealsPreparationResult = runStage(TaskType.DealsPrepare, payload, dealsPrepare); } - //stage 2 - runStage(TaskType.RequirementsAndObligationsCreate, dealsPreparationResult.getStageResult(), requirementsAndObligationCreation); + { + //stage 2 + RequirementsAndObligationCreationPayload payload = new RequirementsAndObligationCreationPayload( + dealsPreparationResult.getStageResult(), currSession.getId() + ); + runStage(TaskType.RequirementsAndObligationsCreate, payload, requirementsAndObligationCreation); + } //stage 3 runStage(TaskType.ObligationsAdmission, currSession.getId(), obligationsAdmission); //stage 4 diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/SecondaryAuctionT0Session.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/SecondaryAuctionT0Session.java index 29bb87216..3ca79e566 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/SecondaryAuctionT0Session.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/SecondaryAuctionT0Session.java @@ -1,5 +1,9 @@ package ru.spcex.clearing.session.stage; +import java.time.Instant; +import java.time.LocalDate; +import java.util.List; +import java.util.function.Supplier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; @@ -10,10 +14,28 @@ import ru.clearing.classes.statics.data.execution.ExecutionFond; import ru.clearing.classes.statics.data.misc.Session; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.BaseRequest; -import ru.spcex.clearing.session.stage.impl.*; +import ru.spcex.clearing.session.stage.impl.BalanceRevise; +import ru.spcex.clearing.session.stage.impl.DealsPrepare; +import ru.spcex.clearing.session.stage.impl.EndStageNotification; +import ru.spcex.clearing.session.stage.impl.FinishingSession; +import ru.spcex.clearing.session.stage.impl.FormingPaymentInstructionAssets; +import ru.spcex.clearing.session.stage.impl.FormingRegistersOnOS; +import ru.spcex.clearing.session.stage.impl.InclusionObligations; +import ru.spcex.clearing.session.stage.impl.InspectionObligationsV2; +import ru.spcex.clearing.session.stage.impl.ObligationAdmission; +import ru.spcex.clearing.session.stage.impl.PaymentInfo; +import ru.spcex.clearing.session.stage.impl.RequirementsAndObligationCreation; +import ru.spcex.clearing.session.stage.impl.UnlockResources; import ru.spcex.clearing.session.stage.monitor.SessionMonitor; import ru.spcex.clearing.session.stage.monitor.SessionMonitorFactory; -import ru.spcex.clearing.session.stage.task.*; +import ru.spcex.clearing.session.stage.task.DealsPreparePayload; +import ru.spcex.clearing.session.stage.task.EndStageNotificationPayload; +import ru.spcex.clearing.session.stage.task.FinishingSessionPayload; +import ru.spcex.clearing.session.stage.task.FormingPaymentInstructionPayload; +import ru.spcex.clearing.session.stage.task.FormingRegistersOnOSPayload; +import ru.spcex.clearing.session.stage.task.InclusionToPoolPayload; +import ru.spcex.clearing.session.stage.task.InspectionPoolPayload; +import ru.spcex.clearing.session.stage.task.RequirementsAndObligationCreationPayload; import ru.spcex.platform.classes.base.interfaces.ExecutionType; import ru.spcex.platform.enumeration.Section; import ru.spcex.platform.enumeration.SessionStatus; @@ -23,11 +45,6 @@ import ru.spcex.platform.imdg.api.ImdgProvider; import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder; import ru.spcex.platform.utils.enumeration.IMessageResolver; -import java.time.Instant; -import java.time.LocalDate; -import java.util.List; -import java.util.function.Supplier; - @Service //todo эта сессия public class SecondaryAuctionT0Session extends AbstractSession implements InitializingBean { @@ -38,7 +55,7 @@ public class SecondaryAuctionT0Session extends AbstractSession implements Initia private final ObligationAdmission obligationsAdmission; private final InclusionObligations inclusionObligations; - private final InspectionObligations inspectionObligations; + private final InspectionObligationsV2 inspectionObligations; private final FormingRegistersOnOS formingRegistersOnOS; private final FormingPaymentInstructionAssets formingPaymentInstructionAssets; private final UnlockResources unlockResources; @@ -66,7 +83,7 @@ public class SecondaryAuctionT0Session extends AbstractSession implements Initia FinishingSession finishingSession, EndStageNotification endStageNotification, IMessageResolver messageResolver, - InspectionObligations inspectionObligations, + InspectionObligationsV2 inspectionObligations, @Qualifier("marketCodesForT0") Supplier> marketCodes) { super(imdgProvider, messageResolver); this.balanceRevise = balanceRevise; @@ -160,8 +177,13 @@ public class SecondaryAuctionT0Session extends AbstractSession implements Initia payload.setSessionId(currSession.getId()); dealsPreparationResult = runStage(TaskType.DealsPrepare, payload, dealsPrepare); } - //stage 2 - runStage(TaskType.RequirementsAndObligationsCreate, dealsPreparationResult.getStageResult(), requirementsAndObligationCreation); + { + //stage 2 + RequirementsAndObligationCreationPayload payload = new RequirementsAndObligationCreationPayload( + dealsPreparationResult.getStageResult(), currSession.getId() + ); + runStage(TaskType.RequirementsAndObligationsCreate, payload, requirementsAndObligationCreation); + } //stage 3 runStage(TaskType.ObligationsAdmission, currSession.getId(), obligationsAdmission); //stage 4 diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/UnitedSession.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/UnitedSession.java index a6372e482..dcdb06879 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/UnitedSession.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/UnitedSession.java @@ -120,6 +120,8 @@ public class UnitedSession extends AbstractSession implements InitializingBean { ImdgPredicateBuilder pb = executionFondImdg.predicateBuilder(); dealsPrepareCurrency.addExecutionFondCondition(pb.regex("settlementCode", "^T0.*$")); dealsPrepareCurrency.addExecutionFondCondition(pb.in("market", marketCodesCurr.get().toArray(new String[0]))); + //dealsPrepareCurrency.addExecutionCurrencyCondition(pb.regex("settlementCode", "^T0.*$")); + //dealsPrepareCurrency.addExecutionCurrencyCondition(pb.in("market", marketCodesCurr.get().toArray(new String[0]))); dealsPrepareTRDT.searchForExecutions(ExecutionType.ExecutionFond); ImdgPredicateBuilder execFondPb = executionFondImdg.predicateBuilder(); @@ -209,7 +211,7 @@ public class UnitedSession extends AbstractSession implements InitializingBean { //stage 2 { RequirementsAndObligationCreationCompoundPayload p; - p = RequirementsAndObligationCreationCompoundPayload.create(dealsPreparationResult.getStageResult()); + p = RequirementsAndObligationCreationCompoundPayload.create(dealsPreparationResult.getStageResult(), currSession.getId()); runStage(TaskType.RequirementsAndObligationsCreate, p, requirementsAndObligationCreation); } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/IRegistryBuilder.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/IRegistryBuilder.java index 3d8d44661..ae53d98e6 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/IRegistryBuilder.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/IRegistryBuilder.java @@ -1,9 +1,19 @@ package ru.spcex.clearing.session.stage.impl; +import ru.clearing.classes.statics.data.account.Account; +import ru.clearing.classes.statics.data.account.ClearingAccount; +import ru.clearing.classes.statics.data.account.DepoAccount; +import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.execution.ExecutionCommon; +import ru.clearing.classes.statics.data.misc.Currency; +import ru.clearing.classes.statics.data.misc.Session; import ru.clearing.classes.statics.data.registry.Registry; +import ru.clearing.classes.statics.data.registry.TradingClearingRegistry; +import ru.clearing.classes.statics.data.security.Security; import ru.spcex.platform.enumeration.RegistryDesignation; import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2; +import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2ById; public interface IRegistryBuilder { @@ -12,4 +22,12 @@ public interface IRegistryBuilder { IRegistryBuilder registryDesignation(RegistryDesignation registryDesignation); IRegistryBuilder returnDeposit(boolean returnDeposit); Registry build(); + default IRegistryBuilder cmpCash(CashV2 cmpCash) {return this;} + default IRegistryBuilder tcrCash(CashV2 tcrCash) {return this;}//CashV2 tcrCash; + default IRegistryBuilder accCash(CashV2 accCash) {return this;}//CashV2 accCash; + default IRegistryBuilder dpAccCash(CashV2 dpAccCash) {return this;}//CashV2 dpAccCash; + default IRegistryBuilder scrtCash(CashV2ById scrtCash) {return this;}//CashV2 scrtCash; + default IRegistryBuilder currCash(CashV2 currCash) {return this;}//CashV2 currCash; + default IRegistryBuilder clrAccCash(CashV2 clrAccCash) {return this;}//CashV2 clrAccCash; + default IRegistryBuilder ssnCash(CashV2 ssnCash) {return this;}//CashV2 clrAccCash; } 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 81d73d088..f4b1d26a2 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 @@ -21,6 +21,7 @@ import ru.clearing.classes.statics.data.registry.Registry; import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.error.RgsError; import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.service.cash.RegistryCash; import ru.spcex.clearing.service.integration.GatewayRequestCreator; import ru.spcex.clearing.service.registry.AssetTBFProcessing; import ru.spcex.clearing.service.registry.RegistryManager; @@ -91,12 +92,18 @@ public class InspectionObligations implements ISessionStage { InspectionPoolPayload payload = (InspectionPoolPayload) task.getData(); switch (task.getTaskType()) { case InspectionObligations -> { - return inspectionObligations(payload.getSessionId()); + try { + return inspectionObligations(payload.getSessionId()); + } finally { + rgsCash.clear(); + } } default -> throw new IllegalStateException("Unknown task type: " + task.getTaskType()); } } + RegistryCash rgsCash = new RegistryCash(); + private StageResult inspectionObligations(Long sessionId) { String sqlCondition = String.format("(%s) and registryStatus = '%s'", RegistryCodeSqlBuilder.getInstance(OS_T, OM_T, TS_T, TM_T).build(), @@ -141,7 +148,13 @@ public class InspectionObligations implements ISessionStage { } String sqlAssetRegistryCondition = searchAssetsByObligationSql(obligation); log.debug("search asset by registry.id={} sql {}", obligation.getId(), sqlAssetRegistryCondition); - Registry asset = registryImdg.getFirstObjectBySQL(sqlAssetRegistryCondition); + Registry asset = rgsCash + .getBy(obligation) + .orElseGet(() -> { + Registry newVal = registryImdg.getFirstObjectBySQL(sqlAssetRegistryCondition); + rgsCash.store(newVal); + return newVal; + }); if (asset == null) { log.warn("Not found asset by registry.id={}", obligation.getId()); isUncovered = true; @@ -171,7 +184,13 @@ public class InspectionObligations implements ISessionStage { if (Section.MKR.equalsByKey(rgs.getSection()) && mOrS.equals(RegistryInstrumentType.S)) { continue; } - Optional a__t = assets.searchByTcrCompanyAccount(rgs, A__T.type(mOrS)); + Optional a__t = rgsCash + .getBy(rgs, A__T.type(mOrS)) + .or(() -> { + Optional newVal = assets.searchByTcrCompanyAccount(rgs, A__T.type(mOrS)); + newVal.ifPresent(r -> rgsCash.store(r)); + return newVal; + }); if (a__t.isEmpty()) { log.debug("groupId {}, {}.id={} - A**T not found. settings FAIL to group", entry.getKey(), rgs.getRegistryCode(), rgs.getId()); @@ -202,13 +221,33 @@ public class InspectionObligations implements ISessionStage { { RegistryInstrumentType mOrS = IEnumKey.getEnumByKey(RegistryInstrumentType.class, registry.getRegistryInstrumentType()); if (mOrS == null) continue; - Optional a__t = assets.searchByTcrCompanyAccount(registry, A__T.type(mOrS)); - Optional a__b = a__t.map(a__tFound -> assets - .searchByTcrCompanyAccount(a__tFound, A__B.type(mOrS)) - .orElseGet(() -> copyB(a__tFound))); - Optional a__f = a__t.map(a__tFound -> assets - .searchByTcrCompanyAccount(a__tFound, A__F.type(mOrS)) - .orElseGet(() -> copyF(a__tFound))); + Optional a__t = rgsCash + .getBy(registry, A__T.type(mOrS)) + .or(() -> { + Optional newVal = assets.searchByTcrCompanyAccount(registry, A__T.type(mOrS)); + newVal.ifPresent(r -> rgsCash.store(r)); + return newVal; + }); + Optional a__b = rgsCash + .getBy(a__t.orElse(null), A__B.type(mOrS)) + .or(() -> { + if (a__t.isEmpty()) return Optional.empty(); + Registry newVal = assets.searchByTcrCompanyAccount( + a__t.get(), A__B.type(mOrS) + ).orElseGet(() -> copyB(a__t.get())); + rgsCash.store(newVal); + return Optional.of(newVal); + }); + Optional a__f = rgsCash + .getBy(a__t.orElse(null), A__F.type(mOrS)) + .or(() -> { + if (a__t.isEmpty()) return Optional.empty(); + Registry newVal = assets.searchByTcrCompanyAccount( + a__t.get(), A__F.type(mOrS) + ).orElseGet(() -> copyB(a__t.get())); + rgsCash.store(newVal); + return Optional.of(newVal); + }); log.debug("registry {}.id={}: {}", registry.getRegistryCode(), registry.getId(), a__t.map(r -> "A**T.id=%d/A**B.id=%d/A**F.id=%d" .formatted(a__t.get().getId(), a__b.get().getId(), a__f.get().getId())) diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InspectionObligationsV2.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InspectionObligationsV2.java new file mode 100644 index 000000000..7a1837430 --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/InspectionObligationsV2.java @@ -0,0 +1,420 @@ +package ru.spcex.clearing.session.stage.impl; + +import java.math.BigDecimal; +import java.time.Instant; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; +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.stereotype.Service; +import ru.clearing.classes.statics.data.registry.Registry; +import ru.spcex.clearing.error.ClearingError; +import ru.spcex.clearing.error.RgsError; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.service.cash.impl.RegistryCashA__F; +import ru.spcex.clearing.service.cash.impl.RegistryCashAssetCash; +import ru.spcex.clearing.service.cash.impl.RegistryCashD___; +import ru.spcex.clearing.service.integration.GatewayRequestCreator; +import ru.spcex.clearing.service.registry.AssetTBFProcessing; +import ru.spcex.clearing.service.registry.AssetTBFProcessingCashing; +import ru.spcex.clearing.service.registry.RegistryManager; +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.clearing.session.stage.util.RegistryUtil; +import ru.spcex.platform.enumeration.RegistryCapacity; +import ru.spcex.platform.enumeration.RegistryDesignation; +import ru.spcex.platform.enumeration.RegistryInstrumentType; +import ru.spcex.platform.enumeration.RegistryStatus; +import ru.spcex.platform.enumeration.RegistryTradingParams; +import static ru.spcex.platform.enumeration.RegistryTradingParams.*; +import ru.spcex.platform.enumeration.RegistryUnit; +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; +import ru.spcex.platform.imdg.api.predicate.specific.RegistryCodeSqlBuilder; +import ru.spcex.platform.utils.collection.Pair; +import ru.spcex.platform.utils.enumeration.EnumMessage; +import ru.spcex.platform.utils.enumeration.IEnumKey; +import ru.spcex.platform.utils.enumeration.IMessageResolver; +import ru.spcex.platform.utils.enumeration.SimpleMessageResolver; +import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD; + + +@Service +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class InspectionObligationsV2 implements ISessionStage { + private final Logger log = LoggerFactory.getLogger(getClass()); + private final Imdg registryImdg; + private final RegistryManager registryManager; + private final IMessageResolver msgResolver = new SimpleMessageResolver(); + private SessionType sessionType; + private Section section; + private final AssetTBFProcessing assets; + private final AssetTBFProcessingCashing assetsCashing; + private final GatewayRequester gateway; + private final TradingTimeService tradingTimeService; + private final PlanBalanceCalc planBalanceCalc; + + @Autowired + public InspectionObligationsV2(ImdgProvider imdgProvider, + RegistryManager registryManager, + AssetTBFProcessing assets, + 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); + this.assetsCashing = new AssetTBFProcessingCashing(imdgProvider, d___Cash); + } + + public void setSessionType(SessionType sessionType) { + this.sessionType = sessionType; + } + + public void setSection(Section section) { + this.section = section; + } + + @Override + public StageResult submit(Task task) { + InspectionPoolPayload payload = (InspectionPoolPayload) task.getData(); + switch (task.getTaskType()) { + case InspectionObligations -> { + try { + return inspectionObligations(payload.getSessionId()); + } finally { + a___Cash.clear(); + a__fCash.clear(); + d___Cash.clear(); + } + } + default -> throw new IllegalStateException("Unknown task type: " + task.getTaskType()); + } + } + + private final RegistryCashAssetCash a___Cash = new RegistryCashAssetCash("[all assets]"); + private final RegistryCashA__F a__fCash = new RegistryCashA__F("[A__F only]"); + private final RegistryCashD___ d___Cash = new RegistryCashD___("[D__I/V]"); + + + 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()); + + Collection registriesToProcess = registryImdg.getCollectionObjectsBySQL(sqlCondition); + List>> registriesByGroupSorted = registriesToProcess.stream() + .collect(Collectors.groupingBy(Registry::getGroupId)) + .entrySet() + .stream() + .sorted((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); + }) + .toList(); + + List assetsToUpdate = new ArrayList<>(); + log.info("found {} ({} groups) registries by sql: {}", registriesToProcess.size(), registriesByGroupSorted.size(), sqlCondition); + GROUP: + for (Map.Entry> entry : registriesByGroupSorted) { + List group = entry.getValue(); + + List obligationsInGroup = group.stream().filter(registry -> + IEnumKey.getEnumByKey(RegistryDesignation.class, registry.getRegistryDesignation()) == RegistryDesignation.O).toList(); + log.debug("Find {} obligation with ids: {} in group: {}", obligationsInGroup.size(), + obligationsInGroup.stream() + .map(Registry::getId).collect(Collectors.toList()), + entry.getKey()); + boolean isUncovered = false; + List checkResults = new ArrayList<>(); + for (Registry obligation : obligationsInGroup) { + if ((SessionType.FINL.equals(sessionType) || SessionType.UNIT.equals(sessionType) || SessionType.MEDM.equals(sessionType)) && RegistryInstrumentType.S.equalsByKey(obligation.getRegistryInstrumentType())) { + checkResults.add(new CheckResult(obligation, false)); + continue; + } + String sqlAssetRegistryCondition = searchAssetsByObligationSql(obligation); + log.debug("search asset by registry.id={} sql {}", obligation.getId(), sqlAssetRegistryCondition); + Registry asset = a__fCash.getOrFind(obligation, () -> registryImdg.getFirstObjectBySQL(sqlAssetRegistryCondition)); + if (asset == null) { + log.warn("Not found asset by registry.id={}", obligation.getId()); + isUncovered = true; + } else if (obligation.getBalance().compareTo(asset.getBalance()) > 0) { + log.warn("groupId: {}: {}", obligation.getGroupId(), + msgResolver.resolve(new EnumMessage(ClearingError.InsecurityObligation, obligation.getCompanyId()))); + isUncovered = true; + } + checkResults.add(new CheckResult(obligation, isUncovered)); + isUncovered = false; + } + + Optional omt = group.stream().filter(rgs -> RegistryManager.equalsByCode(OM_T, rgs)).findFirst(); + for (Registry rgs : group) { + Runnable failGroup = () -> Stream.concat(group.stream(), getRefundDateRgsIfPresent(group).stream()) + .forEach(registry -> { + registry.setComment(msgResolver.resolve(RgsError.A__tNotFound)); + updateRegistryStatus(registry, RegistryStatus.FAIL); + }); + RegistryInstrumentType mOrS = IEnumKey.getEnumByKey(RegistryInstrumentType.class, rgs.getRegistryInstrumentType()); + if (mOrS == null) { + log.error("RegistryInstrumentType is null for groupId {} {}.id={}", entry.getKey(), + rgs.getRegistryCode(), rgs.getId()); + failGroup.run(); + continue; + } + if (Section.MKR.equalsByKey(rgs.getSection()) && mOrS.equals(RegistryInstrumentType.S)) { + continue; + } + Optional a__t = a___Cash.getOrFindO(rgs, A__T.type(mOrS), () -> + assets.searchByTcrCompanyAccount(rgs, A__T.type(mOrS))); + if (a__t.isEmpty()) { + log.debug("groupId {}, {}.id={} - A**T not found. settings FAIL to group", + entry.getKey(), rgs.getRegistryCode(), rgs.getId()); + failGroup.run(); + continue GROUP; + } + } + if (SessionType.FINL.equals(sessionType) + && omt.isPresent() + && checkResults.stream().noneMatch(checkResult -> checkResult.isUncovered) + && tradingTimeService.isTradingTime()) { + Optional gatewayReceived = gateway.gatewayRequestAndWait(() -> GatewayRequestCreator.from(omt.get())); + if (gatewayReceived.isEmpty()) { + log.error("Gateway not received response for groupId: {}. ", entry.getKey()); + } + if (!gatewayReceived.orElse(false)) { + checkResults.stream() + .filter(chk -> chk.registry().getId().equals(omt.get().getId())) + .findFirst() + .ifPresent(chk -> chk.isUncovered = true); + } + } + defineStatusAndUpdateRegistry(checkResults, group); + if (checkResults.stream().noneMatch(checkResult -> checkResult.isUncovered)) { + Instant now = Instant.now(); + //по каждому регистру OM*T, TM*T, OS*T, TS*T из одной группы + for (Registry registry : group) {//TODO CLRNWORM проверка на пустой blockedRegistry + { + RegistryInstrumentType mOrS = IEnumKey.getEnumByKey(RegistryInstrumentType.class, registry.getRegistryInstrumentType()); + if (mOrS == null) continue; + Optional a__t = a___Cash.getOrFindO(registry, A__T.type(mOrS), () + -> assets.searchByTcrCompanyAccount(registry, A__T.type(mOrS))); + Optional a__b = a__t.flatMap(a__tFound -> a___Cash.getOrFind( + a__tFound, + A__B.type(mOrS), + () -> assets + .searchByTcrCompanyAccount(a__tFound, A__B.type(mOrS)).orElseGet(() -> copyB(a__tFound)))); +// Optional a__b = a__t.map(a__tFound -> assets +// .searchByTcrCompanyAccount(a__tFound, A__B.type(mOrS)) +// .orElseGet(() -> copyB(a__tFound))); + Optional a__f = a__t.flatMap(a__tFound -> a___Cash.getOrFind( + a__tFound, + A__F.type(mOrS), + () -> assets + .searchByTcrCompanyAccount(a__tFound, A__F.type(mOrS)).orElseGet(() -> copyF(a__tFound)))); +// Optional a__f = a__t.map(a__tFound -> assets +// .searchByTcrCompanyAccount(a__tFound, A__F.type(mOrS)) +// .orElseGet(() -> copyF(a__tFound))); + log.debug("registry {}.id={}: {}", registry.getRegistryCode(), registry.getId(), + a__t.map(r -> "A**T.id=%d/A**B.id=%d/A**F.id=%d" + .formatted(a__t.get().getId(), a__b.get().getId(), a__f.get().getId())) + .orElse("A**T/A**B/A**F not found")); + if (a__t.isPresent()) { + BigDecimal amount = safeBD(registry.getBalance()); + if (IEnumKey.getEnumByKey(RegistryDesignation.class, registry.getRegistryDesignation()) == RegistryDesignation.O) { + amount = amount.negate(); + } else if (IEnumKey.getEnumByKey(RegistryDesignation.class, registry.getRegistryDesignation()) == RegistryDesignation.T) { + amount = amount; + } + a__b.get().setSessionId(sessionId); + assetsCashing.process(a__b.get(), a__t.get(), a__f.get(), amount); + assetsToUpdate.add(a__b.get()); + assetsToUpdate.add(a__f.get()); + } + } + } + } + } + for (Registry registry : assetsToUpdate) { + if (registry.getId() != null) { + registryImdg.update(registry); + } else { + registryImdg.insert(registry); + } + } + + planBalanceCalc.stageRevision2(sessionId); + + return new StageResult(null, true); + } + + private String searchAssetsByObligationSql(Registry obligation) { + RegistryTradingParams counterRegistryTradingParams = null; + if (IEnumKey.getEnumByKey(RegistryInstrumentType.class, obligation.getRegistryInstrumentType()) == RegistryInstrumentType.S) { + counterRegistryTradingParams = new RegistryTradingParams(RegistryDesignation.A, + RegistryInstrumentType.S, + null, + RegistryUnit.F); + } else if (IEnumKey.getEnumByKey(RegistryInstrumentType.class, obligation.getRegistryInstrumentType()) == RegistryInstrumentType.M) { + counterRegistryTradingParams = new RegistryTradingParams(RegistryDesignation.A, + RegistryInstrumentType.M, + null, + RegistryUnit.F); + } + + return String.format("%s and " + + "tradingClearingRegistryId = '%s' and " + + "securitySymbol = '%s' and " + + "companyId = %d", + RegistryCodeSqlBuilder.getInstance(counterRegistryTradingParams).build(), + obligation.getTradingClearingRegistryId(), + obligation.getSecuritySymbol(), + obligation.getCompanyId()); + } + + private Registry copyF(Registry rgs) { + Registry rgsF = rgs.clone(); + RegistryManager.zeroState(rgsF); + rgsF.setRegistryUnit(RegistryUnit.F.getKey()); + rgsF.setRegistryCode(RegistryUtil.clearingCode(rgsF)); + registryImdg.insert(rgsF); + log.debug("created {}.id={} by {}.id={}", rgsF.getRegistryCode(), rgsF.getId(), rgs.getRegistryCode(), rgs.getId()); + return rgsF; + } + + private Registry copyB(Registry rgs) { + Registry rgsB = rgs.clone(); + RegistryManager.zeroState(rgsB); + rgsB.setRegistryUnit(RegistryUnit.B.getKey()); + rgsB.setRegistryCode(RegistryUtil.clearingCode(rgsB)); + registryImdg.insert(rgsB); + log.debug("created {}.id={} by {}.id={}", rgsB.getRegistryCode(), rgsB.getId(), rgs.getRegistryCode(), rgs.getId()); + return rgsB; + } + + private void defineStatusAndUpdateRegistry(List checkResults, List registries) { + boolean isOneUncovered = checkResults.stream().anyMatch(checkResult -> checkResult.isUncovered); + log.debug("groupId {}, uncovered: {}", registries.stream().findFirst().map(Registry::getGroupId).orElse(null), isOneUncovered); + String commentErr = msgResolver.resolve(ClearingError.InsecurityObligation, checkResults.stream() + .filter(chk -> chk.isUncovered) + .map(chk -> chk.registry.getCompanyId()) + .findFirst().orElse(null)); + + if (isOneUncovered) { + for (CheckResult checkResult : checkResults) { + Optional tRegistryWithSameCompany = registries.stream().filter(registry -> + registry.getCompanyId().equals(checkResult.registry.getCompanyId()) && + !registry.getRegistryDesignation().equals(checkResult.registry.getRegistryDesignation()) + ).findFirst(); + checkResult.registry.setComment(commentErr); + if (checkResult.isUncovered) { + updateRegistryStatus(checkResult.registry, uncvStatus()); + tRegistryWithSameCompany.ifPresent(registry -> updateRegistryStatus(registry, failStatus())); + } else { + updateRegistryStatus(checkResult.registry, failStatus()); + tRegistryWithSameCompany.ifPresent(registry -> updateRegistryStatus(registry, failStatus())); + } + } + //проверяем есть ли второй день для сделки (он не входит в пул, поэтому ищем отдельно) + getRefundDateRgsIfPresent(registries).forEach(rgs -> updateRegistryStatus(rgs, RegistryStatus.FAIL)); + } else { + registries.forEach(registry -> updateRegistryStatus(registry, RegistryStatus.OK)); + } + } + + private Collection getRefundDateRgsIfPresent(List registries) { + if (registries.stream().anyMatch(rgs -> rgs.getRefundDate() != null) && !SessionType.MEDM.equals(sessionType)) { + Optional> groupIdAndSettleDate = registries.stream() + .map(rgs -> new Pair<>(rgs.getGroupId(), rgs.getSettlementDate())) + .filter(pair -> pair.getFirst() != null) + .filter(pair -> pair.getSecond() != null) + .findFirst(); + if (groupIdAndSettleDate.isEmpty()) { + return Collections.emptyList(); + } + ImdgPredicateBuilder pb = registryImdg.predicateBuilder(); + return registryImdg.getCollectionObjectsByPredicate( + pb.and( + pb.equals("groupId", groupIdAndSettleDate.get().getFirst()), + pb.not(pb.equals("settlementDate", groupIdAndSettleDate.get().getSecond())) + ) + ); + } else return Collections.emptyList(); + } + + private void updateRegistryStatus(Registry registry, RegistryStatus registryStatus) { + log.debug("Update registry.id: {} to {}", registry.getId(), registryStatus.getKey()); + registry.setRegistryStatus(registryStatus.getKey()); + registry.setUpdated(Instant.now()); + registryImdg.update(registry); + } + + private static final class CheckResult { + private final Registry registry; + private boolean isUncovered; + + private CheckResult(Registry registry, boolean isUncovered) { + this.registry = registry; + this.isUncovered = isUncovered; + } + + public Registry registry() { + return registry; + } + + public boolean isUncovered() { + return isUncovered; + } + } + + private RegistryStatus uncvStatus() { + if (SessionType.MEDM.equals(sessionType)) { + return RegistryStatus.MNG; + } else { + return RegistryStatus.UNCV; + } + } + + private RegistryStatus failStatus() { + if (SessionType.MEDM.equals(sessionType)) { + return RegistryStatus.MNG; + } else { + return RegistryStatus.FAIL; + } + } + + private static boolean equalByRgs(RegistryTradingParams code, Registry rgs) { + return code.equalByRegistry( + IEnumKey.getEnumByKey(RegistryDesignation.class, rgs.getRegistryDesignation()), + IEnumKey.getEnumByKey(RegistryInstrumentType.class, rgs.getRegistryInstrumentType()), + IEnumKey.getEnumByKey(RegistryCapacity.class, rgs.getRegistryCapacity()), + IEnumKey.getEnumByKey(RegistryUnit.class, rgs.getRegistryUnit()) + ); + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/RegistryFondBuilder.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/RegistryFondBuilder.java index 9a62c75f6..3fc948348 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/RegistryFondBuilder.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/RegistryFondBuilder.java @@ -4,7 +4,6 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.time.Instant; import java.time.LocalDate; -import java.util.Map; import ru.clearing.classes.statics.data.account.Account; import ru.clearing.classes.statics.data.account.ClearingAccount; import ru.clearing.classes.statics.data.account.DepoAccount; @@ -18,6 +17,8 @@ import ru.clearing.classes.statics.data.misc.Session; import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.registry.TradingClearingRegistry; import ru.clearing.classes.statics.data.security.Security; +import ru.spcex.clearing.component.predicate.cash.account.AccountIdCashingPredicate; +import ru.spcex.clearing.component.predicate.cash.currency.CurrencyCodePredicate; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.session.stage.util.RegistryUtil; import ru.spcex.platform.classes.base.interfaces.ExecutionType; @@ -35,10 +36,22 @@ import ru.spcex.platform.enumeration.Section; import ru.spcex.platform.enumeration.Side; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; import ru.spcex.platform.imdg.api.predicate.specific.SecuritySelector; +import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2; +import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2ById; import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD; public class RegistryFondBuilder implements IRegistryBuilder { + CashV2 cmpCash; + CashV2 ssnCash; + CashV2 tcrCash; + CashV2 accCash; + CashV2 dpAccCash; + CashV2ById scrtCash; + CashV2 currCash; + CashV2 clrAccCash; + private Imdg companyImdg; private Imdg tradingClearingRegistryImdg; private Imdg accountImdg; @@ -61,19 +74,65 @@ public class RegistryFondBuilder implements IRegistryBuilder { @Override public RegistryFondBuilder imdg(ImdgProvider imdgProvider) { - this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class); - this.tradingClearingRegistryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class); - this.accountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class); - this.marketImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Market, Market.class); - this.sessionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Session, Session.class); - this.clearingAccountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingAccount, ClearingAccount.class); - this.depoAccountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_DepoAccount, DepoAccount.class); - this.informationAccountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_InformationAccount, InformationAccount.class); - this.currencyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Currency, Currency.class); + this.companyImdg = imdgProvider.getCashingImdg(IMDGDistributedNames.Map_Company, Company.class, cmpCash); + this.tradingClearingRegistryImdg = imdgProvider.getCashingImdg(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class, tcrCash); + this.accountImdg = imdgProvider.getCashingImdg(IMDGDistributedNames.Map_Account, Account.class, accCash); + this.sessionImdg = imdgProvider.getCashingImdg(IMDGDistributedNames.Map_Session, Session.class, ssnCash); + this.clearingAccountImdg = imdgProvider.getCashingImdg(IMDGDistributedNames.Map_ClearingAccount, ClearingAccount.class, null); + this.depoAccountImdg = imdgProvider.getCashingImdg(IMDGDistributedNames.Map_DepoAccount, DepoAccount.class, null); + this.currencyImdg = imdgProvider.getCashingImdg(IMDGDistributedNames.Map_Currency, Currency.class, null); this.scrSlctr = new SecuritySelector<>(imdgProvider, Security.class); return this; } + @Override + public IRegistryBuilder cmpCash(CashV2 cmpCash) { + this.cmpCash = cmpCash; + return this; + } + + @Override + public IRegistryBuilder tcrCash(CashV2 tcrCash) { + this.tcrCash = tcrCash; + return this; + } + + @Override + public IRegistryBuilder accCash(CashV2 accCash) { + this.accCash = accCash; + return this; + } + + @Override + public IRegistryBuilder dpAccCash(CashV2 dpAccCash) { + this.dpAccCash = dpAccCash; + return this; + } + + @Override + public IRegistryBuilder scrtCash(CashV2ById scrtCash) { + this.scrtCash = scrtCash; + return this; + } + + @Override + public IRegistryBuilder currCash(CashV2 currCash) { + this.currCash = currCash; + return this; + } + + @Override + public IRegistryBuilder clrAccCash(CashV2 clrAccCash) { + this.clrAccCash = clrAccCash; + return this; + } + + @Override + public IRegistryBuilder ssnCash(CashV2 ssnCash) { + this.ssnCash = ssnCash; + return this; + } + @Override public RegistryFondBuilder exec(ExecutionCommon exec) { this.exec = exec; @@ -118,7 +177,10 @@ public class RegistryFondBuilder implements IRegistryBuilder { } reg.setRegistryInstrumentType(RegistryInstrumentType.M.getKey()); reg.setBalanceDimension(BalanceDimension.MONY.getKey()); //fixme add second leg code branch - Currency currency = currencyImdg.getFirstObjectByFieldValues(Map.of("currencyCode", exec.getSettlementCurrency())); + ImdgPredicate currPrdct = CurrencyCodePredicate + .getPredicate(exec.getSettlementCurrency()) + .cashed(currencyImdg.predicateBuilder(), currCash); + Currency currency = currencyImdg.getFirstObjectByPredicate(currPrdct); reg.setSecurityId(currency.getId()); reg.setSecuritySymbol(currency.getCurrencyCode()); } else if ((regDsgn.equals(RegistryDesignation.T) && side.isBuy()) || (regDsgn.equals(RegistryDesignation.O) && side.isSell())) { @@ -127,8 +189,10 @@ public class RegistryFondBuilder implements IRegistryBuilder { DepoAccount depoAccount = null; if (tcr.getDepoAccountId() != null) { account = accountImdg.getSingleObjectByID(tcr.getDepoAccountId()); - depoAccount = depoAccountImdg.getFirstObjectByFieldValues( - Map.of("accountId", tcr.getDepoAccountId())); + ImdgPredicate depAccPrdct = AccountIdCashingPredicate + .getPredicate(tcr.getDepoAccountId()) + .cashed(depoAccountImdg.predicateBuilder(), dpAccCash); + depoAccount = depoAccountImdg.getFirstObjectByPredicate(depAccPrdct); } if (depoAccount != null) { capacityByAccount = depoAccount.getDepoAccountType(); @@ -154,7 +218,9 @@ public class RegistryFondBuilder implements IRegistryBuilder { reg.setRegistryStatus(RegistryStatus.PROC.getKey()); ExecutionFond execFond = (ExecutionFond) this.exec; if (isMoney) { - Security security = scrSlctr.selectSecurityById(execFond.getSecurityId()); + Security security = scrtCash.getOrFind( + execFond.getSecurityId(), () -> scrSlctr.selectSecurityById(execFond.getSecurityId()) + ).orElse(null); if (InstrumentType.BOND.equalsByKey(security.getInstrumentType())) { BigDecimal stlAmt = safeBD(execFond.getSettlementAmount()); BigDecimal intAmt = safeBD(execFond.getInterestAmount()); @@ -192,7 +258,7 @@ public class RegistryFondBuilder implements IRegistryBuilder { } private Company searchCompany() { - return companyImdg.getFirstObjectBySQL("id = " + exec.getCompanyId()); + return companyImdg.getSingleObjectByID(exec.getCompanyId()); } private TradingClearingRegistry searchTradingClearingRegistry() { @@ -212,7 +278,10 @@ public class RegistryFondBuilder implements IRegistryBuilder { private String defineCapacityByAccountType(String accountType, Long moneyAccountId) { String capacityByAccount = null; if (AccountType.Clrn.equalsByKey(accountType)) { - ClearingAccount clearingAccount = clearingAccountImdg.getFirstObjectByFieldValues(Map.of("accountId", moneyAccountId)); + ImdgPredicate prdct = AccountIdCashingPredicate + .getPredicate(moneyAccountId) + .cashed(clearingAccountImdg.predicateBuilder(), clrAccCash); + ClearingAccount clearingAccount = clearingAccountImdg.getFirstObjectByPredicate(prdct); if (clearingAccount != null) { capacityByAccount = clearingAccount.getClearingAccountType(); } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/RequirementsAndObligationCreation.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/RequirementsAndObligationCreation.java index b84fd9561..b6f847050 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/RequirementsAndObligationCreation.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/RequirementsAndObligationCreation.java @@ -12,16 +12,25 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; +import ru.clearing.classes.statics.data.account.Account; +import ru.clearing.classes.statics.data.account.ClearingAccount; +import ru.clearing.classes.statics.data.account.DepoAccount; +import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.execution.ExecutionCommon; import ru.clearing.classes.statics.data.execution.ExecutionCurrency; import ru.clearing.classes.statics.data.execution.ExecutionDeposit; import ru.clearing.classes.statics.data.execution.ExecutionFond; +import ru.clearing.classes.statics.data.misc.Currency; +import ru.clearing.classes.statics.data.misc.Session; import ru.clearing.classes.statics.data.registry.Registry; +import ru.clearing.classes.statics.data.registry.TradingClearingRegistry; +import ru.clearing.classes.statics.data.security.Security; import ru.spcex.clearing.imdg.IMDGDistributedNames; 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.TaskType; +import ru.spcex.clearing.session.stage.task.RequirementsAndObligationCreationPayload; import static ru.spcex.clearing.util.ComparatorUtil.execIdComparator; import static ru.spcex.clearing.util.ComparatorUtil.tradeTimeComparator; import ru.spcex.platform.classes.base.interfaces.ExecutionType; @@ -38,6 +47,10 @@ 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 ru.spcex.platform.imdg.iml.hazelcast.adapter.CashCloser; +import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2; +import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2ById; +import ru.spcex.platform.imdg.iml.hazelcast.adapter.CashV2ByString; import ru.spcex.platform.utils.collection.Pair; /** @@ -49,24 +62,61 @@ public class RequirementsAndObligationCreation implements ISessionStage { private final Logger log = LoggerFactory.getLogger(getClass()); private final Imdg registryImdg; private final ImdgProvider imdgProvider; + private final RequirementsAndObligationCreationCash cash; @Autowired public RequirementsAndObligationCreation(ImdgProvider imdgProvider) { this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class); this.imdgProvider = imdgProvider; + this.cash = new RequirementsAndObligationCreationCash(); } @SuppressWarnings("unchecked") @Override public StageResult submit(Task task) { if (task.getTaskType() == TaskType.RequirementsAndObligationsCreate) { - return createRegisters((List) task.getData()); + try (cash) { + try { + RequirementsAndObligationCreationPayload data + = (RequirementsAndObligationCreationPayload) task.getData(); + return createRegisters(data.getExecutions(), data.getSessionId()); + } catch (ClassCastException e) { + List data = (List) task.getData(); + return createRegisters(data, null); + } + } finally { + doRgsSearch = null; + } } throw new IllegalStateException("Unknown task type: " + task.getTaskType()); } - protected StageResult createRegisters(List data) { + protected Boolean doRgsSearch = null; + protected boolean searchForRegisters(Long sessionId) { + if (sessionId == null) return true; + if (doRgsSearch != null) return doRgsSearch; + + ImdgPredicateBuilder pb = registryImdg.predicateBuilder(); + ImdgPredicate condition = pb.and( + pb.equals("sessionId", sessionId), + pb.or( + pb.equals("registryDesignation", RegistryDesignation.O.getKey()), + pb.equals("registryDesignation", RegistryDesignation.T.getKey()) + ), + pb.or( + pb.equals("registryInstrumentType", RegistryInstrumentType.M.getKey()), + pb.equals("registryInstrumentType", RegistryInstrumentType.S.getKey()) + ), + pb.equals("registryUnit", RegistryUnit.T.getKey()) + ); + Registry rgs = registryImdg.getFirstObjectByPredicate(condition); + this.doRgsSearch = rgs != null; + return this.doRgsSearch; + } + + + protected StageResult createRegisters(List data, Long sessionId) { data.sort(tradeTimeComparator.thenComparing(execIdComparator)); //см. описание к #matchExecutions for (int i = 0; i < data.size(); ) { @@ -81,9 +131,13 @@ public class RequirementsAndObligationCreation implements ISessionStage { ExecutionCommon partyExec = matched.getFirst(); ExecutionCommon counterExec = matched.getSecond(); //бывает поиск обычный, бывает по ExecutionDeposit.secondLegSettlementDt - AtomicReference>> regSearchMethod = new AtomicReference<>(); + AtomicReference>> regSearchMethod = new AtomicReference<>( + (exc, dsg) -> Optional.empty() + ); //обычный поиск - regSearchMethod.set(this::findReg); + if (searchForRegisters(sessionId)) { + regSearchMethod.set(this::findReg); + } TriConsumer findAndUpdateOrCreate = (exec, regDsgn, returnedDep) -> regSearchMethod.get().apply(exec, regDsgn) .ifPresentOrElse(registry -> { @@ -96,6 +150,16 @@ public class RequirementsAndObligationCreation implements ISessionStage { }, () -> { IRegistryBuilder registryBuilder = defineBuilderByExecType(partyExec.type()); Registry newRegister = registryBuilder + //cashes + .cmpCash(cash.cmpCash) + .tcrCash(cash.tcrCash) + .accCash(cash.accCash) + .dpAccCash(cash.dpAccCash) + .scrtCash(cash.scrtCash) + .currCash(cash.currCash) + .clrAccCash(cash.clrAccCash) + .ssnCash(cash.ssnCash) + //------ .imdg(imdgProvider) .exec(exec) .registryDesignation(regDsgn) @@ -110,7 +174,9 @@ public class RequirementsAndObligationCreation implements ISessionStage { findAndUpdateOrCreate.accept(counterExec, RegistryDesignation.T, false); if (partyExec.type().equals(ExecutionType.ExecutionDeposit) && ((ExecutionDeposit) partyExec).getSecondLegSettlementDate() != null) { //поиск по дате расчетов ExecutionDeposit.secondLegSettlementDt - regSearchMethod.set(this::findRegBySettlementDt); + if (searchForRegisters(sessionId)) { + regSearchMethod.set(this::findRegBySettlementDt); + } findAndUpdateOrCreate.accept(partyExec, RegistryDesignation.T, true); findAndUpdateOrCreate.accept(partyExec, RegistryDesignation.O, true); findAndUpdateOrCreate.accept(counterExec, RegistryDesignation.T, true); @@ -269,4 +335,27 @@ public class RequirementsAndObligationCreation implements ISessionStage { private static interface TriConsumer { void accept(T1 t1, T2 t2, T3 t3); } + + private static class RequirementsAndObligationCreationCash extends CashCloser { + private final CashV2 cmpCash; + private final CashV2 tcrCash; + private final CashV2 accCash; + private final CashV2 dpAccCash; + private final CashV2ById scrtCash; + private final CashV2 currCash; + private final CashV2 clrAccCash; + private final CashV2 ssnCash; + + public RequirementsAndObligationCreationCash() { + cmpCash = new CashV2ById<>("cmpCash"); + tcrCash = new CashV2ById<>("tcrCash"); + accCash = new CashV2ById<>("accCash"); + dpAccCash = new CashV2ById<>("dpAccCash"); + scrtCash = new CashV2ById<>("scrtCash"); + currCash = new CashV2ByString<>("currCash", Currency::getCurrencyCode); + clrAccCash = new CashV2ById<>("clrAccCash"); + ssnCash = new CashV2ById<>("ssnCash"); + cashes = List.of(cmpCash, tcrCash, accCash, dpAccCash, scrtCash, currCash, clrAccCash, ssnCash); + } + } } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/RequirementsAndObligationCreationCompound.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/RequirementsAndObligationCreationCompound.java index af826fb1d..e41c4b54e 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/RequirementsAndObligationCreationCompound.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/impl/RequirementsAndObligationCreationCompound.java @@ -39,7 +39,11 @@ public class RequirementsAndObligationCreationCompound extends RequirementsAndOb @Override public StageResult submit(Task task) { if (task.getTaskType() == TaskType.RequirementsAndObligationsCreate) { - return mergeReqsAndClaims((RequirementsAndObligationCreationCompoundPayload) task.getData()); + try { + return mergeReqsAndClaims((RequirementsAndObligationCreationCompoundPayload) task.getData()); + } finally { + this.doRgsSearch = null; + } } throw new IllegalStateException("Unknown task type: " + task.getTaskType()); } @@ -68,7 +72,7 @@ public class RequirementsAndObligationCreationCompound extends RequirementsAndOb if (pair.getFirst().type().equals(ExecutionType.ExecutionDeposit)) ied[0] += 2; if (pair.getFirst().type().equals(ExecutionType.ExecutionCurrency)) iec[0] += 2; pair.map(f -> tmpList.set(0, f), s -> tmpList.set(1, s)); - createRegisters(tmpList); + createRegisters(tmpList, data.getSessionId()); } return new StageResult<>(null, true); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/task/RequirementsAndObligationCreationCompoundPayload.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/task/RequirementsAndObligationCreationCompoundPayload.java index 184ffab5b..b8ed7971d 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/task/RequirementsAndObligationCreationCompoundPayload.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/task/RequirementsAndObligationCreationCompoundPayload.java @@ -5,18 +5,28 @@ import ru.clearing.classes.statics.data.execution.ExecutionCommon; import ru.spcex.clearing.session.stage.task.result.DealsPrepareCompoundResult; public class RequirementsAndObligationCreationCompoundPayload { + private Long sessionId; private List executionsTrdt; private List executionsCurrency; private List executionsFinal; - public static RequirementsAndObligationCreationCompoundPayload create(DealsPrepareCompoundResult stageResult) { + public static RequirementsAndObligationCreationCompoundPayload create(DealsPrepareCompoundResult stageResult, Long sessionId) { RequirementsAndObligationCreationCompoundPayload p = new RequirementsAndObligationCreationCompoundPayload(); p.setExecutionsTrdt(stageResult.getExecutionsTrdt()); p.setExecutionsCurrency(stageResult.getExecutionsCurrency()); p.setExecutionsFinal(stageResult.getExecutionsFinal()); + p.setSessionId(sessionId); return p; } + public Long getSessionId() { + return sessionId; + } + + public void setSessionId(Long sessionId) { + this.sessionId = sessionId; + } + public List getExecutionsTrdt() { return executionsTrdt; } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/task/RequirementsAndObligationCreationPayload.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/task/RequirementsAndObligationCreationPayload.java new file mode 100644 index 000000000..63c08dd2c --- /dev/null +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/task/RequirementsAndObligationCreationPayload.java @@ -0,0 +1,30 @@ +package ru.spcex.clearing.session.stage.task; + +import java.util.List; +import ru.clearing.classes.statics.data.execution.ExecutionCommon; + +public class RequirementsAndObligationCreationPayload { + private List executions; + private Long sessionId; + + public RequirementsAndObligationCreationPayload(List executions, Long sessionId) { + this.executions = executions; + this.sessionId = sessionId; + } + + public Long getSessionId() { + return sessionId; + } + + public void setSessionId(Long sessionId) { + this.sessionId = sessionId; + } + + public List getExecutions() { + return executions; + } + + public void setExecutions(List executions) { + this.executions = executions; + } +} diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/util/RegistryUtil.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/util/RegistryUtil.java index ab1826862..8e752c590 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/util/RegistryUtil.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/session/stage/util/RegistryUtil.java @@ -1,14 +1,18 @@ package ru.spcex.clearing.session.stage.util; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.apache.commons.lang3.StringUtils; 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 java.math.BigDecimal; -import java.util.*; +import ru.spcex.platform.utils.text.TextUtil; public class RegistryUtil { @@ -29,6 +33,31 @@ public class RegistryUtil { return registryDesignation.getKey() + registryInstrumentType.getKey() + registryCapacity.getKey() + registryUnit.getKey(); } + public static String clearingCodeSafe(RegistryDesignation registryDesignationE, + RegistryInstrumentType registryInstrumentTypeE, + RegistryCapacity registryCapacityE, + RegistryUnit registryUnitE) { + String registryDesignation = registryDesignationE != null ? registryDesignationE.getKey() : "-"; + String registryInstrumentType = registryInstrumentTypeE != null ? registryInstrumentTypeE.getKey() : "-"; + String registryCapacity = registryCapacityE != null ? registryCapacityE.getKey() : "-"; + String registryUnit = registryUnitE != null ? registryUnitE.getKey() : "-"; + return registryDesignation + registryInstrumentType + registryCapacity + registryUnit; + } + + public static String clearingCode(RegistryTradingParams params) { + return clearingCodeSafe(params.registryDesignation(), params.registryInstrumentType(), params.registryCapacity(), params.registryUnit()); + } + + public static String rgsCdeWithoutCapacity(Registry rgs) { + String rgsCde = rgs.getRegistryCode(); + if (TextUtil.isEmpty(rgsCde) || rgsCde.length() < 3) { + return rgsCde; + } + StringBuilder newRgsCde = new StringBuilder(rgsCde); + newRgsCde.setCharAt(2, '-'); + return newRgsCde.toString(); + } + public static Map> groupByGroupId(Collection registries) { HashMap> groups = new HashMap<>(); for (Registry reg : registries) {