etreschenkov 2026-06-17 09:27:09 +03:00
parent a6b1c5372a
commit 7492fbe823
4 changed files with 177 additions and 10 deletions

View file

@ -12,6 +12,7 @@ import ru.spcex.clearing.account.errors.AccountError;
import ru.spcex.clearing.account.validation.BackendClientCodeValidationRule;
import ru.spcex.clearing.account.validation.GatewayClientCodeValidationRule;
import ru.spcex.clearing.account.validation.GatewayEksClientCodeValidationRule;
import ru.spcex.clearing.account.validation.GatewayUpdateEksClientCodeValidationRule;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.cud.account.ClientCodeNewRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.account.ClientCodeUpdateRequest;
@ -163,4 +164,19 @@ public class ClientCodeValidationConfig {
};
}
@Bean("updateTkrEksAccountsGatewayValidator")
public Function<TkrAccount, IValidator> updateTkrEksAccountsGatewayValidator(Map<String, Imdg<? extends SpcexObjectBase>> imdgForValidation) {
return tkrGatewayRequest -> {
ImdgValidationContext<TkrAccount> context = new ImdgValidationContext<>();
context.setValidatedObject(tkrGatewayRequest);
Consumer<String> addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s));
addImdg.accept(IMDGDistributedNames.Map_Account);
addImdg.accept(IMDGDistributedNames.Map_TradingClearingRegistry);
addImdg.accept(IMDGDistributedNames.Map_TradingClearingRegistryList);
return new ValidatorImpl<>(context,
GatewayUpdateEksClientCodeValidationRule.TkrIsPresent,
GatewayUpdateEksClientCodeValidationRule.AccountsNotLinkedToTkr
);
};
}
}

View file

