From c1c5ec4c9cbf2f37e58fa4b973554fc68df769e1 Mon Sep 17 00:00:00 2001 From: akulikov Date: Mon, 24 Apr 2023 11:52:59 +0300 Subject: [PATCH] Account: new account request --- .../validation/AccountValidationConfig.java | 47 ++++-- .../config/validation/ValidationConfig.java | 2 + .../account/service/AccountService.java | 136 +++++++++++++++++- .../account/service/AccountServiceTest.java | 4 +- .../balance/service/StatementService.java | 2 +- .../service/StatementServiceServiceTest.java | 2 +- .../spcex/platform/enumeration/Service.java | 2 +- .../platform/messaging/domain/Consts.java | 7 +- 8 files changed, 178 insertions(+), 24 deletions(-) diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/AccountValidationConfig.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/AccountValidationConfig.java index 5f54f0982..d545be8ab 100644 --- a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/AccountValidationConfig.java +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/AccountValidationConfig.java @@ -9,6 +9,7 @@ import ru.spcex.clearing.account.errors.AccountError; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.cud.account.AccountNewRequest; import ru.spcex.clearing.platform.messaging.domain.cud.account.AccountUpdateRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest; import ru.spcex.clearing.validation.common.rules.DictionaryPresentRule; import ru.spcex.clearing.validation.common.rules.EnumPresentRule; import ru.spcex.clearing.validation.common.rules.FieldRequiredRule; @@ -16,7 +17,6 @@ import ru.spcex.clearing.validation.common.rules.IdPresentRule; import ru.spcex.platform.classes.base.SpcexObjectBase; import ru.spcex.platform.enumeration.AccountStatus; import ru.spcex.platform.enumeration.AccountType; -import ru.spcex.platform.enumeration.Status; import ru.spcex.platform.enumeration.WorkflowStatus; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.predicate.ImdgPredicate; @@ -35,7 +35,7 @@ import java.util.function.Function; @Configuration public class AccountValidationConfig { - @Bean("bankAccountNewRequestValidator") + @Bean("accountNewRequestValidator") public Function accountNewRequestValidator( Map> imdgForValidation ) { @@ -88,12 +88,16 @@ public class AccountValidationConfig { IMDGDistributedNames.Map_AccountTypeDictionary, AccountTypeDictionary.class, AccountError.RequiredFieldEmpty, - AccountError.WrongFieldValue) + AccountError.WrongFieldValue, + accountType -> { + if (accountType.getCode().equalsIgnoreCase(AccountType.Corr.getKey())) return null; + return AccountError.WrongFieldValue; + }) ); }; } - @Bean("bankAccountUpdateRequestValidator") + @Bean("accountUpdateRequestValidator") public Function accountUpdateRequestValidator( Map> imdgForValidation ) { @@ -135,15 +139,6 @@ public class AccountValidationConfig { false, AccountError.WrongFieldValue, AccountError.RequiredFieldEmpty), - FieldRequiredRule.instance("status", - AccountUpdateRequest::getStatus, - AccountError.RequiredFieldEmpty, - false, - statusValue -> { - if (statusValue != null && !Status.Active.getKey().equalsIgnoreCase(statusValue)) - return AccountError.WrongFieldValue; - return null; - }), EnumPresentRule.instance("accountType", AccountUpdateRequest::getAccountType, AccountType.values(), @@ -154,7 +149,31 @@ public class AccountValidationConfig { IMDGDistributedNames.Map_AccountTypeDictionary, AccountTypeDictionary.class, AccountError.RequiredFieldEmpty, - AccountError.WrongFieldValue) + AccountError.WrongFieldValue, + accountType -> { + if (accountType.getCode().equalsIgnoreCase(AccountType.Corr.getKey())) return null; + return AccountError.WrongFieldValue; + }) + ); + }; + } + + @Bean("accountBlockRequestValidator") + public Function accountBlockRequestValidator( + Map> imdgForValidation + ) { + return accountDeleteRequest -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(accountDeleteRequest); + Consumer addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s)); + addImdg.accept(IMDGDistributedNames.Map_Account); + return new ValidatorImpl<>(context, + IdPresentRule.instance("id", + CommonDeleteRequest::getId, + IMDGDistributedNames.Map_Account, + Account.class, + AccountError.RequiredFieldEmpty, + AccountError.AccountNotFound) ); }; } diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/ValidationConfig.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/ValidationConfig.java index a606cf3b0..537073f68 100644 --- a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/ValidationConfig.java +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/ValidationConfig.java @@ -5,6 +5,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import ru.clearing.classes.statics.data.account.Account; import ru.clearing.classes.statics.data.account.BankAccount; +import ru.clearing.classes.statics.data.company.ClearingMemberCategory; import ru.clearing.classes.statics.data.company.Company; import ru.clearing.platform.dictionary.CurrencyCodeDictionary; import ru.spcex.clearing.imdg.IMDGDistributedNames; @@ -27,6 +28,7 @@ public class ValidationConfig { BiConsumer> addImdg = (s, aClass) -> imdg.put(s, imdgProvider.getImdg(s, aClass)); addImdg.accept(IMDGDistributedNames.Map_Company, Company.class); + addImdg.accept(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class); addImdg.accept(IMDGDistributedNames.Map_Account, Account.class); addImdg.accept(IMDGDistributedNames.Map_AccountTypeDictionary, Account.class); addImdg.accept(IMDGDistributedNames.Map_BankAccount, BankAccount.class); diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/AccountService.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/AccountService.java index b3885b9aa..96edca925 100644 --- a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/AccountService.java +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/AccountService.java @@ -5,46 +5,174 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import ru.clearing.classes.statics.data.account.Account; +import ru.clearing.classes.statics.data.company.ClearingMemberCategory; +import ru.clearing.classes.statics.data.company.relation.Relation; +import ru.spcex.clearing.account.errors.AccountError; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.Consts; +import ru.spcex.clearing.platform.messaging.domain.cud.account.AccountNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.account.AccountUpdateRequest; import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountSdf01Request; import ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01.AccountSdfRequestPart; import ru.spcex.clearing.platform.messaging.domain.cud.balance.AccountSdfToStatementRequestPart; import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest; import ru.spcex.clearing.platform.messaging.service.QueueConsumer; import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate; +import ru.spcex.clearing.platform.messaging.service.Status; import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; +import ru.spcex.clearing.util.security.UserRoleVerification; +import ru.spcex.clearing.validation.common.ValidationHelper; +import ru.spcex.platform.enumeration.Allowed; +import ru.spcex.platform.enumeration.ClearingCategory; 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.utils.enumeration.EnumMessage; +import ru.spcex.platform.utils.enumeration.IEnumKey; +import ru.spcex.platform.utils.enumeration.IMessageResolver; +import ru.spcex.platform.utils.validation.IValidator; import java.util.ArrayList; +import java.util.Collection; import java.util.List; +import java.util.function.Function; @Service public class AccountService extends QueueConsumer implements InitializingBean { private final Logger log = LoggerFactory.getLogger(getClass()); private final Imdg accountMap; + private final Imdg clearingMemberCategoryMap; + private final Imdg relationMap; private final KafkaSender kafkaSender; + private final IMessageResolver messageResolver; + private final UserRoleVerification userRoleVerification; + private final ValidationHelper validationHelper; + private final Function accountNewRequestValidator; + private final Function accountUpdateRequestValidator; + private final Function accountBlockRequestValidator; @Autowired - public AccountService(Consumer kafkaQueue, ImdgProvider imdgProvider, KafkaSender kafkaSender) { + public AccountService(Consumer kafkaQueue, + ImdgProvider imdgProvider, + KafkaSender kafkaSender, + IMessageResolver messageResolver, + UserRoleVerification userRoleVerification, + ValidationHelper validationHelper, + @Qualifier("accountNewRequestValidator") + Function accountNewRequestValidator, + @Qualifier("accountUpdateRequestValidator") + Function accountUpdateRequestValidator, + @Qualifier("accountBlockRequestValidator") + Function accountBlockRequestValidator) { super(kafkaQueue); - this.accountMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class); + this.accountMap = imdgProvider.getImdg( + IMDGDistributedNames.Map_Account, Account.class + ); + this.clearingMemberCategoryMap = imdgProvider.getImdg( + IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class + ); + this.relationMap = imdgProvider.getImdg( + IMDGDistributedNames.Map_Relation, Relation.class + ); this.kafkaSender = kafkaSender; + this.messageResolver = messageResolver; + this.userRoleVerification = userRoleVerification; + this.validationHelper = validationHelper; + this.accountNewRequestValidator = accountNewRequestValidator; + this.accountUpdateRequestValidator = accountUpdateRequestValidator; + this.accountBlockRequestValidator = accountBlockRequestValidator; } @Override public void afterPropertiesSet() { callback(AccountSdf01Request.class) + .setConsumer(this::accountNewSdf01) + .forDestination(Consts.ACCOUNT_NEW_SDF01, callbacks::put); + callback(AccountNewRequest.class) .setConsumer(this::accountNew) - .forDestination(Consts.ACCOUNT_NEW, callbacks::put); + .forDestination(Consts.DESTINATION_ACCOUNT_NEW, callbacks::put); init(); } - public RequestInfoUpdate accountNew(BaseRequest userRequest) { + public RequestInfoUpdate accountNew(BaseRequest userRequest) { + log.debug("AccountNewRequest received"); + + RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(userRequest); + if (requestInfoUpdate != null) return requestInfoUpdate; + + requestInfoUpdate = validationHelper.validateTillFirstError(userRequest, accountNewRequestValidator); + if (requestInfoUpdate != null) return requestInfoUpdate; + + AccountNewRequest req = userRequest.getRequestPayload(); + + Long companyId = req.getCompanyId(); + ImdgPredicateBuilder clearingMemberCategoryPredicateBuilder = clearingMemberCategoryMap.predicateBuilder(); + ImdgPredicate companyIdEquals = clearingMemberCategoryPredicateBuilder.equals("companyId", companyId); + Collection clearingMemberCategories = clearingMemberCategoryMap.getCollectionObjectsByPredicate(companyIdEquals); + + // todo выяснить у репортера, что делать в такой ситуации (нужна ли отдельная ошибка) + if (clearingMemberCategories.isEmpty()) { + String errMsg = messageResolver.resolve(new EnumMessage(AccountError.WrongFieldValue, "companyId")); + return new RequestInfoUpdate() + .setId(userRequest.getId()) + .setStatus(Status.Error) + .setMessage(errMsg); + } + if (clearingMemberCategories.size() > 1) { + log.warn("ClearingMemberCategory for companyId {} contains multiply elements, use first", companyId); + } + + ImdgPredicateBuilder relationPredicateBuilder = relationMap.predicateBuilder(); + ImdgPredicate consumerIdPredicate = relationPredicateBuilder.equals("consumerId", companyId); + ImdgPredicate servicePredicate = null; + ClearingMemberCategory clearingMemberCategory = clearingMemberCategories.iterator().next(); + String clearingCategoryValue = clearingMemberCategory.getClearingMemberCategory(); + if (IEnumKey.contains(clearingCategoryValue, ClearingCategory.B, ClearingCategory.I, ClearingCategory.V)) { + servicePredicate = relationPredicateBuilder.equals("service", ru.spcex.platform.enumeration.Service.MKR.getKey()); + } else if (IEnumKey.contains(clearingCategoryValue, ClearingCategory.F, ClearingCategory.C)) { + servicePredicate = relationPredicateBuilder.equals("service", ru.spcex.platform.enumeration.Service.FOND.getKey()); + } else { + // todo выяснить у репортера, что делать в такой ситуации + String errMsg = messageResolver.resolve(new EnumMessage(AccountError.WrongFieldValue, "companyId")); + return new RequestInfoUpdate() + .setId(userRequest.getId()) + .setStatus(Status.Error) + .setMessage(errMsg); + } + ImdgPredicate finalRelationPredicate = relationPredicateBuilder.and(consumerIdPredicate, servicePredicate); + Collection relations = relationMap.getCollectionObjectsByPredicate(finalRelationPredicate); + if (relations.isEmpty()) { + String errMsg = messageResolver.resolve(new EnumMessage(AccountError.WrongFieldValue, "companyId")); + return new RequestInfoUpdate() + .setId(userRequest.getId()) + .setStatus(Status.Error) + .setMessage(errMsg); + } + if (relations.size() > 1) { + log.warn("Relation for consumerId {} contains multiply elements, use first", companyId); + } + Relation relation = relations.iterator().next(); + + Account account = new Account(); + account.setAccount(req.getAccount()); + account.setAccountType(req.getAccountType()); + account.setRelationId(relation.getId()); + account.setStatus(req.getStatus()); + account.setProcessingSign(Allowed.ALLOWED.getKey()); + account.setCompanyId(req.getCompanyId()); + Long id = accountMap.insert(account); + + log.debug("successfully processed, new account id {}", id); + return null; + } + + public RequestInfoUpdate accountNewSdf01(BaseRequest userRequest) { log.debug("AccountSdf01Request received"); // todo add validation (create task for that?) diff --git a/clearing-parent/account-service/src/test/java/ru/spcex/clearing/account/service/AccountServiceTest.java b/clearing-parent/account-service/src/test/java/ru/spcex/clearing/account/service/AccountServiceTest.java index 50e495b0b..89d62b90c 100644 --- a/clearing-parent/account-service/src/test/java/ru/spcex/clearing/account/service/AccountServiceTest.java +++ b/clearing-parent/account-service/src/test/java/ru/spcex/clearing/account/service/AccountServiceTest.java @@ -50,7 +50,7 @@ class AccountServiceTest { public static final MatcherFactory.Matcher ACCOUNT_MATCHER = usingIgnoringFieldsComparator(); public static final MatcherFactory.Matcher REQUEST_INFO_MATCHER_MATCHER = usingIgnoringFieldsComparator("created"); private static final int PARTITION = 0; - private static final String TOPIC_ACCOUNT_NEW = Consts.ACCOUNT_NEW; + private static final String TOPIC_ACCOUNT_NEW = Consts.ACCOUNT_NEW_SDF01; private static final String account = "123456789123"; @Autowired AccountService accountService; @@ -64,7 +64,7 @@ class AccountServiceTest { private MockProducer producer; /** - * {@link AccountService#accountNew(BaseRequest)}
+ * {@link AccountService#accountNewSdf01(BaseRequest)}
* Тест проверяет создание сущности {@link BaseRequest} в Hazelcast при передаче из Apache Kafka.
* Входной запрос {@link AccountSdf01Request}:
* {@link AccountSdfRequestPart#setSdfId} - текущий Id
diff --git a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/StatementService.java b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/StatementService.java index 37495b876..c2125fe09 100644 --- a/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/StatementService.java +++ b/clearing-parent/balance-service/src/main/java/ru/spcex/clearing/balance/service/StatementService.java @@ -106,7 +106,7 @@ public class StatementService extends QueueConsumer implements InitializingBean exportRequest.setNameOfTable(service.exportTableName()); kafkaReqProducer.sendRequestToQueue(Consts.EXPORT_PROCESS, exportRequest); } else { - kafkaReqProducer.sendRequestToQueue(Consts.ACCOUNT_NEW, createAccountsRequest(statementRequest.getGroupId(), res.getAccountRequests())); + kafkaReqProducer.sendRequestToQueue(Consts.ACCOUNT_NEW_SDF01, createAccountsRequest(statementRequest.getGroupId(), res.getAccountRequests())); } } diff --git a/clearing-parent/balance-service/src/test/java/ru/spcex/clearing/balance/service/StatementServiceServiceTest.java b/clearing-parent/balance-service/src/test/java/ru/spcex/clearing/balance/service/StatementServiceServiceTest.java index 5d39a8926..9759178f4 100644 --- a/clearing-parent/balance-service/src/test/java/ru/spcex/clearing/balance/service/StatementServiceServiceTest.java +++ b/clearing-parent/balance-service/src/test/java/ru/spcex/clearing/balance/service/StatementServiceServiceTest.java @@ -130,7 +130,7 @@ class StatementServiceServiceTest extends AbstractServiceTest { BaseRequest baseRequest = (BaseRequest) producerRecord.getValue().value(); RequestInfo resultRequestInfo = requestInfoImdg.getSingleObjectByID(baseRequest.getId()); - assertEquals(Consts.ACCOUNT_NEW, producerRecord.getValue().topic()); + assertEquals(Consts.ACCOUNT_NEW_SDF01, producerRecord.getValue().topic()); assertNotNull(baseRequest); assertNotNull(resultRequestInfo); } diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Service.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Service.java index 2fd271c0a..b84fde000 100644 --- a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Service.java +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/Service.java @@ -3,7 +3,7 @@ package ru.spcex.platform.enumeration; import ru.spcex.platform.utils.enumeration.IEnumKey; public enum Service implements IEnumKey { - MKR("MKR"); + MKR("MKR"), FOND("FOND"); private final String key; diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/Consts.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/Consts.java index fddd74586..4eeca343f 100644 --- a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/Consts.java +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/Consts.java @@ -57,6 +57,11 @@ public interface Consts { String DESTINATION_BANK_ACCOUNT_DELETE = "bank-account-delete"; String DESTINATION_BANK_ACCOUNT_UPDATE = "bank-account-update"; String DESTINATION_BANK_ACCOUNT_NEW = "bank-account-new"; + + String DESTINATION_ACCOUNT_NEW = "account-new"; + String DESTINATION_ACCOUNT_UPDATE = "account-update"; + String DESTINATION_ACCOUNT_BLOCK = "account-block"; + String DESTINATION_RELATION_UPDATE = "relation-update"; String DESTINATION_PROFILE_DOCUMENT_NEW = "profile-document-new"; String DESTINATION_PROFILE_DOCUMENT_UPDATE = "profile-document-update"; @@ -75,7 +80,7 @@ public interface Consts { String SDF03_PROCESS = "sdf03-process"; String SDF11_PROCESS = "sdf11-process"; String EXPORT_PROCESS = "export-process"; - String ACCOUNT_NEW = "account-new"; + String ACCOUNT_NEW_SDF01 = "account-new-sdf01"; String ACCOUNT_TERMINATION = "account-termination"; String BALANCE_ACCOUNT_NEW = "balance-account-new"; String BALANCE_ACCOUNT_UPDATE = "balance-account-update";