From 459fe3db6c2ccaeac922704d42e8cec2dff032d3 Mon Sep 17 00:00:00 2001 From: etreschenkov Date: Thu, 18 Jun 2026 13:46:56 +0300 Subject: [PATCH] http://jira.mfd.msk:8088/browse/CLS-1039 --- .../ClientCodeValidationConfig.java | 13 +- .../clearing/account/errors/AccountError.java | 2 + .../listeners/ClientCodeMessageListener.java | 4 +- .../validation/ClientCodeStoreObjects.java | 3 +- ...ewayUpdateEksClientCodeValidationRule.java | 190 +++++++++++++++++- 5 files changed, 206 insertions(+), 6 deletions(-) diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/ClientCodeValidationConfig.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/ClientCodeValidationConfig.java index 01d85d8bc..6f4d3f309 100644 --- a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/ClientCodeValidationConfig.java +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/ClientCodeValidationConfig.java @@ -170,12 +170,21 @@ public class ClientCodeValidationConfig { ImdgValidationContext context = new ImdgValidationContext<>(); context.setValidatedObject(tkrGatewayRequest); Consumer addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s)); + addImdg.accept(IMDGDistributedNames.Map_Company); + addImdg.accept(IMDGDistributedNames.Map_CompanySymbols); addImdg.accept(IMDGDistributedNames.Map_Account); addImdg.accept(IMDGDistributedNames.Map_TradingClearingRegistry); - addImdg.accept(IMDGDistributedNames.Map_TradingClearingRegistryList); + addImdg.accept(IMDGDistributedNames.Map_AccountSymbols); + addImdg.accept(IMDGDistributedNames.Map_DepoAccount); + addImdg.accept(IMDGDistributedNames.Map_ClientCode); return new ValidatorImpl<>(context, + GatewayUpdateEksClientCodeValidationRule.CompanyPresent, GatewayUpdateEksClientCodeValidationRule.TkrIsPresent, - GatewayUpdateEksClientCodeValidationRule.AccountsNotLinkedToTkr + GatewayUpdateEksClientCodeValidationRule.DepoAccountIsValid, + GatewayUpdateEksClientCodeValidationRule.NewForRubNotAllowed, + GatewayUpdateEksClientCodeValidationRule.ClientCodeIsPresent, + GatewayUpdateEksClientCodeValidationRule.ClrnAccountsNotLinkedToTkr, + GatewayUpdateEksClientCodeValidationRule.AnltAccountsNotLinkedToTkr ); }; } diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/errors/AccountError.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/errors/AccountError.java index 1114b546d..c479f99bd 100644 --- a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/errors/AccountError.java +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/errors/AccountError.java @@ -32,6 +32,8 @@ public enum AccountError implements IErrorEnumId { CurrencyForTradingClearingRegistryListAlreadyUsed(5031L), BadSymbol(5032L), TradingClearingRegistryNotFound(3022L), + ClientCodeNotLinedToTkr(3033L), + AccountRubForbiddenForAdd(3033L), CurrencyNotFound(1016L), ; diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/v2/listeners/ClientCodeMessageListener.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/v2/listeners/ClientCodeMessageListener.java index aa30ef504..3b5a8c69a 100644 --- a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/v2/listeners/ClientCodeMessageListener.java +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/v2/listeners/ClientCodeMessageListener.java @@ -8,6 +8,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Stream; import org.apache.kafka.clients.consumer.Consumer; import org.apache.kafka.clients.producer.Producer; import org.slf4j.Logger; @@ -221,8 +222,9 @@ public class ClientCodeMessageListener extends QueueConsumer implements Initiali ValidationResult validationResult = entry.getValue(); IValidator validator = validationResult.validator(); List clrnAccs = validator.getStored(ClientCodeStoreObjects.CLRN_ACCS); + List anltAccs = validator.getStored(ClientCodeStoreObjects.ANLT_ACCS); TradingClearingRegistry tradingClearingRegistry = validator.getStored(ClientCodeStoreObjects.TRADING_CLEARING_REGISTRY); - List accIds = clrnAccs.stream() + List accIds = Stream.concat(clrnAccs.stream(), anltAccs.stream()) .map(Account::getId) .toList(); diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/validation/ClientCodeStoreObjects.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/validation/ClientCodeStoreObjects.java index 02d68d153..70b042cef 100644 --- a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/validation/ClientCodeStoreObjects.java +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/validation/ClientCodeStoreObjects.java @@ -7,5 +7,6 @@ public enum ClientCodeStoreObjects { CLRN_ACCS, ANLT_ACCS, MAPPED_TO_CURRENCY_ACCOUNTS, - TRADING_CLEARING_REGISTRY + TRADING_CLEARING_REGISTRY, + CLIENT_CODE } diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/validation/GatewayUpdateEksClientCodeValidationRule.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/validation/GatewayUpdateEksClientCodeValidationRule.java index 028b30e12..8f6775a17 100644 --- a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/validation/GatewayUpdateEksClientCodeValidationRule.java +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/validation/GatewayUpdateEksClientCodeValidationRule.java @@ -2,10 +2,16 @@ package ru.spcex.clearing.account.validation; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; import ru.clearing.classes.statics.data.account.Account; +import ru.clearing.classes.statics.data.account.AccountSymbols; +import ru.clearing.classes.statics.data.account.ClientCode; +import ru.clearing.classes.statics.data.account.DepoAccount; +import ru.clearing.classes.statics.data.company.Company; import ru.clearing.classes.statics.data.registry.TradingClearingRegistry; import ru.clearing.classes.statics.data.registry.TradingClearingRegistryList; import ru.spcex.clearing.account.errors.AccountError; @@ -22,18 +28,40 @@ import ru.spcex.platform.utils.enumeration.EnumMessage; import ru.spcex.platform.utils.validation.IValidationRule; public enum GatewayUpdateEksClientCodeValidationRule implements IValidationRule> { + CompanyPresent() { + @Override + public Optional validate(ImdgValidationContext context) { + TkrAccount validatedObject = context.getValidatedObject(); + Long tradingCode = validatedObject.getTradingCode(); + if (tradingCode == null) { + return of(AccountError.RequiredFieldEmpty, "trading_code"); + } + + Imdg companyImdg = context.obtainMap(IMDGDistributedNames.Map_Company, Company.class); + Company company = companyImdg.getFirstObjectByFieldValues( + Map.of("tradingCode", String.valueOf(tradingCode)) + ); + if (company == null) { + return of(AccountError.COMPANY_NOT_FOUND_GTW, "trading_code"); + } + + context.storeObject(ClientCodeStoreObjects.COMPANY, company); + return Optional.empty(); + } + }, TkrIsPresent() { @Override public Optional validate(ImdgValidationContext context) { TkrAccount validatedObject = context.getValidatedObject(); + Company company = context.getStoredObject(ClientCodeStoreObjects.COMPANY); Imdg tkrImdg = context.obtainMap(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class); ImdgPredicateBuilder predicate = tkrImdg.predicateBuilder(); String trkCode = validatedObject.getTkrCode(); TradingClearingRegistry existTkr = tkrImdg.getSingleObjectByPredicate( predicate.and( predicate.equals("code", trkCode), - predicate.equals("status", Status.Active.getKey()) + predicate.equals("companyId", company.getId()) ) ); if (existTkr == null) { @@ -43,7 +71,82 @@ public enum GatewayUpdateEksClientCodeValidationRule implements IValidationRule< return empty(); } }, - AccountsNotLinkedToTkr() { + DepoAccountIsValid() { + @Override + public Optional validate(ImdgValidationContext context) { + TkrAccount validatedObject = context.getValidatedObject(); + TradingClearingRegistry tkr = context.getStoredObject(ClientCodeStoreObjects.TRADING_CLEARING_REGISTRY); + if (StringUtils.hasText(validatedObject.getDepoAccount())) { + String depoAccountVal = validatedObject.getDepoAccount(); + Imdg accountSymbolsImdg = context.obtainMap(IMDGDistributedNames.Map_AccountSymbols, AccountSymbols.class); + ImdgPredicateBuilder predicateBuilder = accountSymbolsImdg.predicateBuilder(); + AccountSymbols accountSymbols = accountSymbolsImdg.getSingleObjectByPredicate( + predicateBuilder.equals("accountSymbolValue", depoAccountVal) + ); + + if (accountSymbols == null) { + return of(AccountError.DepoAccountNotFound, "depo_account"); + } + Company company = context.getStoredObject(ClientCodeStoreObjects.COMPANY); + Imdg imdg = context.obtainMap(IMDGDistributedNames.Map_DepoAccount, DepoAccount.class); + DepoAccount depoAccount = imdg.getFirstObjectByPredicate( + predicateBuilder.and( + predicateBuilder.equals("accountId", accountSymbols.getAccountId()), + predicateBuilder.equals("companyId", company.getId()) + ) + ); + if (depoAccount == null) { + context.storeObject(ClientCodeStoreObjects.DEPO_ACCOUNT, Optional.empty()); + return of(AccountError.DepoAccountNotFound, "depo_account"); + } + if (!tkr.getDepoAccountId().equals(depoAccount.getAccountId())) { + return of(AccountError.AccountForTradingClearingRegistryAlreadyUsed, depoAccount.getAccountId()); + } + } + return empty(); + } + }, + NewForRubNotAllowed(){ + @Override + public Optional validate(ImdgValidationContext context) { + TkrAccount validatedObject = context.getValidatedObject(); + List accounts = validatedObject.getMoneyAccounts().stream() + .filter(moneyAccountMsgRequest -> + moneyAccountMsgRequest.getStatus().equals("NEW") + && CurrencyCode.RUB.equalsByKey(moneyAccountMsgRequest.getCurrCode())) + .toList(); + if (!accounts.isEmpty()) { + return of(AccountError.AccountRubForbiddenForAdd, accounts.stream().findFirst().get().getAccount()); + } + return empty(); + } + }, + ClientCodeIsPresent() { + @Override + public Optional validate(ImdgValidationContext context) { + TkrAccount validatedObject = context.getValidatedObject(); + if (!StringUtils.hasText(validatedObject.getClientCode())) { + return empty(); + } + TradingClearingRegistry tkr = context.getStoredObject(ClientCodeStoreObjects.TRADING_CLEARING_REGISTRY); + Imdg clientCodeImdg = context.obtainMap(IMDGDistributedNames.Map_ClientCode, ClientCode.class); + ImdgPredicateBuilder predicate = clientCodeImdg.predicateBuilder(); + String trkCode = validatedObject.getTkrCode(); + ClientCode existClientCode = clientCodeImdg.getSingleObjectByPredicate( + predicate.and( + predicate.equals("code", validatedObject.getClientCode()), + predicate.equals("tradingClearingRegistryId", tkr.getId()), + predicate.equals("status", Status.Active.getKey()) + ) + ); + if (existClientCode == null) { + return of(AccountError.ClientCodeNotLinedToTkr, trkCode); + } + context.storeObject(ClientCodeStoreObjects.CLIENT_CODE, existClientCode); + return empty(); + } + }, + ClrnAccountsNotLinkedToTkr() { @Override public Optional validate(ImdgValidationContext context) { TkrAccount validatedObject = context.getValidatedObject(); @@ -55,6 +158,11 @@ public enum GatewayUpdateEksClientCodeValidationRule implements IValidationRule< moneyAccountMsgRequest.getStatus().equals("NEW") && !CurrencyCode.RUB.equalsByKey(moneyAccountMsgRequest.getCurrCode())) .toList(); + List existAccounts = validatedObject.getMoneyAccounts().stream() + .filter(moneyAccountMsgRequest -> + moneyAccountMsgRequest.getStatus().equals("NEW") + && !CurrencyCode.RUB.equalsByKey(moneyAccountMsgRequest.getCurrCode())) + .toList(); List clrnAccounts = new ArrayList<>(); for (MoneyAccountMsgRequest request : accounts) { Account account = accountImdg.getFirstObjectByPredicate( @@ -74,9 +182,87 @@ public enum GatewayUpdateEksClientCodeValidationRule implements IValidationRule< } clrnAccounts.add(account); } + + for (MoneyAccountMsgRequest request : existAccounts) { + Account account = accountImdg.getFirstObjectByPredicate( + predicateBuilder.and( + predicateBuilder.equals("account", request.getAccount()), + predicateBuilder.equals("accountType", AccountType.Clrn.getKey()) + ) + ); + if (account == null) { + return of(AccountError.AccountNotFound, request.getAccount()); + } + TradingClearingRegistryList tkrListByAccount = tkrList.getSingleObjectByPredicate( + predicateBuilder.equals("accountId", account.getId()) + ); + if (tkrListByAccount == null) { + return of(AccountError.AccountForTradingClearingRegistryAlreadyUsed, account.getId()); + } + } context.storeObject(ClientCodeStoreObjects.CLRN_ACCS, clrnAccounts); return empty(); } + }, + AnltAccountsNotLinkedToTkr() { + @Override + public Optional validate(ImdgValidationContext context) { + TkrAccount validatedObject = context.getValidatedObject(); + Imdg accountImdg = context.obtainMap(IMDGDistributedNames.Map_Account, Account.class); + Imdg tkrList = context.obtainMap(IMDGDistributedNames.Map_TradingClearingRegistryList, TradingClearingRegistryList.class); + ImdgPredicateBuilder predicateBuilder = accountImdg.predicateBuilder(); + List newAccounts = validatedObject.getMoneyAccounts().stream() + .filter(moneyAccountMsgRequest -> + StringUtils.hasText(moneyAccountMsgRequest.getEks_account()) && moneyAccountMsgRequest.getStatus().equals("NEW") + && !CurrencyCode.RUB.equalsByKey(moneyAccountMsgRequest.getCurrCode())) + .toList(); + List anltAccounts = new ArrayList<>(); + for (MoneyAccountMsgRequest request : newAccounts) { + Account account = accountImdg.getFirstObjectByPredicate( + predicateBuilder.and( + predicateBuilder.equals("accountType", AccountType.Anlt.getKey()), + predicateBuilder.equals("currency", request.getCurrCode()), + predicateBuilder.equals("account", request.getEks_account()) + ) + ); + if (account == null) { + return of(AccountError.AccountNotFound, request.getAccount()); + } + TradingClearingRegistryList tkrListByAccount = tkrList.getSingleObjectByPredicate( + predicateBuilder.equals("accountId", account.getId()) + ); + if (tkrListByAccount != null) { + return of(AccountError.AccountForTradingClearingRegistryAlreadyUsed, account.getId()); + } + anltAccounts.add(account); + } + + List existAccounts = validatedObject.getMoneyAccounts().stream() + .filter(moneyAccountMsgRequest -> + StringUtils.hasText(moneyAccountMsgRequest.getEks_account()) && moneyAccountMsgRequest.getStatus().equals("NOW") + && !CurrencyCode.RUB.equalsByKey(moneyAccountMsgRequest.getCurrCode())) + .toList(); + for (MoneyAccountMsgRequest request : existAccounts) { + Account account = accountImdg.getFirstObjectByPredicate( + predicateBuilder.and( + predicateBuilder.equals("accountType", AccountType.Anlt.getKey()), + predicateBuilder.equals("currency", request.getCurrCode()), + predicateBuilder.equals("account", request.getEks_account()) + ) + ); + if (account == null) { + return of(AccountError.AccountNotFound, request.getAccount()); + } + TradingClearingRegistryList tkrListByAccount = tkrList.getSingleObjectByPredicate( + predicateBuilder.equals("accountId", account.getId()) + ); + if (tkrListByAccount == null) { + return of(AccountError.AccountForTradingClearingRegistryAlreadyUsed, account.getId()); + } + } + context.storeObject(ClientCodeStoreObjects.ANLT_ACCS, anltAccounts); + return empty(); + } } ;