@ -23,6 +23,7 @@ import ru.spcex.clearing.account.service.TradingClearingRegistryService;
import ru.spcex.clearing.account.service.v2.GatewayRequestCreator;
import ru.spcex.clearing.account.service.v2.facade.AccountFacade;
import ru.spcex.clearing.account.service.v2.facade.ClientCodeFacade;
import ru.spcex.clearing.account.service.v2.facade.TradingClearingRegistryListFacade;
import ru.spcex.clearing.account.service.v2.validators.ClientCodeValidator;
import ru.spcex.clearing.account.validation.ClientCodeStoreObjects;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
@ -34,6 +35,7 @@ import ru.spcex.clearing.platform.messaging.domain.cud.account.TkrAccountsGatewa
import ru.spcex.clearing.platform.messaging.domain.cud.gateway.MoneyAccountMsgRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.gateway.SendTkrRequest;
import ru.spcex.clearing.platform.messaging.domain.cud.gateway.Tkr;
import ru.spcex.clearing.platform.messaging.domain.cud.registry.TradingClearingRegistryListNewRequest;
import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate;
import ru.spcex.clearing.platform.messaging.service.Status;
@ -57,6 +59,7 @@ public class ClientCodeMessageListener extends QueueConsumer implements Initiali
private final UserRoleVerification userRoleVerification;
private final AccountFacade accountFacade;
private final TradingClearingRegistryService tradingClearingRegistryService;
private final TradingClearingRegistryListFacade tradingClearingRegistryListFacade;
public ClientCodeMessageListener(Consumer<String, Object> kafkaQueue,
Producer<String, Object> kafkaProducer,
@ -67,7 +70,8 @@ public class ClientCodeMessageListener extends QueueConsumer implements Initiali
GatewayRequestCreator gatewayRequestCreator,
UserRoleVerification userRoleVerification,
AccountFacade accountFacade,
TradingClearingRegistryService tradingClearingRegistryService) {
TradingClearingRegistryService tradingClearingRegistryService,
TradingClearingRegistryListFacade tradingClearingRegistryListFacade) {
super(kafkaQueue, kafkaProducer);
this.kafkaSender = kafkaSender;
this.imdgProvider = imdgProvider;
@ -77,6 +81,7 @@ public class ClientCodeMessageListener extends QueueConsumer implements Initiali
this.userRoleVerification = userRoleVerification;
this.accountFacade = accountFacade;
this.tradingClearingRegistryService = tradingClearingRegistryService;
this.tradingClearingRegistryListFacade = tradingClearingRegistryListFacade;
}
@Override
@ -92,7 +97,7 @@ public class ClientCodeMessageListener extends QueueConsumer implements Initiali
.setFunction(this::clientCodeNewFromGateway)
.forDestination(Consts.DESTINATION_CLIENT_CODE_NEW_FROM_GATEWAY, callbacks::put);
callback(TkrAccountsGatewayRequest.class)
.setFunction(this::clientCodeNewFromGateway)
.setFunction(this::clientCodeUpdateFromGateway)
.forDestination(Consts.DESTINATION_CLIENT_CODE_UPDATE_FROM_GATEWAY, callbacks::put);
init();
}
@ -118,16 +123,10 @@ public class ClientCodeMessageListener extends QueueConsumer implements Initiali
eksAccountsAfterValidation.put(tkrAccount, validationResult);
});
if (isAnyoneInvalid.get()) {
log.debug("Create error request to gateway service");
List<Tkr> eksTkrs = eksAccountsAfterValidation.entrySet()
.stream()
.map(tkrAccountValidationResultEntry ->
gatewayRequestCreator.crateErrorTkrToGateway(
tkrAccountValidationResultEntry.getKey(),
tkrAccountValidationResultEntry.getValue().errorMsg()
))
.toList();
List<Tkr> eksTkrs = makeErrorTkrResponse(eksAccountsAfterValidation);
sendTkrRequest.getTkrs().addAll(eksTkrs);
kafkaSender.sendRequestToQueue(Consts.ACCOUNTS_TO_GATEWAY, sendTkrRequest);
return null;
@ -137,6 +136,37 @@ public class ClientCodeMessageListener extends QueueConsumer implements Initiali
return null;
}
private RequestInfoUpdate clientCodeUpdateFromGateway(BaseRequest<TkrAccountsGatewayRequest> tkrRequest) {
TkrAccountsGatewayRequest gatewayRequest = tkrRequest.getRequestPayload();
SendTkrRequest sendTkrRequest = new SendTkrRequest();
sendTkrRequest.setRequestId(gatewayRequest.getRequestId());
AtomicBoolean isAnyoneInvalid = new AtomicBoolean(false);
Map<TkrAccount, ValidationResult> eksAccountsAfterValidation = new HashMap<>();
gatewayRequest.getAccounts().forEach(tkrAccount -> {
ValidationResult validationResult = clientCodeValidator.checkGatewayUpdateRequestWithEksAcc(tkrAccount);
if (!validationResult.isValid()) {
log.debug("Validation failed for tkr.client_code {}", tkrAccount.getClientCode());
isAnyoneInvalid.set(true);
}
eksAccountsAfterValidation.put(tkrAccount, validationResult);
});
if (isAnyoneInvalid.get()) {
log.debug("Create error request to gateway service");
List<Tkr> eksTkrs = makeErrorTkrResponse(eksAccountsAfterValidation);
sendTkrRequest.getTkrs().addAll(eksTkrs);
kafkaSender.sendRequestToQueue(Consts.ACCOUNTS_TO_GATEWAY, sendTkrRequest);
return null;
}
processUpdateEksAccount(eksAccountsAfterValidation, sendTkrRequest);
kafkaSender.sendRequestToQueue(Consts.ACCOUNTS_TO_GATEWAY, sendTkrRequest);
return null;
}
private void processEksAccount(Map<TkrAccount, ValidationResult> accountsAfterValidation, SendTkrRequest tkrRequest) {
for (Map.Entry<TkrAccount, ValidationResult> entry : accountsAfterValidation.entrySet()) {
TkrAccount tkrAccount = entry.getKey();
@ -180,6 +210,26 @@ public class ClientCodeMessageListener extends QueueConsumer implements Initiali
}
}
private void processUpdateEksAccount(Map<TkrAccount, ValidationResult> accountsAfterValidation, SendTkrRequest tkrRequest) {
for (Map.Entry<TkrAccount, ValidationResult> entry : accountsAfterValidation.entrySet()) {
TkrAccount tkrAccount = entry.getKey();
ValidationResult validationResult = entry.getValue();
IValidator validator = validationResult.validator();
List<Account> clrnAccs = validator.getStored(ClientCodeStoreObjects.CLRN_ACCS);
TradingClearingRegistry tradingClearingRegistry = validator.getStored(ClientCodeStoreObjects.TRADING_CLEARING_REGISTRY);
List<Long> accIds = clrnAccs.stream()
.map(Account::getId)
.toList();
TradingClearingRegistryListNewRequest tcrListNew = new TradingClearingRegistryListNewRequest();
tcrListNew.setTradingClearingRegistryId(tradingClearingRegistry.getId());
tcrListNew.setCurrencyAccountList(accIds);
List<Long> tkrListIds = tradingClearingRegistryListFacade.createTradingClearingRegistryList(tcrListNew, null);
Optional<Tkr> tkrReq = gatewayRequestCreator.createTkrGatewayReq(tradingClearingRegistry);
tkrReq.ifPresent(tkr -> tkrRequest.getTkrs().add(tkr));
}
}
private RequestInfoUpdate clientCodeNewFromBackend(BaseRequest<ClientCodeNewRequest> clientCodeNewRequest) {
RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(clientCodeNewRequest);
if (requestInfoUpdate != null) return requestInfoUpdate;
@ -193,6 +243,17 @@ public class ClientCodeMessageListener extends QueueConsumer implements Initiali
return null;
}
private List<Tkr> makeErrorTkrResponse(Map<TkrAccount, ValidationResult> eksAccountsAfterValidation) {
return eksAccountsAfterValidation.entrySet()
.stream()
.map(tkrAccountValidationResultEntry ->
gatewayRequestCreator.crateErrorTkrToGateway(
tkrAccountValidationResultEntry.getKey(),
tkrAccountValidationResultEntry.getValue().errorMsg()
))
.toList();
}
private RequestInfoUpdate makeErrorResponse(BaseRequest<ClientCodeNewRequest> clientCodeNewRequest,
ValidationResult validationResult) {
RequestInfoUpdate requestInfoUpdate = new RequestInfoUpdate();

View file

@ -5,6 +5,7 @@ import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import ru.spcex.clearing.account.model.ValidationResult;
import ru.spcex.clearing.platform.messaging.domain.cud.account.ClientCodeNewRequest;
@ -25,6 +26,7 @@ public class ClientCodeValidator {
private final Function<CommonDeleteRequest, IValidator> clientCodeDeleteRequestValidator;
private final Function<TkrAccount, IValidator> tkrAccountsGatewayValidator;
private final Function<TkrAccount, IValidator> tkrEksAccountsGatewayValidator;
private final Function<TkrAccount, IValidator> updateTkrEksAccountsGatewayValidator;
private final IMessageResolver messageResolver;
public ClientCodeValidator(UserRoleVerification userRoleVerification,
@ -33,6 +35,7 @@ public class ClientCodeValidator {
Function<CommonDeleteRequest, IValidator> clientCodeDeleteRequestValidator,
Function<TkrAccount, IValidator> tkrAccountsGatewayValidator,
Function<TkrAccount, IValidator> tkrEksAccountsGatewayValidator,
@Qualifier("updateTkrEksAccountsGatewayValidator") Function<TkrAccount, IValidator> updateTkrEksAccountsGatewayValidator,
IMessageResolver messageResolver) {
this.userRoleVerification = userRoleVerification;
this.clientCodeNewRequestValidator = clientCodeNewRequestValidator;
@ -40,6 +43,7 @@ public class ClientCodeValidator {
this.clientCodeDeleteRequestValidator = clientCodeDeleteRequestValidator;
this.tkrAccountsGatewayValidator = tkrAccountsGatewayValidator;
this.tkrEksAccountsGatewayValidator = tkrEksAccountsGatewayValidator;
this.updateTkrEksAccountsGatewayValidator = updateTkrEksAccountsGatewayValidator;
this.messageResolver = messageResolver;
}
@ -51,6 +55,10 @@ public class ClientCodeValidator {
return standardValidation(tkrEksAccountsGatewayValidator, gatewayAccountRequest);
}
public ValidationResult checkGatewayUpdateRequestWithEksAcc(TkrAccount gatewayAccountRequest) {
return standardValidation(updateTkrEksAccountsGatewayValidator, gatewayAccountRequest);
}
public ValidationResult checkBackendNewRequest(ClientCodeNewRequest clientCodeNewRequest) {
return standardValidation(clientCodeNewRequestValidator, clientCodeNewRequest);
}

View file

@ -0,0 +1,82 @@
package ru.spcex.clearing.account.validation;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.clearing.classes.statics.data.account.Account;
import ru.clearing.classes.statics.data.registry.TradingClearingRegistry;
import ru.clearing.classes.statics.data.registry.TradingClearingRegistryList;
import ru.spcex.clearing.account.errors.AccountError;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.cud.account.TkrAccount;
import ru.spcex.clearing.platform.messaging.domain.cud.gateway.MoneyAccountMsgRequest;
import ru.spcex.platform.enumeration.AccountType;
import ru.spcex.platform.enumeration.CurrencyCode;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
import ru.spcex.platform.imdg.validation.ImdgValidationContext;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import ru.spcex.platform.utils.validation.IValidationRule;
public enum GatewayUpdateEksClientCodeValidationRule implements IValidationRule<ImdgValidationContext<TkrAccount>> {
TkrIsPresent() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<TkrAccount> context) {
TkrAccount validatedObject = context.getValidatedObject();
Imdg<TradingClearingRegistry> tkrImdg = context.obtainMap(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class);
ImdgPredicateBuilder predicate = tkrImdg.predicateBuilder();
String trkCode = validatedObject.getTkrCode();
TradingClearingRegistry existTkr = tkrImdg.getSingleObjectByPredicate(
predicate.equals("code", trkCode)
);
if (existTkr == null) {
return of(AccountError.TradingClearingRegistryNotFound, trkCode);
}
context.storeObject(ClientCodeStoreObjects.TRADING_CLEARING_REGISTRY, existTkr);
return empty();
}
},
AccountsNotLinkedToTkr() {
@Override
public Optional<EnumMessage> validate(ImdgValidationContext<TkrAccount> context) {
TkrAccount validatedObject = context.getValidatedObject();
Imdg<Account> accountImdg = context.obtainMap(IMDGDistributedNames.Map_Account, Account.class);
Imdg<TradingClearingRegistryList> tkrList = context.obtainMap(IMDGDistributedNames.Map_TradingClearingRegistryList, TradingClearingRegistryList.class);
ImdgPredicateBuilder predicateBuilder = accountImdg.predicateBuilder();
List<MoneyAccountMsgRequest> accounts = validatedObject.getMoneyAccounts().stream()
.filter(moneyAccountMsgRequest ->
moneyAccountMsgRequest.getStatus().equals("ADD")
&& !CurrencyCode.RUB.equalsByKey(moneyAccountMsgRequest.getCurrCode()))
.toList();
List<Account> clrnAccounts = new ArrayList<>();
for (MoneyAccountMsgRequest request : accounts) {
Account account = accountImdg.getFirstObjectByPredicate(
predicateBuilder.and(
predicateBuilder.equals("account", request.getAccount()),
predicateBuilder.equals("accountType", AccountType.Clrn.getKey())
)
);
if (account == null) {
//todo пропускать такие счета и не выдавать ошибку? just continue;
return of(AccountError.AccountNotFound, request.getAccount());
}
TradingClearingRegistryList tkrListByAccount = tkrList.getSingleObjectByPredicate(
predicateBuilder.equals("accountId", account.getId())
);
if (tkrListByAccount != null) {
//todo пропускать такие счета и не выдавать ошибку? just continue;
return of(AccountError.AccountForTradingClearingRegistryAlreadyUsed, account.getId());
}
clrnAccounts.add(account);
}
context.storeObject(ClientCodeStoreObjects.CLRN_ACCS, clrnAccounts);
return empty();
}
}
;
private static final Logger log = LoggerFactory.getLogger(GatewayUpdateEksClientCodeValidationRule.class);
}