diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java index 592d0c12c..988d68534 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/config/ValidationConfig.java @@ -64,6 +64,7 @@ public class ValidationConfig { Imdg imdgSession; Imdg imdgSectionDictionary; Imdg imdgStatement; + Imdg imdgInOutDirection; ImdgProvider imdgProvider; public ValidationConfig(ImdgProvider imdgProvider) { @@ -82,6 +83,7 @@ public class ValidationConfig { this.equitySecurityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_EquitySecurity, EquitySecurity.class); this.imdgStatement = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class); this.imdgDepoAccount = imdgProvider.getImdg(IMDGDistributedNames.Map_DepoAccount, DepoAccount.class); + this.imdgInOutDirection = imdgProvider.getImdg(IMDGDistributedNames.Map_InOutDirectionDictionary, InOutDirectionDictionary.class); this.imdgProvider = imdgProvider; } @@ -346,7 +348,8 @@ public class ValidationConfig { ImdgValidationContext context = new ImdgValidationContext<>(); context.setValidatedObject(refundDateRequest); context.addImdg(IMDGDistributedNames.Map_Registry, imdgRegistry); - context.setLogPrefix(r -> "contract=%d refundDate=%s".formatted(r.getContract(), r.getRefundDate())); + context.addImdg(IMDGDistributedNames.Map_InOutDirectionDictionary, imdgInOutDirection); + context.setLogPrefix(r -> "contract=%s refundDate=%s".formatted(r.getContract(), r.getRefundDate())); return new ValidatorImpl<>(context, FieldRequiredRule.instance("contract", RegistrySplitDepositActionRequest::getContract, ClearingError.RequiredFieldEmpty), FieldRequiredRule.instance("refundDate", RegistrySplitDepositActionRequest::getRefundDate, ClearingError.RequiredFieldEmpty), diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java index a91b17e84..d471f9e4d 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/RegistryService.java @@ -6,7 +6,6 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.registry.TradingClearingRegistry; -import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.cud.clearing.CreateRegistryRequest; @@ -66,6 +65,7 @@ public class RegistryService { this.splitDepositActionVal = splitDepositActionVal; this.msgResolver = msgResolver; this.rights = rights; + rights.setRoleForVerification(UserRole.Admin); } public void createRegistry(CreateRegistryRequest createRegistryRequest) { @@ -213,24 +213,15 @@ public class RegistryService { RegistryTradingParams registryInfo = null; //todo спросить про дубль C и T switch (registryType) { - case Owner_A -> - registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.M, RegistryCapacity.A, RegistryUnit.T); - case Client_B -> - registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.M, RegistryCapacity.B, RegistryUnit.T); - case Trustee_C, DepoOfShares_T -> - registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.T); - case TrusteeManager_D -> - registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.A); - case Issuer_E -> - registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.E, RegistryUnit.R); - case ToThePlacementOrRedeem_Z -> - registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.Z, RegistryUnit.R); - case DepoBond_H -> - registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.R); - case DepoOfTrustedBond_N -> - registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.C, RegistryUnit.R); - case DepoOfTrustedShares_S -> - registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.C, RegistryUnit.T); + case Owner_A -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.M, RegistryCapacity.A, RegistryUnit.T); + case Client_B -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.M, RegistryCapacity.B, RegistryUnit.T); + case Trustee_C, DepoOfShares_T -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.T); + case TrusteeManager_D -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.A); + case Issuer_E -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.E, RegistryUnit.R); + case ToThePlacementOrRedeem_Z -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.Z, RegistryUnit.R); + case DepoBond_H -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.A, RegistryUnit.R); + case DepoOfTrustedBond_N -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.C, RegistryUnit.R); + case DepoOfTrustedShares_S -> registryInfo = new RegistryTradingParams(RegistryDesignation.A, RegistryInstrumentType.S, RegistryCapacity.C, RegistryUnit.T); } return registryInfo; } @@ -295,7 +286,7 @@ public class RegistryService { if (roleCheck != null) { return roleCheck; } - Registry baseRegistry; + Collection baseRegistrys; { IValidator validator = splitDepositActionVal.apply(requestPayload); Optional err = validator.tillFirstError(); @@ -305,7 +296,7 @@ public class RegistryService { msgResolver.resolve(err.get())); return new RequestInfoUpdate(req.getId(), Status.Error, msgResolver.resolve(err.get())); } - baseRegistry = validator.getStored(ValidationStored.RegistryByContract); + baseRegistrys = validator.getStored(ValidationStored.RegistrysByContract); } ImdgTransaction txCtx = imdgProvider.newTransaction(); @@ -319,43 +310,56 @@ public class RegistryService { direction = InOutDirection.out; log.debug("Direction not set. Use default: {}", direction); } - // 1. Первая группа - Registry firstRegistry = baseRegistry.clone(); - firstRegistry.setId(null); - firstRegistry.setCreated(now); - firstRegistry.setUpdated(null); - if (InOutDirection.out == direction) { - firstRegistry.setBalance(baseRegistry.getBalance().subtract(requestPayload.getOutboundAmount())); - } else if (InOutDirection.in == direction) { - firstRegistry.setBalance(baseRegistry.getBalance().add(requestPayload.getOutboundAmount())); - } else { - log.warn("Direction not set, do not change Balance"); - } - firstRegistry.setContract(baseRegistry.getContract() + "~1"); - registryTMap.insert(firstRegistry); + log.debug("Process {} for {} registry", direction, baseRegistrys.size()); + Long groupId = null; + for (Registry baseRegistry : baseRegistrys) { + log.trace("Registry[{}], groupId={}, ClearingCode={}", baseRegistry.getId(), baseRegistry.getGroupId(), baseRegistry.getClearingCode()); + if (groupId == null) + groupId = baseRegistry.getGroupId(); + else if (!groupId.equals(baseRegistry.getGroupId())) { + log.warn("Group id different: groupId={}; registry[{}].groupId={}", groupId, baseRegistry.getId(), baseRegistry.getGroupId()); + } + // 1. Первая группа + Registry firstRegistry = baseRegistry.clone(); + firstRegistry.setId(null); + firstRegistry.setCreated(now); + firstRegistry.setUpdated(null); + if (InOutDirection.out == direction) { + firstRegistry.setBalance(baseRegistry.getBalance().subtract(requestPayload.getOutboundAmount())); + } else if (InOutDirection.in == direction) { + firstRegistry.setBalance(baseRegistry.getBalance().add(requestPayload.getOutboundAmount())); + } else { + log.warn("Direction not set, do not change Balance"); + } + firstRegistry.setContract(baseRegistry.getContract() + "~1"); + registryTMap.insert(firstRegistry); - // 2. Вторая группа - Registry secondRegistry = null; - if (InOutDirection.out == direction) { - secondRegistry.setId(null); - secondRegistry.setCreated(now); - secondRegistry.setUpdated(null); - secondRegistry.setBalance(requestPayload.getOutboundAmount()); - secondRegistry.setContract(baseRegistry.getContract() + "~2"); - registryTMap.insert(secondRegistry); - } + // 2. Вторая группа + Registry secondRegistry = null; + if (InOutDirection.out == direction) { + secondRegistry = baseRegistry.clone(); + secondRegistry.setId(null); + secondRegistry.setCreated(now); + secondRegistry.setUpdated(null); + secondRegistry.setBalance(requestPayload.getOutboundAmount()); + secondRegistry.setContract(baseRegistry.getContract() + "~2"); + secondRegistry.setRefundDate(requestPayload.getRefundDate()); + secondRegistry.setSettlementDate(requestPayload.getRefundDate()); + registryTMap.insert(secondRegistry); + } - // 3. Текущим обязательствам установить статус SPLT - baseRegistry.setRegistryStatus(RegistryStatus.SPLT.getKey()); - baseRegistry.setUpdated(Instant.now()); - registryTMap.update(baseRegistry); + // 3. Текущим обязательствам установить статус SPLT + baseRegistry.setRegistryStatus(RegistryStatus.SPLT.getKey()); + baseRegistry.setUpdated(Instant.now()); + registryTMap.update(baseRegistry); + log.debug("Registry[{}] groupId={} split to: id1={} {}, id2={} {}", + baseRegistry.getId(), baseRegistry.getGroupId(), + firstRegistry == null ? null : firstRegistry.getId(), firstRegistry == null ? null : firstRegistry.getContract(), + secondRegistry == null ? null : secondRegistry.getId(), secondRegistry == null ? null : secondRegistry.getContract() + ); + } txOk = true; - log.debug("Registry[{}] groupId={} split to: id1={} {}, id2={} {}", - baseRegistry.getId(), baseRegistry.getGroupId(), - firstRegistry == null ? null : firstRegistry.getId(), firstRegistry == null ? null : firstRegistry.getContract(), - secondRegistry == null ? null : secondRegistry.getId(), secondRegistry == null ? null : secondRegistry.getContract() - ); } finally { if (txOk) { txCtx.commitTransaction(); diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/SplitDepositRequestValidationRule.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/SplitDepositRequestValidationRule.java index 90d1346cd..fc94dd6c8 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/SplitDepositRequestValidationRule.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/SplitDepositRequestValidationRule.java @@ -6,18 +6,20 @@ import ru.clearing.classes.statics.data.registry.Registry; import ru.spcex.clearing.error.ClearingError; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.cud.registry.RegistrySplitDepositActionRequest; +import ru.spcex.platform.enumeration.RegistryDesignation; import ru.spcex.platform.enumeration.RegistryStatus; -import ru.spcex.platform.enumeration.RegistryTradingParams; +import ru.spcex.platform.enumeration.RegistryUnit; import ru.spcex.platform.imdg.api.Imdg; 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.validation.ImdgValidationContext; import ru.spcex.platform.utils.enumeration.EnumMessage; import ru.spcex.platform.utils.validation.IValidationRule; import java.math.BigDecimal; +import java.util.Collection; import java.util.Optional; +import java.util.stream.Collectors; public enum SplitDepositRequestValidationRule implements IValidationRule> { CrossvalidateByRegistry() { @@ -30,32 +32,36 @@ public enum SplitDepositRequestValidationRule implements IValidationRule registrys = registryImdg.getCollectionObjectsByPredicate(query); + registrys = registrys.stream() + .filter(r->r.getValueDate()!=null && r.getSettlementDate()!=null && r.getValueDate().isBefore(r.getSettlementDate())) + .collect(Collectors.toList()); + Registry registryO = registrys.stream() + .filter(r -> RegistryDesignation.O.equalsByKey(r.getRegistryDesignation())) + .findAny().orElse(null); + log.trace("Found registry {}. Crossvalidate for {}", registrys, registryO); + + if (registryO == null) { + log.debug("Registry not found by query \"{}\" and valueDate < settlementDate", query); return of(ClearingError.TCRegistryNotFound, request.getContract()); - } else { - log.trace("Registry.id={} found by query \"{}\"", registry.getId(), query); } - context.storeObject(ValidationStored.RegistryByContract, registry); + context.storeObject(ValidationStored.RegistrysByContract, registrys); // кросс-валидация - if (!RegistryStatus.PROC.equalsByKey(registry.getRegistryStatus())) { - log.debug("Registry[{}].RegistryStatus={} - error", - registry.getId(), registry.getRegistryStatus()); - return Optional.of(new EnumMessage(ClearingError.TCRegistryNotFound, request.getContract())); - } - BigDecimal regBalance = registry.getBalance(); - if (regBalance == null || regBalance.compareTo(request.getOutboundAmount()) < 0) { + BigDecimal regBalance = registryO.getBalance(); + if (regBalance == null || regBalance.compareTo(request.getOutboundAmount()) <= 0) { log.trace("Registry[{}] balance={} < OutboundAmount {}", - registry.getId(), regBalance, request.getOutboundAmount()); + registryO.getId(), regBalance, request.getOutboundAmount()); return Optional.of(new EnumMessage(ClearingError.BalanceInsufficient, request.getContract())); } - if (!registry.getRefundDate().isAfter(request.getRefundDate())) { + if (registryO.getRefundDate().isBefore(request.getRefundDate())) { // дате в регистре >= refundDate log.trace("Registry[{}].RefundDate={} but request RefundDate={}", - registry.getId(), registry.getRefundDate(), request.getRefundDate()); + registryO.getId(), registryO.getRefundDate(), request.getRefundDate()); return Optional.of(new EnumMessage(ClearingError.WrongFieldValue, "RefundDate")); } diff --git a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java index a4faa986a..42ef0ae39 100644 --- a/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java +++ b/clearing-parent/clearing-service/src/main/java/ru/spcex/clearing/service/validation/ValidationStored.java @@ -28,5 +28,5 @@ public enum ValidationStored { SecurityBySecurityCode, - RegistryByContract + RegistrysByContract }