diff --git a/clearing-parent/account-service/pom.xml b/clearing-parent/account-service/pom.xml index f2bfdaf25..a9fae56b7 100644 --- a/clearing-parent/account-service/pom.xml +++ b/clearing-parent/account-service/pom.xml @@ -65,6 +65,14 @@ spring-boot-test test + + ru.spcex.clearing + security-util + + + ru.spcex.clearing + clearing-validation + diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/BeanConfiguration.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/BeanConfiguration.java new file mode 100644 index 000000000..9a7793082 --- /dev/null +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/BeanConfiguration.java @@ -0,0 +1,26 @@ +package ru.spcex.clearing.account.config; + +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Scope; +import ru.spcex.clearing.account.errors.AccountError; +import ru.spcex.clearing.util.security.UserRoleVerification; +import ru.spcex.platform.enumeration.UserRole; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.utils.enumeration.IMessageResolver; +import ru.spcex.platform.utils.enumeration.SimpleMessageResolver; + +@Configuration +public class BeanConfiguration { + @Bean + public IMessageResolver messageResolver() { + return new SimpleMessageResolver(); + } + + @Bean + @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public UserRoleVerification userRoleVerification(ImdgProvider imdgProvider, IMessageResolver messageResolver) { + return new UserRoleVerification(imdgProvider, messageResolver, UserRole.Admin, AccountError.UserVerifyDenial); + } +} diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/ErrorResolverConfig.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/ErrorResolverConfig.java deleted file mode 100644 index 7cf2db17a..000000000 --- a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/ErrorResolverConfig.java +++ /dev/null @@ -1,14 +0,0 @@ -package ru.spcex.clearing.account.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import ru.spcex.platform.utils.enumeration.IMessageResolver; -import ru.spcex.platform.utils.enumeration.SimpleMessageResolver; - -@Configuration -public class ErrorResolverConfig { - @Bean - public IMessageResolver messageResolver() { - return new SimpleMessageResolver(); - } -} diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/ValidationConfig.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/ValidationConfig.java deleted file mode 100644 index f6e0e1deb..000000000 --- a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/ValidationConfig.java +++ /dev/null @@ -1,70 +0,0 @@ -package ru.spcex.clearing.account.config; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -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.AccountBalance; -import ru.clearing.classes.statics.data.company.Company; -import ru.clearing.classes.statics.data.company.CompanySymbols; -import ru.spcex.clearing.account.validation.AccountValidationRule; -import ru.spcex.clearing.imdg.IMDGDistributedNames; -import ru.spcex.clearing.platform.messaging.domain.cud.account.BankAccountNewRequest; -import ru.spcex.platform.classes.base.SpcexObjectBase; -import ru.spcex.platform.imdg.api.Imdg; -import ru.spcex.platform.imdg.api.ImdgProvider; -import ru.spcex.platform.imdg.validation.ImdgValidationContext; -import ru.spcex.platform.utils.validation.IValidator; -import ru.spcex.platform.utils.validation.ValidatorImpl; - -import java.util.HashMap; -import java.util.Map; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Function; - -@Configuration -public class ValidationConfig { - Logger log = LoggerFactory.getLogger(getClass()); - private final Map> imdgs; - - public ValidationConfig(ImdgProvider imdgProvider) { - log.debug("Init validator config"); - this.imdgs = new HashMap<>(); - BiConsumer> addImdg = (s, aClass) -> imdgs.put(s, imdgProvider.getImdg(s, aClass)); - addImdg.accept(IMDGDistributedNames.Map_Account, Account.class); - addImdg.accept(IMDGDistributedNames.Map_Company, Company.class); - addImdg.accept(IMDGDistributedNames.Map_CompanySymbols, CompanySymbols.class); - addImdg.accept(IMDGDistributedNames.Map_AccountBalance, AccountBalance.class); - } - - /** - * чтобы во всех валидаторах был один экземпляр Imdg - */ - private Imdg getImdg(String key) { - return imdgs.get(key); - } - - @Bean("bankAccountNewRequestValidator") - public Function bankAccountNewRequestValidator() { - log.debug("Create validator bankAccountNewRequestValidator"); - return bankAccountNewRequest -> { - ImdgValidationContext context = new ImdgValidationContext<>(); - context.setValidatedObject(bankAccountNewRequest); - Consumer addImdg = (s) -> context.addImdg(s, getImdg(s)); - addImdg.accept(IMDGDistributedNames.Map_Account); - addImdg.accept(IMDGDistributedNames.Map_Company); - addImdg.accept(IMDGDistributedNames.Map_AccountBalance); - - return new ValidatorImpl<>(context, - AccountValidationRule.RequiredFields, - AccountValidationRule.RubRequiredFields, - AccountValidationRule.AccountIsNew, - AccountValidationRule.CompanyPresent - ); - }; - //todo после слияния ветки CLR_51_57 переписать на использование DictionaryPresentRule, FieldRequiredRule - } - -} 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 new file mode 100644 index 000000000..cb654bc0e --- /dev/null +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/AccountValidationConfig.java @@ -0,0 +1,174 @@ +package ru.spcex.clearing.account.config.validation; + +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.company.Company; +import ru.clearing.platform.dictionary.AccountTypeDictionary; +import ru.spcex.clearing.account.errors.AccountError; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.cud.account.CorrespondentAccountNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.account.CorrespondentAccountUpdateRequest; +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; +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.WorkflowStatus; +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.validation.ImdgValidationContext; +import ru.spcex.platform.utils.enumeration.IErrorEnumId; +import ru.spcex.platform.utils.validation.IValidator; +import ru.spcex.platform.utils.validation.ValidatorImpl; + +import java.util.Collection; +import java.util.Map; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.Function; + +@Configuration +public class AccountValidationConfig { + + @Bean("correspondentAccountNewRequestValidator") + public Function correspondentAccountNewRequestValidator( + Map> imdgForValidation + ) { + return correspondentAccountNewRequest -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(correspondentAccountNewRequest); + Consumer addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s)); + addImdg.accept(IMDGDistributedNames.Map_Company); + addImdg.accept(IMDGDistributedNames.Map_Account); + addImdg.accept(IMDGDistributedNames.Map_AccountTypeDictionary); + return new ValidatorImpl<>(context, + IdPresentRule.instance("companyId", + CorrespondentAccountNewRequest::getCompanyId, + IMDGDistributedNames.Map_Company, + Company.class, + AccountError.RequiredFieldEmpty, + AccountError.CompanyNotFound, + company -> WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus()) ? null : AccountError.CompanyNotActive), + FieldRequiredRule.instance("account", + CorrespondentAccountNewRequest::getAccount, + AccountError.RequiredFieldEmpty, + accountValue -> { + Imdg accountImdg = context.obtainMap( + IMDGDistributedNames.Map_Account, Account.class + ); + ImdgPredicateBuilder pb = accountImdg.predicateBuilder(); + ImdgPredicate accountValuePredicate = pb.equals("account", accountValue); + ImdgPredicate accountStatusPredicate = pb.equals("status", AccountStatus.ACTIVE.getKey()); + ImdgPredicate finalPredicate = pb.and(accountValuePredicate, accountStatusPredicate); + Collection accounts = accountImdg.getCollectionObjectsByPredicate(finalPredicate); + if (accounts.isEmpty()) return null; + return AccountError.AccountAlreadyExist; + }), + FieldRequiredRule.instance("status", + CorrespondentAccountNewRequest::getStatus, + AccountError.RequiredFieldEmpty, + false, + statusValue -> { + if (statusValue == null || AccountStatus.ACTIVE.equalsByKey(statusValue)) return null; + return AccountError.WrongFieldValue; + }), + DictionaryPresentRule.instance("accountType", + CorrespondentAccountNewRequest::getAccountType, + IMDGDistributedNames.Map_AccountTypeDictionary, + AccountTypeDictionary.class, + AccountError.RequiredFieldEmpty, + AccountError.WrongFieldValue, + accountType -> { + if (AccountType.Corr.equalsByKey(accountType.getCode())) return null; + return AccountError.WrongFieldValue; + }) + ); + }; + } + + @Bean("correspondentAccountUpdateRequestValidator") + public Function correspondentAccountUpdateRequestValidator( + Map> imdgForValidation + ) { + return correspondentAccountUpdateRequest -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(correspondentAccountUpdateRequest); + Consumer addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s)); + addImdg.accept(IMDGDistributedNames.Map_Company); + addImdg.accept(IMDGDistributedNames.Map_Account); + addImdg.accept(IMDGDistributedNames.Map_AccountTypeDictionary); + return new ValidatorImpl<>(context, + IdPresentRule.instance("id", + CorrespondentAccountUpdateRequest::getId, + IMDGDistributedNames.Map_Account, + Account.class, + AccountError.RequiredFieldEmpty, + AccountError.AccountNotFound, + account -> { + String statusFromRequest = correspondentAccountUpdateRequest.getStatus(); + if (statusFromRequest != null && !statusFromRequest.equalsIgnoreCase(account.getStatus())) + return AccountError.WrongFieldValue; + return null; + }), + IdPresentRule.instance("companyId", + CorrespondentAccountUpdateRequest::getCompanyId, + IMDGDistributedNames.Map_Company, + Company.class, + AccountError.RequiredFieldEmpty, + AccountError.CompanyNotFound, + false, + company -> { + IErrorEnumId error = WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus()) ? null : AccountError.CompanyNotActive; + error = Objects.equals(company.getId(), correspondentAccountUpdateRequest.getCompanyId()) ? error : AccountError.WrongFieldValue; + return error; + }), + EnumPresentRule.instance("status", + CorrespondentAccountUpdateRequest::getStatus, + AccountStatus.values(), + false, + AccountError.WrongFieldValue, + AccountError.RequiredFieldEmpty), + DictionaryPresentRule.instance("accountType", + CorrespondentAccountUpdateRequest::getAccountType, + IMDGDistributedNames.Map_AccountTypeDictionary, + AccountTypeDictionary.class, + AccountError.RequiredFieldEmpty, + AccountError.WrongFieldValue, + accountType -> { + if (AccountType.Corr.equalsByKey(accountType.getCode())) return null; + return AccountError.WrongFieldValue; + }) + ); + }; + } + + @Bean("correspondentAccountBlockRequestValidator") + public Function correspondentAccountBlockRequestValidator( + Map> imdgForValidation + ) { + return correspondentAccountBlockRequest -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(correspondentAccountBlockRequest); + 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, + account -> { + if (AccountStatus.ACTIVE.equalsByKey(account.getStatus())) return null; + return AccountError.AccountNotActive; + }) + ); + }; + } + +} diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/BankAccountValidationConfig.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/BankAccountValidationConfig.java new file mode 100644 index 000000000..1c2ca6ab6 --- /dev/null +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/BankAccountValidationConfig.java @@ -0,0 +1,164 @@ +package ru.spcex.clearing.account.config.validation; + +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.Company; +import ru.clearing.platform.dictionary.CurrencyCodeDictionary; +import ru.spcex.clearing.account.errors.AccountError; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.cud.account.BankAccountNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.account.BankAccountUpdateRequest; +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.FieldRequiredRule; +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.WorkflowStatus; +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.validation.ImdgValidationContext; +import ru.spcex.platform.utils.validation.IValidator; +import ru.spcex.platform.utils.validation.ValidatorImpl; + +import java.util.Collection; +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Function; + +@Configuration +public class BankAccountValidationConfig { + + @Bean("bankAccountNewRequestValidator") + public Function bankAccountNewRequestValidator( + Map> imdgForValidation + ) { + return bankAccountNewRequest -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(bankAccountNewRequest); + Consumer addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s)); + addImdg.accept(IMDGDistributedNames.Map_Account); + addImdg.accept(IMDGDistributedNames.Map_BankAccount); + addImdg.accept(IMDGDistributedNames.Map_Company); + addImdg.accept(IMDGDistributedNames.Map_CurrencyCodeDictionary); + return new ValidatorImpl<>(context, + IdPresentRule.instance("companyId", + BankAccountNewRequest::getCompanyId, + IMDGDistributedNames.Map_Company, + Company.class, + AccountError.RequiredFieldEmpty, + AccountError.CompanyNotFound, + company -> WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus()) ? null : AccountError.CompanyNotActive), + FieldRequiredRule.instance("account", + BankAccountNewRequest::getAccount, + AccountError.RequiredFieldEmpty, + accountValue -> { + Imdg accountImdg = context.obtainMap( + IMDGDistributedNames.Map_Account, Account.class + ); + ImdgPredicateBuilder pb = accountImdg.predicateBuilder(); + ImdgPredicate accountValuePredicate = pb.equals("account", accountValue); + ImdgPredicate accountStatusPredicate = pb.equals("status", AccountStatus.ACTIVE.getKey()); + ImdgPredicate accountTypePredicate = pb.equals("accountType", AccountType.Bank.getKey()); + ImdgPredicate finalPredicate = pb.and(accountValuePredicate, + accountStatusPredicate, + accountTypePredicate); + Collection accounts = accountImdg.getCollectionObjectsByPredicate(finalPredicate); + if (accounts.isEmpty()) return null; + return AccountError.AccountAlreadyExist; + }), + DictionaryPresentRule.instance("currency", + BankAccountNewRequest::getCurrency, + IMDGDistributedNames.Map_CurrencyCodeDictionary, + CurrencyCodeDictionary.class, + AccountError.RequiredFieldEmpty, + AccountError.WrongFieldValue), + FieldRequiredRule.instance("bankIdentificationCode", + BankAccountNewRequest::getBankIdentificationCode, + AccountError.RequiredFieldEmpty), + FieldRequiredRule.instance("bankName", + BankAccountNewRequest::getBankName, + AccountError.RequiredFieldEmpty), + FieldRequiredRule.instance("destination", + BankAccountNewRequest::getDestination, + AccountError.RequiredFieldEmpty) + ); + }; + } + + @Bean("bankAccountUpdateRequestValidator") + public Function bankAccountUpdateRequestValidator( + Map> imdgForValidation + ) { + return bankAccountUpdateRequest -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(bankAccountUpdateRequest); + Consumer addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s)); + addImdg.accept(IMDGDistributedNames.Map_Account); + addImdg.accept(IMDGDistributedNames.Map_CurrencyCodeDictionary); + addImdg.accept(IMDGDistributedNames.Map_BankAccount); + addImdg.accept(IMDGDistributedNames.Map_Company); + return new ValidatorImpl<>(context, + IdPresentRule.instance("id", + BankAccountUpdateRequest::getId, + IMDGDistributedNames.Map_BankAccount, + BankAccount.class, + AccountError.RequiredFieldEmpty, + AccountError.AccountNotFound, + bankAccount -> { + Long accountId = bankAccount.getAccountId(); + Imdg accountImdg = context.obtainMap( + IMDGDistributedNames.Map_Account, Account.class + ); + Account account = accountImdg.getSingleObjectByID(accountId); + if (account == null) return AccountError.AccountNotFound; + if (!AccountStatus.ACTIVE.equalsByKey(account.getStatus())) return AccountError.AccountNotActive; + return null; + }), + DictionaryPresentRule.instance("currency", + BankAccountUpdateRequest::getCurrency, + IMDGDistributedNames.Map_CurrencyCodeDictionary, + CurrencyCodeDictionary.class, + AccountError.RequiredFieldEmpty, + AccountError.WrongFieldValue, + false) + ); + }; + } + + @Bean("bankAccountBlockRequestValidator") + public Function bankAccountBlockRequestValidator( + Map> imdgForValidation + ) { + return bankAccountBlockRequest -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(bankAccountBlockRequest); + Consumer addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s)); + addImdg.accept(IMDGDistributedNames.Map_BankAccount); + addImdg.accept(IMDGDistributedNames.Map_Account); + return new ValidatorImpl<>(context, + IdPresentRule.instance("id", + CommonDeleteRequest::getId, + IMDGDistributedNames.Map_BankAccount, + BankAccount.class, + AccountError.RequiredFieldEmpty, + AccountError.AccountNotFound, + bankAccount -> { + Long accountId = bankAccount.getAccountId(); + Imdg accountImdg = context.obtainMap( + IMDGDistributedNames.Map_Account, Account.class + ); + Account account = accountImdg.getSingleObjectByID(accountId); + if (account == null) return AccountError.AccountNotFound; + if (!AccountStatus.ACTIVE.equalsByKey(account.getStatus())) return AccountError.AccountNotActive; + return null; + }) + ); + }; + } + +} diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/ClearingAccountValidationConfig.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/ClearingAccountValidationConfig.java new file mode 100644 index 000000000..cb3c2368e --- /dev/null +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/ClearingAccountValidationConfig.java @@ -0,0 +1,136 @@ +package ru.spcex.clearing.account.config.validation; + +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.company.Company; +import ru.clearing.platform.dictionary.ClearingAccountTypeDictionary; +import ru.spcex.clearing.account.errors.AccountError; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.cud.account.ClearingAccountNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.account.ClearingAccountUpdateRequest; +import ru.spcex.clearing.validation.common.rules.DictionaryPresentRule; +import ru.spcex.clearing.validation.common.rules.FieldRequiredRule; +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.WorkflowStatus; +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.validation.ImdgValidationContext; +import ru.spcex.platform.utils.validation.IValidator; +import ru.spcex.platform.utils.validation.ValidatorImpl; + +import java.util.Collection; +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Function; + +@Configuration +public class ClearingAccountValidationConfig { + + @Bean("clearingAccountNewRequestValidator") + public Function clearingAccountNewRequestValidator( + Map> imdgForValidation + ) { + return clearingAccountNewRequest -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(clearingAccountNewRequest); + Consumer addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s)); + addImdg.accept(IMDGDistributedNames.Map_Account); + addImdg.accept(IMDGDistributedNames.Map_Company); + addImdg.accept(IMDGDistributedNames.Map_ClearingAccount); + addImdg.accept(IMDGDistributedNames.Map_ClearingAccountTypeDictionary); + return new ValidatorImpl<>(context, + IdPresentRule.instance("companyId", + ClearingAccountNewRequest::getCompanyId, + IMDGDistributedNames.Map_Company, + Company.class, + AccountError.RequiredFieldEmpty, + AccountError.CompanyNotFound, + company -> !WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus()) ? AccountError.CompanyNotActive : null), + FieldRequiredRule.instance("account", + ClearingAccountNewRequest::getAccount, + AccountError.RequiredFieldEmpty, + accountValue -> { + Imdg accountImdg = context.obtainMap( + IMDGDistributedNames.Map_Account, Account.class + ); + ImdgPredicateBuilder pb = accountImdg.predicateBuilder(); + ImdgPredicate accountValuePredicate = pb.equals("account", accountValue); + ImdgPredicate accountStatusPredicate = pb.equals("status", AccountStatus.ACTIVE.getKey()); + ImdgPredicate accountTypePredicate = pb.equals("accountType", AccountType.Clrn.getKey()); + ImdgPredicate finalPredicate = pb.and(accountValuePredicate, + accountStatusPredicate, + accountTypePredicate); + Collection accounts = accountImdg.getCollectionObjectsByPredicate(finalPredicate); + if (accounts.isEmpty()) return null; + return AccountError.AccountAlreadyExist; + }), + DictionaryPresentRule.instance("clearingAccountType", + ClearingAccountNewRequest::getClearingAccountType, + IMDGDistributedNames.Map_ClearingAccountTypeDictionary, + ClearingAccountTypeDictionary.class, + AccountError.RequiredFieldEmpty, + AccountError.WrongFieldValue) + ); + }; + } + + + @Bean("clearingAccountUpdateRequestValidator") + public Function clearingAccountUpdateRequestValidator( + Map> imdgForValidation + ) { + return clearingAccountUpdateRequest -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(clearingAccountUpdateRequest); + Consumer addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s)); + addImdg.accept(IMDGDistributedNames.Map_Account); + addImdg.accept(IMDGDistributedNames.Map_Company); + addImdg.accept(IMDGDistributedNames.Map_ClearingAccount); + addImdg.accept(IMDGDistributedNames.Map_ClearingAccountTypeDictionary); + return new ValidatorImpl<>(context, + FieldRequiredRule.instance("account", + ClearingAccountUpdateRequest::getAccount, + AccountError.RequiredFieldEmpty, + accountValue -> { + Imdg accountImdg = context.obtainMap( + IMDGDistributedNames.Map_Account, Account.class + ); + ImdgPredicateBuilder pb = accountImdg.predicateBuilder(); + ImdgPredicate accountValuePredicate = pb.equals("account", accountValue); + ImdgPredicate accountStatusPredicate = pb.equals("status", AccountStatus.ACTIVE.getKey()); + ImdgPredicate accountTypePredicate = pb.equals("accountType", AccountType.Clrn.getKey()); + ImdgPredicate finalPredicate = pb.and(accountValuePredicate, + accountStatusPredicate, + accountTypePredicate); + Collection accounts = accountImdg.getCollectionObjectsByPredicate(finalPredicate); + if (accounts.isEmpty()) return AccountError.AccountNotFound; + return null; + }), + FieldRequiredRule.instance("status", + ClearingAccountUpdateRequest::getStatus, + AccountError.RequiredFieldEmpty, + statusValue -> { + if (statusValue == 0 || statusValue == 1 || statusValue == 2) return null; + return AccountError.WrongFieldValue; + }), + FieldRequiredRule.instance("deal", + ClearingAccountUpdateRequest::getDeal, + AccountError.RequiredFieldEmpty, + dealValue -> { + Imdg companyImdg = context.obtainMap( + IMDGDistributedNames.Map_Company, Company.class + ); + Company company = companyImdg.getSingleObjectByFieldValues(Map.of("tradingCode", dealValue)); + if (company == null) return AccountError.WrongFieldValue; + return null; + }) + ); + }; + } + +} diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/DepoAccountValidationConfig.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/DepoAccountValidationConfig.java new file mode 100644 index 000000000..10277912b --- /dev/null +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/DepoAccountValidationConfig.java @@ -0,0 +1,76 @@ +package ru.spcex.clearing.account.config.validation; + +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.company.Company; +import ru.spcex.clearing.account.errors.AccountError; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.cud.account.DepoAccountNewRequest; +import ru.spcex.clearing.validation.common.rules.FieldRequiredRule; +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.WorkflowStatus; +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.validation.ImdgValidationContext; +import ru.spcex.platform.utils.validation.IValidator; +import ru.spcex.platform.utils.validation.ValidatorImpl; + +import java.util.Collection; +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Function; + +@Configuration +public class DepoAccountValidationConfig { + + @Bean("depoAccountNewRequestValidator") + public Function depoAccountNewRequestValidator( + Map> imdgForValidation + ) { + return depoAccountNewRequest -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(depoAccountNewRequest); + Consumer addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s)); + addImdg.accept(IMDGDistributedNames.Map_Company); + addImdg.accept(IMDGDistributedNames.Map_Account); + addImdg.accept(IMDGDistributedNames.Map_DepoAccount); + return new ValidatorImpl<>(context, + IdPresentRule.instance("companyId", + DepoAccountNewRequest::getCompanyId, + IMDGDistributedNames.Map_Company, + Company.class, + AccountError.RequiredFieldEmpty, + AccountError.CompanyNotFound, + company -> !WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus()) ? AccountError.CompanyNotActive : null), + FieldRequiredRule.instance("account", + DepoAccountNewRequest::getAccount, + AccountError.RequiredFieldEmpty, + accountValue -> { + Imdg accountImdg = context.obtainMap( + IMDGDistributedNames.Map_Account, Account.class + ); + ImdgPredicateBuilder pb = accountImdg.predicateBuilder(); + ImdgPredicate accountValuePredicate = pb.equals("account", accountValue); + ImdgPredicate accountStatusPredicate = pb.equals("status", AccountStatus.ACTIVE.getKey()); + ImdgPredicate accountTypePredicate = pb.equals("accountType", AccountType.Clrn.getKey()); + ImdgPredicate finalPredicate = pb.and(accountValuePredicate, + accountStatusPredicate, + accountTypePredicate); + Collection accounts = accountImdg.getCollectionObjectsByPredicate(finalPredicate); + if (accounts.isEmpty()) return null; + return AccountError.AccountAlreadyExist; + }), + FieldRequiredRule.instance("depoAccountType", + DepoAccountNewRequest::getDepoAccountType, + AccountError.RequiredFieldEmpty) + ); + }; + } + + +} diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/InformationAccountValidationConfig.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/InformationAccountValidationConfig.java new file mode 100644 index 000000000..37d2712f5 --- /dev/null +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/InformationAccountValidationConfig.java @@ -0,0 +1,60 @@ +package ru.spcex.clearing.account.config.validation; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import ru.clearing.classes.statics.data.account.InformationAccount; +import ru.clearing.classes.statics.data.company.Company; +import ru.spcex.clearing.account.errors.AccountError; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.cud.account.InformationAccountNewRequest; +import ru.spcex.clearing.validation.common.rules.IdPresentRule; +import ru.spcex.platform.classes.base.SpcexObjectBase; +import ru.spcex.platform.enumeration.WorkflowStatus; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.validation.ImdgValidationContext; +import ru.spcex.platform.utils.validation.IValidator; +import ru.spcex.platform.utils.validation.ValidatorImpl; + +import java.util.Collection; +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Function; + +@Configuration +public class InformationAccountValidationConfig { + + @Bean("informationAccountNewRequestValidator") + public Function informationAccountNewRequestValidator( + Map> imdgForValidation + ) { + return informationAccountNewRequest -> { + ImdgValidationContext context = new ImdgValidationContext<>(); + context.setValidatedObject(informationAccountNewRequest); + Consumer addImdg = (s) -> context.addImdg(s, imdgForValidation.get(s)); + addImdg.accept(IMDGDistributedNames.Map_Company); + addImdg.accept(IMDGDistributedNames.Map_InformationAccount); + return new ValidatorImpl<>(context, + IdPresentRule.instance("companyId", + InformationAccountNewRequest::getCompanyId, + IMDGDistributedNames.Map_Company, + Company.class, + AccountError.RequiredFieldEmpty, + AccountError.CompanyNotFound, + company -> { + if (!WorkflowStatus.Active.equalsByKey(company.getWorkflowStatus())) + return AccountError.CompanyNotActive; + Long companyId = company.getId(); + Imdg informationAccountImdg = context.obtainMap( + IMDGDistributedNames.Map_InformationAccount, InformationAccount.class + ); + Collection infoAccounts = informationAccountImdg.getCollectionObjectsByFieldValues( + Map.of("companyId", companyId) + ); + if (infoAccounts.isEmpty()) return null; + return AccountError.InfoAccountAlreadyExist; + }) + ); + }; + } + +} 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 new file mode 100644 index 000000000..d6189008f --- /dev/null +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/config/validation/ValidationConfig.java @@ -0,0 +1,53 @@ +package ru.spcex.clearing.account.config.validation; + + +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.account.ClearingAccount; +import ru.clearing.classes.statics.data.account.InformationAccount; +import ru.clearing.classes.statics.data.company.ClearingMemberCategory; +import ru.clearing.classes.statics.data.company.Company; +import ru.clearing.platform.dictionary.AccountTypeDictionary; +import ru.clearing.platform.dictionary.ClearingAccountTypeDictionary; +import ru.clearing.platform.dictionary.CurrencyCodeDictionary; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.validation.common.ValidationHelper; +import ru.spcex.platform.classes.base.SpcexObjectBase; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.utils.enumeration.IMessageResolver; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.BiConsumer; + +@Configuration +public class ValidationConfig { + + @Bean("imdgForValidation") + public Map> imdgForValidation(ImdgProvider imdgProvider) { + final Map> imdg = new HashMap<>(); + 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_ClearingAccountTypeDictionary, ClearingAccountTypeDictionary.class); + addImdg.accept(IMDGDistributedNames.Map_Account, Account.class); + addImdg.accept(IMDGDistributedNames.Map_InformationAccount, InformationAccount.class); + addImdg.accept(IMDGDistributedNames.Map_AccountTypeDictionary, AccountTypeDictionary.class); + addImdg.accept(IMDGDistributedNames.Map_BankAccount, BankAccount.class); + addImdg.accept(IMDGDistributedNames.Map_CurrencyCodeDictionary, CurrencyCodeDictionary.class); + addImdg.accept(IMDGDistributedNames.Map_ClearingAccount, ClearingAccount.class); + + return imdg; + } + + @Bean("validationHelper") + public ValidationHelper validationHelper(IMessageResolver messageResolver) { + return new ValidationHelper(messageResolver); + } + +} + 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 122609131..82789613d 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 @@ -3,12 +3,18 @@ package ru.spcex.clearing.account.errors; import ru.spcex.platform.utils.enumeration.IErrorEnumId; public enum AccountError implements IErrorEnumId { + UserVerifyDenial(5001L), + RequiredFieldEmpty(5002L), WrongFieldValue(5004L), AccountAlreadyExist(5010L), + AccountNotFound(5011L), + AccountNotActive(5012L), CompanyNotFound(5013L), CompanyNotActive(5014L), - + InfoAccountAlreadyExist(5015L), + ClearingCategoryNotFound(5019L) ; + private final Long id; AccountError(Long id) { 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 36fea1fe3..81df09673 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 @@ -1,51 +1,192 @@ package ru.spcex.clearing.account.service; import org.apache.kafka.clients.consumer.Consumer; +import org.apache.kafka.clients.producer.Producer; 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.CorrespondentAccountNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.account.CorrespondentAccountUpdateRequest; 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.AccountStatus; +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.time.Instant; 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) { - super(kafkaQueue); - this.accountMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class); + public AccountService(Consumer kafkaQueue, + Producer kafkaProducer, + ImdgProvider imdgProvider, + KafkaSender kafkaSender, + IMessageResolver messageResolver, + UserRoleVerification userRoleVerification, + ValidationHelper validationHelper, + @Qualifier("correspondentAccountNewRequestValidator") + Function accountNewRequestValidator, + @Qualifier("correspondentAccountUpdateRequestValidator") + Function accountUpdateRequestValidator, + @Qualifier("correspondentAccountBlockRequestValidator") + Function accountBlockRequestValidator) { + super(kafkaQueue, kafkaProducer); + 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::accountNew) - .forDestination(Consts.ACCOUNT_NEW, callbacks::put); + .setConsumer(this::accountNewSdf01) + .forDestination(Consts.ACCOUNT_NEW_SDF01, callbacks::put); + callback(CorrespondentAccountNewRequest.class) + .setConsumer(this::accountCorrespondentNew) + .forDestination(Consts.DESTINATION_CORRESPONDENT_ACCOUNT_NEW, callbacks::put); + callback(CorrespondentAccountUpdateRequest.class) + .setConsumer(this::correspondentAccountUpdate) + .forDestination(Consts.DESTINATION_CORRESPONDENT_ACCOUNT_UPDATE, callbacks::put); + callback(CommonDeleteRequest.class) + .setConsumer(this::correspondentAccountBlock) + .forDestination(Consts.DESTINATION_CORRESPONDENT_ACCOUNT_BLOCK, callbacks::put); init(); } - private void accountNew(BaseRequest userRequest) { - AccountSdf01Request req = userRequest.getRequestPayload(); + + public RequestInfoUpdate accountCorrespondentNew(BaseRequest userRequest) { + log.debug("CorrespondentAccountNewRequest received"); + + RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(userRequest); + if (requestInfoUpdate != null) return requestInfoUpdate; + + requestInfoUpdate = validationHelper.validateTillFirstError(userRequest, accountNewRequestValidator); + if (requestInfoUpdate != null) return requestInfoUpdate; + + CorrespondentAccountNewRequest req = userRequest.getRequestPayload(); + + Instant now = Instant.now(); + Account account = new Account(); + account.setCompanyId(req.getCompanyId()); + account.setAccount(req.getAccount()); + account.setAccountType(req.getAccountType()); + account.setStatus(req.getStatus()); + account.setCreated(now); + account.setUpdated(now); + + requestInfoUpdate = fillAccountFromRelation(account, userRequest.getId()); + if (requestInfoUpdate != null) return requestInfoUpdate; + + Long newId = accountMap.insert(account); + log.debug("successfully processed, new account id {}", newId); + return null; + } + + public RequestInfoUpdate correspondentAccountUpdate(BaseRequest userRequest) { + log.debug("CorrespondentAccountUpdateRequest received"); + + RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(userRequest); + if (requestInfoUpdate != null) return requestInfoUpdate; + + requestInfoUpdate = validationHelper.validateTillFirstError(userRequest, accountUpdateRequestValidator); + if (requestInfoUpdate != null) return requestInfoUpdate; + + CorrespondentAccountUpdateRequest request = userRequest.getRequestPayload(); + + Account account = accountMap.getSingleObjectByID(request.getId()); + + if (request.getStatus() != null) account.setStatus(request.getStatus()); + + account.setUpdated(Instant.now()); + + accountMap.update(account); + + log.debug("successfully processed, update account id {}", account.getId()); + return null; + } + + public RequestInfoUpdate correspondentAccountBlock(BaseRequest userRequest) { + log.debug("AccountBlockRequest received"); + + RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(userRequest); + if (requestInfoUpdate != null) return requestInfoUpdate; + + requestInfoUpdate = validationHelper.validateTillFirstError(userRequest, accountBlockRequestValidator); + if (requestInfoUpdate != null) return requestInfoUpdate; + + CommonDeleteRequest request = userRequest.getRequestPayload(); + + Account account = accountMap.getSingleObjectByID(request.getId()); + account.setStatus(AccountStatus.BLOCKED.getKey()); + account.setUpdated(Instant.now()); + + accountMap.update(account); + + log.debug("successfully processed, block account id {}", account.getId()); + return null; + } + + @Deprecated + public RequestInfoUpdate accountNewSdf01(BaseRequest userRequest) { log.debug("AccountSdf01Request received"); + + AccountSdf01Request req = userRequest.getRequestPayload(); List accountToStatement = new ArrayList<>(); for (AccountSdfRequestPart accountReq : req.getAccounts()) { Account account = new Account(); @@ -58,13 +199,15 @@ public class AccountService extends QueueConsumer implements InitializingBean { } sendStatementRequestBack(req.getGroupingSdf01Id(), accountToStatement); log.debug("successfully processed, grouping id={}, processed number={}", req.getGroupingSdf01Id(), accountToStatement.size()); + + return null; } - private void accountUpdateWithBrake(BaseRequest userRequest) { + public void accountUpdateWithBrake(BaseRequest userRequest) { } - private AccountSdfToStatementRequestPart responsePart(Long sdf01Id) { + public AccountSdfToStatementRequestPart responsePart(Long sdf01Id) { AccountSdfToStatementRequestPart responsePart = new AccountSdfToStatementRequestPart(); responsePart.setSdfId(sdf01Id); responsePart.setErrorCode(null); @@ -72,10 +215,59 @@ public class AccountService extends QueueConsumer implements InitializingBean { return responsePart; } - private void sendStatementRequestBack(Long groupingSdf01Id, List results) { + public void sendStatementRequestBack(Long groupingSdf01Id, List results) { StatementRequest request = new StatementRequest(); request.setGroupId(groupingSdf01Id); request.setAccountCreationResults(results); kafkaSender.sendRequestToQueue(Consts.STATEMENT_PROCESS, request); } + + /** + * Заполняет поля relationId и companyId из соответствующей записи Relation + * + * @param requestId Идентификатор запроса для вывода лога + */ + public RequestInfoUpdate fillAccountFromRelation(Account account, Long requestId) { + Long companyId = account.getCompanyId(); + ImdgPredicateBuilder clearingMemberCategoryPredicateBuilder = clearingMemberCategoryMap.predicateBuilder(); + ImdgPredicate companyIdEquals = clearingMemberCategoryPredicateBuilder.equals("companyId", companyId); + Collection clearingMemberCategories = clearingMemberCategoryMap.getCollectionObjectsByPredicate(companyIdEquals); + + if (clearingMemberCategories.isEmpty()) + return makeError(AccountError.ClearingCategoryNotFound, "clearingMemberCategory[companyId]", requestId); + if (clearingMemberCategories.size() > 1) + log.warn("ClearingMemberCategory for companyId {} contains multiply elements, use first", companyId); + ClearingMemberCategory clearingMemberCategory = clearingMemberCategories.iterator().next(); + + ImdgPredicateBuilder relationPredicateBuilder = relationMap.predicateBuilder(); + ImdgPredicate consumerIdPredicate = relationPredicateBuilder.equals("consumerId", companyId); + ImdgPredicate servicePredicate; + 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 { + return makeError(AccountError.ClearingCategoryNotFound, "relation[consumerId = companyId].service", requestId); + } + ImdgPredicate finalRelationPredicate = relationPredicateBuilder.and(consumerIdPredicate, servicePredicate); + Collection relations = relationMap.getCollectionObjectsByPredicate(finalRelationPredicate); + + if (relations.isEmpty()) return makeError(AccountError.WrongFieldValue, "companyId", requestId); + if (relations.size() > 1) + log.warn("Relation for consumerId {} contains multiply elements, use first", companyId); + Relation relation = relations.iterator().next(); + account.setRelationId(relation.getId()); + + return null; + } + + private RequestInfoUpdate makeError(AccountError accountError, String fieldName, Long reqId) { + String errMsg = messageResolver.resolve(new EnumMessage(accountError, fieldName)); + return new RequestInfoUpdate() + .setId(reqId) + .setStatus(Status.Error) + .setMessage(errMsg); + } + } diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/BankAccountService.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/BankAccountService.java index 7cc642a92..1940cc5a9 100644 --- a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/BankAccountService.java +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/BankAccountService.java @@ -10,7 +10,6 @@ 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.account.BankAccount; -import ru.clearing.classes.statics.data.company.relation.Relation; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.BaseRequest; import ru.spcex.clearing.platform.messaging.domain.Consts; @@ -19,18 +18,16 @@ import ru.spcex.clearing.platform.messaging.domain.cud.account.BankAccountUpdate 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.util.security.UserRoleVerification; +import ru.spcex.clearing.validation.common.ValidationHelper; import ru.spcex.platform.enumeration.AccountStatus; import ru.spcex.platform.enumeration.AccountType; -import ru.spcex.platform.enumeration.Allowed; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.api.ImdgProvider; -import ru.spcex.platform.utils.enumeration.EnumMessage; -import ru.spcex.platform.utils.enumeration.IMessageResolver; +import ru.spcex.platform.imdg.api.ImdgTransaction; import ru.spcex.platform.utils.validation.IValidator; import java.time.Instant; -import java.util.Optional; import java.util.function.Function; @Service @@ -38,30 +35,40 @@ public class BankAccountService extends QueueConsumer implements InitializingBea private final Logger log = LoggerFactory.getLogger(getClass()); private final Imdg bankAccountMap; private final Imdg accountMap; - private final Imdg relationMap; - private final IMessageResolver messageResolver; + private final ImdgProvider imdgProvider; + + private final UserRoleVerification userRoleVerification; + private final ValidationHelper validationHelper; + + private final AccountService accountService; - // private final Imdg userImdg; -// private final Imdg userRoleSessionImdg; private final Function bankAccountNewRequestValidator; + private final Function bankAccountUpdateRequestValidator; + private final Function bankAccountBlockRequestValidator; @Autowired public BankAccountService(Consumer kafkaQueue, Producer kafkaProducer, ImdgProvider imdgProvider, - IMessageResolver messageResolver, - + UserRoleVerification userRoleVerification, + ValidationHelper validationHelper, + AccountService accountService, @Qualifier("bankAccountNewRequestValidator") - Function bankAccountNewRequestValidator) { + Function bankAccountNewRequestValidator, + @Qualifier("bankAccountUpdateRequestValidator") + Function bankAccountUpdateRequestValidator, + @Qualifier("bankAccountBlockRequestValidator") + Function bankAccountBlockRequestValidator) { super(kafkaQueue, kafkaProducer); this.bankAccountMap = imdgProvider.getImdg(IMDGDistributedNames.Map_BankAccount, BankAccount.class); this.accountMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class); - this.relationMap = imdgProvider.getImdg(IMDGDistributedNames.Map_Relation, Relation.class); - this.messageResolver = messageResolver; - -// this.userImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_User, User.class); -// this.userRoleSessionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_UserRoleSession, UserRoleSession.class); + this.imdgProvider = imdgProvider; + this.userRoleVerification = userRoleVerification; + this.validationHelper = validationHelper; + this.accountService = accountService; this.bankAccountNewRequestValidator = bankAccountNewRequestValidator; + this.bankAccountUpdateRequestValidator = bankAccountUpdateRequestValidator; + this.bankAccountBlockRequestValidator = bankAccountBlockRequestValidator; } @Override @@ -73,82 +80,81 @@ public class BankAccountService extends QueueConsumer implements InitializingBea .setFunction(this::bankAccountUpdate) .forDestination(Consts.DESTINATION_BANK_ACCOUNT_UPDATE, callbacks::put); callback(CommonDeleteRequest.class) - .setFunction(this::bankAccountDelete) - .forDestination(Consts.DESTINATION_BANK_ACCOUNT_DELETE, callbacks::put); + .setFunction(this::bankAccountBlock) + .forDestination(Consts.DESTINATION_BANK_ACCOUNT_BLOCK, callbacks::put); init(); } -// protected Optional checkUserRole(Long userId) { -// User user = userImdg.getSingleObjectByID(userId); -// if (user == null) { -// return Optional.of(new EnumMessage(AccountError.userNotFound(5007))); -// } -// UserRoleSession role=userRoleSessionImdg.getSingleObjectBySql("userId="+userId+" and userRoleSessions.userRole='ADMN'"); -// if (role == null) { -// return Optional.of(new EnumMessage(AccountError.userNotFound(5001))); // Нет прав на проведение данной операции». -// } -// return Optional.empty(); -// } - private RequestInfoUpdate bankAccountNew(BaseRequest userRequest) { + public RequestInfoUpdate bankAccountNew(BaseRequest userRequest) { + log.debug("BankAccountNewRequest received"); + + RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(userRequest); + if (requestInfoUpdate != null) return requestInfoUpdate; + + requestInfoUpdate = validationHelper.validateTillFirstError(userRequest, bankAccountNewRequestValidator); + if (requestInfoUpdate != null) return requestInfoUpdate; + BankAccountNewRequest req = userRequest.getRequestPayload(); -// // проверка прав -// checkUserRole(req.getUserId()); - // валидация - IValidator validator = bankAccountNewRequestValidator.apply(req); - Optional error = validator.tillFirstError(); - if (error.isPresent()) { - log.warn("BankAccountNewRequest[{}] validation error: {}", userRequest.getId(), error.get()); - String errorMsg = messageResolver.resolve(error.get()); - return new RequestInfoUpdate() - .setId(userRequest.getId()) - .setStatus(Status.Error) - .setMessage(errorMsg); - } - - log.debug("BankAccountNewRequest received"); - BankAccount bankAccount = new BankAccount(); - bankAccount.setBankIdentificationCode(req.getBankIdentificationCode()); - bankAccount.setBankName(req.getBankName()); - bankAccount.setCorrespondentAccount(req.getCorrespondentAccount()); - bankAccount.setCorrespondentAccountName(req.getCorrespondentAccountName()); - bankAccount.setCurrency(req.getCurrency()); - bankAccount.setDestination(req.getDestination()); - bankAccount.setTaxpayerIdentificationNumber(req.getTaxpayerIdentificationNumber()); - bankAccount.setTaxRegistrationReasonCode(req.getTaxRegistrationReasonCode()); - bankAccount.setAccount(req.getAccount()); - bankAccount.setCompanyId(req.getCompanyId()); - + Instant now = Instant.now(); Account account = new Account(); - account.setAccount(req.account); + account.setAccount(req.getAccount()); account.setAccountType(AccountType.Bank.getKey()); - - String relationSqlCondition = String.format("consumerId = %s and service = %s", req.companyId, - ru.spcex.platform.enumeration.Service.MKR.getKey()); - Relation relationByCompany = relationMap.getSingleObjectBySQL(relationSqlCondition); - if (relationByCompany != null) { - account.setRelationId(relationByCompany.getId()); - account.setCompanyId(relationByCompany.getConsumerId()); - } else { - log.warn("Not found relation by condition: {}", relationSqlCondition); - } account.setStatus(AccountStatus.ACTIVE.getKey()); - account.setProcessingSign(Allowed.ALLOWED.getKey()); - account.setCreated(Instant.now()); - account.setUpdated(Instant.now()); + account.setCompanyId(req.getCompanyId()); + account.setCreated(now); + account.setUpdated(now); + requestInfoUpdate = accountService.fillAccountFromRelation(account, userRequest.getId()); + if (requestInfoUpdate != null) return requestInfoUpdate; - accountMap.insert(account); + Long bankAccountId = -1L; + Long accountId = -1L; + ImdgTransaction imdgTransaction = imdgProvider.newTransaction(); + boolean txOk = false; + imdgTransaction.beginTransaction(); + try { + accountId = accountMap.insert(account); - bankAccount.setAccountId(account.getId()); - bankAccountMap.insert(bankAccount); - log.debug("successfully processed, new id {}", bankAccount.getId()); + BankAccount bankAccount = new BankAccount(); + bankAccount.setBankIdentificationCode(req.getBankIdentificationCode()); + bankAccount.setBankName(req.getBankName()); + bankAccount.setCorrespondentAccount(req.getCorrespondentAccount()); + bankAccount.setCorrespondentAccountName(req.getCorrespondentAccountName()); + bankAccount.setCurrency(req.getCurrency()); + bankAccount.setDestination(req.getDestination()); + bankAccount.setTaxpayerIdentificationNumber(req.getTaxpayerIdentificationNumber()); + bankAccount.setTaxRegistrationReasonCode(req.getTaxRegistrationReasonCode()); + bankAccount.setAccount(req.getAccount()); + bankAccount.setCompanyId(req.getCompanyId()); + bankAccount.setAccountId(accountId); + bankAccountId = bankAccountMap.insert(bankAccount); + + txOk = true; + } finally { + if (txOk) { + imdgTransaction.commitTransaction(); + log.debug("successfully processed, new bank account id {}, account id {}", bankAccountId, accountId); + } else { + log.debug("failed insert, new bank account id {}, new account id {} (if id = -1 then insert is failed)", + bankAccountId, + accountId); + imdgTransaction.rollbackTransaction(); + } + } return null; } private RequestInfoUpdate bankAccountUpdate(BaseRequest userRequest) { BankAccountUpdateRequest req = userRequest.getRequestPayload(); log.debug("BankAccountUpdateRequest received id = {}", req.getId()); + + RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(userRequest); + if (requestInfoUpdate != null) return requestInfoUpdate; + + requestInfoUpdate = validationHelper.validateTillFirstError(userRequest, bankAccountUpdateRequestValidator); + if (requestInfoUpdate != null) return requestInfoUpdate; + BankAccount bankAccount = bankAccountMap.getSingleObjectByID(req.getId()); bankAccount.setBankIdentificationCode(req.getBankIdentificationCode()); bankAccount.setBankName(req.getBankName()); @@ -164,24 +170,68 @@ public class BankAccountService extends QueueConsumer implements InitializingBea account.setAccount(req.account); account.setUpdated(Instant.now()); - accountMap.update(account); - bankAccountMap.update(bankAccount); + ImdgTransaction imdgTransaction = imdgProvider.newTransaction(); + boolean txOk = false; + imdgTransaction.beginTransaction(); + try { + accountMap.update(account); + bankAccountMap.update(bankAccount); + txOk = true; + } finally { + if (txOk) { + imdgTransaction.commitTransaction(); + log.debug("successfully processed, new bank account id {}, account id {}", + bankAccount.getId(), + account.getId()); + } else { + log.debug("failed update, bank account id {}, new account id {}", + bankAccount.getId(), + account.getId()); + imdgTransaction.rollbackTransaction(); + } + } log.debug("successfully update, existing bankAccount with id {}", bankAccount.getId()); return null; } - private RequestInfoUpdate bankAccountDelete(BaseRequest userRequest) { + private RequestInfoUpdate bankAccountBlock(BaseRequest userRequest) { CommonDeleteRequest req = userRequest.getRequestPayload(); + + RequestInfoUpdate requestInfoUpdate = userRoleVerification.validateRoleAndGetResult(userRequest); + if (requestInfoUpdate != null) return requestInfoUpdate; + + requestInfoUpdate = validationHelper.validateTillFirstError(userRequest, bankAccountBlockRequestValidator); + if (requestInfoUpdate != null) return requestInfoUpdate; + log.debug("CommonDeleteRequest received id = {}", req.getId()); BankAccount bankAccount = bankAccountMap.getSingleObjectByID(req.getId()); Account account = accountMap.getSingleObjectByID(bankAccount.getAccountId()); account.setStatus(AccountStatus.BLOCKED.getKey()); account.setUpdated(Instant.now()); - - accountMap.update(account); - bankAccountMap.delete(bankAccount); - log.debug("successfully delete, existing bankAccount with id {}", bankAccount.getId()); + + ImdgTransaction imdgTransaction = imdgProvider.newTransaction(); + boolean txOk = false; + imdgTransaction.beginTransaction(); + try { + accountMap.update(account); + bankAccountMap.delete(bankAccount); + txOk = true; + } finally { + if (txOk) { + imdgTransaction.commitTransaction(); + log.debug("successfully processed, new bank account id {}, account id {}", + bankAccount.getId(), + account.getId()); + } else { + // todo выяснить, что возвращать из метода в этой ситуации + log.debug("failed block, bank account id {}, new account id {}", + bankAccount.getId(), + account.getId()); + imdgTransaction.rollbackTransaction(); + } + } + log.debug("successfully block, existing bankAccount with id {}", bankAccount.getId()); return null; } diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/ClearingAccountService.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/ClearingAccountService.java new file mode 100644 index 000000000..03f148353 --- /dev/null +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/ClearingAccountService.java @@ -0,0 +1,168 @@ +package ru.spcex.clearing.account.service; + +import org.apache.kafka.clients.consumer.Consumer; +import org.apache.kafka.clients.producer.Producer; +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.account.ClearingAccount; +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.ClearingAccountNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.account.ClearingAccountUpdateRequest; +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.validation.common.ValidationHelper; +import ru.spcex.platform.enumeration.AccountStatus; +import ru.spcex.platform.enumeration.AccountType; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.ImdgTransaction; +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.IMessageResolver; +import ru.spcex.platform.utils.validation.IValidator; + +import java.time.Instant; +import java.util.Map; +import java.util.function.Function; + +@Service +public class ClearingAccountService extends QueueConsumer implements InitializingBean { + private final Logger log = LoggerFactory.getLogger(getClass()); + private final AccountService accountService; + private final ValidationHelper validationHelper; + private final ImdgProvider imdgProvider; + private final Imdg accountImdg; + private final Imdg clearingAccountImdg; + private final IMessageResolver messageResolver; + private final Function clearingAccountNewRequestValidator; + private final Function clearingAccountUpdateRequestValidator; + + @Autowired + public ClearingAccountService(Consumer kafkaQueue, + Producer kafkaResponseQueue, + AccountService accountService, + ValidationHelper validationHelper, + ImdgProvider imdgProvider, + IMessageResolver messageResolver, + @Qualifier("clearingAccountNewRequestValidator") + Function clearingAccountNewRequestValidator, + @Qualifier("clearingAccountUpdateRequestValidator") + Function clearingAccountUpdateRequestValidator) { + super(kafkaQueue, kafkaResponseQueue); + this.accountService = accountService; + this.validationHelper = validationHelper; + this.imdgProvider = imdgProvider; + this.accountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class); + this.clearingAccountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingAccount, ClearingAccount.class); + this.messageResolver = messageResolver; + this.clearingAccountNewRequestValidator = clearingAccountNewRequestValidator; + this.clearingAccountUpdateRequestValidator = clearingAccountUpdateRequestValidator; + } + + @Override + public void afterPropertiesSet() throws Exception { + init(); + callback(ClearingAccountNewRequest.class) + .setFunction(this::clearingAccountNew) + .forDestination(Consts.DESTINATION_CLEARING_ACCOUNT_NEW, callbacks::put); + callback(ClearingAccountUpdateRequest.class) + .setFunction(this::clearingAccountUpdate) + .forDestination(Consts.DESTINATION_CLEARING_ACCOUNT_UPDATE, callbacks::put); + } + + public RequestInfoUpdate clearingAccountNew(BaseRequest userRequest) { + RequestInfoUpdate requestInfoUpdate = validationHelper.validateTillFirstError( + userRequest, clearingAccountNewRequestValidator + ); + if (requestInfoUpdate != null) return requestInfoUpdate; + + ClearingAccountNewRequest req = userRequest.getRequestPayload(); + + Instant now = Instant.now(); + Account account = new Account(); + account.setAccount(req.getAccount()); + account.setAccountType(AccountType.Clrn.getKey()); + account.setStatus(AccountStatus.ACTIVE.getKey()); + account.setCompanyId(req.getCompanyId()); + account.setCreated(now); + account.setUpdated(now); + requestInfoUpdate = accountService.fillAccountFromRelation(account, userRequest.getId()); + if (requestInfoUpdate != null) return requestInfoUpdate; + + Long clearingAccountId = -1L; + Long accountId = -1L; + ImdgTransaction imdgTransaction = imdgProvider.newTransaction(); + boolean txOk = false; + imdgTransaction.beginTransaction(); + try { + accountId = accountImdg.insert(account); + + ClearingAccount clearingAccount = new ClearingAccount(); + clearingAccount.setCompanyId(req.getCompanyId()); + clearingAccount.setAccountId(accountId); + clearingAccount.setClearingAccountType(req.getClearingAccountType()); + clearingAccountId = clearingAccountImdg.insert(clearingAccount); + txOk = true; + } finally { + if (txOk) { + imdgTransaction.commitTransaction(); + log.debug("successfully processed, new clearing account id {}, account id {}", clearingAccountId, accountId); + } else { + // todo выяснить, что возвращать из метода в этой ситуации + log.debug("failed insert, new clearing account id {}, new account id {} (if id = -1 then insert is failed)", + clearingAccountId, + accountId); + imdgTransaction.rollbackTransaction(); + } + } + return null; + } + + public RequestInfoUpdate clearingAccountUpdate(BaseRequest userRequest) { + RequestInfoUpdate requestInfoUpdate = validationHelper.validateTillFirstError( + userRequest, clearingAccountUpdateRequestValidator + ); + if (requestInfoUpdate != null) return requestInfoUpdate; + + ClearingAccountUpdateRequest req = userRequest.getRequestPayload(); + ImdgPredicateBuilder pb = accountImdg.predicateBuilder(); + ImdgPredicate accountValuePredicate = pb.equals("account", req.getAccount()); + ImdgPredicate accountStatusPredicate = pb.equals("status", AccountStatus.ACTIVE.getKey()); + ImdgPredicate accountTypePredicate = pb.equals("accountType", AccountType.Clrn.getKey()); + ImdgPredicate finalPredicate = pb.and(accountValuePredicate, + accountStatusPredicate, + accountTypePredicate); + + Account account = accountImdg.getCollectionObjectsByPredicate(finalPredicate).iterator().next(); + Long accountId = account.getId(); + + ClearingAccount clearingAccount = clearingAccountImdg.getSingleObjectByFieldValues(Map.of("accountId", accountId)); + if (clearingAccount == null) { + String errMsg = messageResolver.resolve(new EnumMessage(AccountError.AccountNotFound, account.getAccount())); + return new RequestInfoUpdate() + .setId(userRequest.getId()) + .setStatus(Status.Error) + .setMessage(errMsg); + } + + Integer statusValue = req.getStatus(); + if (statusValue == 0) account.setStatus(AccountStatus.BLOCKED.getKey()); + else if (statusValue == 1) account.setStatus(AccountStatus.ACTIVE.getKey()); + else if (statusValue == 2) account.setStatus(AccountStatus.CLOSE.getKey()); + account.setUpdated(Instant.now()); + + accountImdg.update(account); + + return null; + } +} diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/DepoAccountService.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/DepoAccountService.java new file mode 100644 index 000000000..625e909f5 --- /dev/null +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/DepoAccountService.java @@ -0,0 +1,112 @@ +package ru.spcex.clearing.account.service; + +import org.apache.kafka.clients.consumer.Consumer; +import org.apache.kafka.clients.producer.Producer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; +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.account.DepoAccount; +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.DepoAccountNewRequest; +import ru.spcex.clearing.platform.messaging.service.QueueConsumer; +import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate; +import ru.spcex.clearing.validation.common.ValidationHelper; +import ru.spcex.platform.enumeration.AccountStatus; +import ru.spcex.platform.enumeration.AccountType; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.ImdgTransaction; +import ru.spcex.platform.utils.validation.IValidator; + +import java.time.Instant; +import java.util.function.Function; + +@Service +public class DepoAccountService extends QueueConsumer implements InitializingBean { + private final Logger log = LoggerFactory.getLogger(getClass()); + + private final ValidationHelper validationHelper; + private final ImdgProvider imdgProvider; + private final AccountService accountService; + private final Function depoAccountNewRequestValidator; + private final Imdg accountImdg; + private final Imdg depoAccountImdg; + + public DepoAccountService(Consumer kafkaQueue, + Producer kafkaProducer, + ValidationHelper validationHelper, + ImdgProvider imdgProvider, + AccountService accountService, + @Qualifier("depoAccountNewRequestValidator") + Function depoAccountNewRequestValidator) { + super(kafkaQueue, kafkaProducer); + this.validationHelper = validationHelper; + this.imdgProvider = imdgProvider; + this.accountService = accountService; + this.depoAccountNewRequestValidator = depoAccountNewRequestValidator; + this.accountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Account, Account.class); + this.depoAccountImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_DepoAccount, DepoAccount.class); + } + + @Override + public void afterPropertiesSet() throws Exception { + callback(DepoAccountNewRequest.class) + .setConsumer(this::depoAccountNew) + .forDestination(Consts.DESTINATION_DEPO_ACCOUNT_NEW, callbacks::put); + init(); + } + + public RequestInfoUpdate depoAccountNew(BaseRequest userRequest) { + log.debug("DepoAccountNewRequest received"); + RequestInfoUpdate requestInfoUpdate = validationHelper.validateTillFirstError( + userRequest, depoAccountNewRequestValidator + ); + if (requestInfoUpdate != null) return requestInfoUpdate; + + DepoAccountNewRequest req = userRequest.getRequestPayload(); + + Instant now = Instant.now(); + Account account = new Account(); + account.setAccount(req.getAccount()); + account.setAccountType(AccountType.Depo.getKey()); + account.setStatus(AccountStatus.ACTIVE.getKey()); + account.setCompanyId(req.getCompanyId()); + account.setCreated(now); + account.setUpdated(now); + requestInfoUpdate = accountService.fillAccountFromRelation(account, userRequest.getId()); + if (requestInfoUpdate != null) return requestInfoUpdate; + + Long depoAccountId = -1L; + Long accountId = -1L; + ImdgTransaction imdgTransaction = imdgProvider.newTransaction(); + boolean txOk = false; + imdgTransaction.beginTransaction(); + try { + accountId = accountImdg.insert(account); + + DepoAccount depoAccount = new DepoAccount(); + depoAccount.setCompanyId(req.getCompanyId()); + depoAccount.setAccountId(accountId); + depoAccount.setDepoAccountType(req.getDepoAccountType()); + depoAccountId = depoAccountImdg.insert(depoAccount); + txOk = true; + } finally { + if (txOk) { + imdgTransaction.commitTransaction(); + log.debug("successfully processed, new depo account id {}, account id {}", depoAccountId, accountId); + } else { + // todo выяснить, что возвращать из метода в этой ситуации + log.debug("failed insert, new depo account id {}, new account id {} (if id = -1 then insert is failed)", + depoAccountId, + accountId); + imdgTransaction.rollbackTransaction(); + } + } + return null; + } +} diff --git a/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/InformationAccountService.java b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/InformationAccountService.java new file mode 100644 index 000000000..2c74b2086 --- /dev/null +++ b/clearing-parent/account-service/src/main/java/ru/spcex/clearing/account/service/InformationAccountService.java @@ -0,0 +1,152 @@ +package ru.spcex.clearing.account.service; + +import org.apache.kafka.clients.consumer.Consumer; +import org.apache.kafka.clients.producer.Producer; +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.account.InformationAccount; +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.InformationAccountNewRequest; +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.validation.common.ValidationHelper; +import ru.spcex.platform.enumeration.AccountStatus; +import ru.spcex.platform.enumeration.AccountType; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.api.ImdgTransaction; +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.IMessageResolver; +import ru.spcex.platform.utils.validation.IValidator; + +import java.time.Instant; +import java.util.Collection; +import java.util.function.Function; + +@Service +public class InformationAccountService extends QueueConsumer implements InitializingBean { + private final Logger log = LoggerFactory.getLogger(getClass()); + private final IMessageResolver messageResolver; + private final ImdgProvider imdgProvider; + private final ValidationHelper validationHelper; + private final AccountService accountService; + private final Function infoAccountNewRequestValidator; + private final Imdg informationAccountImdg; + private final Imdg accountImdg; + + @Autowired + public InformationAccountService(Consumer kafkaQueue, + Producer kafkaResponseQueue, + IMessageResolver messageResolver, + ImdgProvider imdgProvider, + ValidationHelper validationHelper, + AccountService accountService, + @Qualifier("informationAccountNewRequestValidator") + Function infoAccountNewRequestValidator) { + super(kafkaQueue, kafkaResponseQueue); + this.messageResolver = messageResolver; + this.imdgProvider = imdgProvider; + this.validationHelper = validationHelper; + this.accountService = accountService; + this.infoAccountNewRequestValidator = infoAccountNewRequestValidator; + this.informationAccountImdg = imdgProvider.getImdg( + IMDGDistributedNames.Map_InformationAccount, InformationAccount.class + ); + this.accountImdg = imdgProvider.getImdg( + IMDGDistributedNames.Map_Account, Account.class + ); + } + + @Override + public void afterPropertiesSet() throws Exception { + callback(InformationAccountNewRequest.class) + .setConsumer(this::informationAccountNew) + .forDestination(Consts.DESTINATION_INFORMATION_ACCOUNT_NEW, callbacks::put); + init(); + } + + public RequestInfoUpdate informationAccountNew(BaseRequest userRequest) { + log.debug("InformationAccountNewRequest received"); + + RequestInfoUpdate requestInfoUpdate = validationHelper.validateTillFirstError(userRequest, infoAccountNewRequestValidator); + if (requestInfoUpdate != null) return requestInfoUpdate; + + Long newId = informationAccountImdg.nextIDSequenceFor(); + String accountValue = generateInfoAccount(newId); + + ImdgPredicateBuilder accountPredicateBuilder = accountImdg.predicateBuilder(); + ImdgPredicate companyIdPredicate = accountPredicateBuilder.equals("companyId", 1); + ImdgPredicate accountTypePredicate = accountPredicateBuilder.equals("accountType", AccountType.Anlt.getKey()); + ImdgPredicate andPredicate = accountPredicateBuilder.and(companyIdPredicate, accountTypePredicate); + Collection accountsAnlt = accountImdg.getCollectionObjectsByPredicate(andPredicate); + if (accountsAnlt.isEmpty()) { + String errMsg = messageResolver.resolve(new EnumMessage(AccountError.WrongFieldValue, "clearingAccountId")); + return new RequestInfoUpdate() + .setId(userRequest.getId()) + .setStatus(Status.Error) + .setMessage(errMsg); + } else if (accountsAnlt.size() > 1) { + log.warn("Account for companyId 1 and accountType=ANLT contains multiply elements, use first"); + } + Account anltAccount = accountsAnlt.iterator().next(); + + Instant now = Instant.now(); + Account account = new Account(); + account.setAccount(accountValue); + account.setAccountType(AccountType.Info.getKey()); + account.setStatus(AccountStatus.ACTIVE.getKey()); + account.setCompanyId(userRequest.getRequestPayload().getCompanyId()); + account.setCreated(now); + account.setUpdated(now); + requestInfoUpdate = accountService.fillAccountFromRelation(account, userRequest.getId()); + if (requestInfoUpdate != null) return requestInfoUpdate; + + ImdgTransaction imdgTransaction = imdgProvider.newTransaction(); + imdgTransaction.beginTransaction(); + boolean txOk = false; + Long informationAccountId = -1L; + Long accountId = -1L; + try { + accountId = accountImdg.insert(account); + + InformationAccount informationAccount = new InformationAccount(); + informationAccount.setId(newId); + informationAccount.setAccountId(accountId); + informationAccount.setClearingAccountId(anltAccount.getId()); + informationAccount.setCompanyId(userRequest.getRequestPayload().getCompanyId()); + informationAccountId = informationAccountImdg.insert(informationAccount); + txOk = true; + } finally { + if (txOk) { + imdgTransaction.commitTransaction(); + log.debug("successfully processed, new information account id {}, new account id {}", + informationAccountId, + accountId); + } else { + // todo выяснить, что возвращать из метода в этой ситуации + log.debug("failed insert, new information account id {}, new account id {} (if id = -1 then insert is failed)", + informationAccountId, + accountId); + imdgTransaction.rollbackTransaction(); + } + } + + return null; + } + + public String generateInfoAccount(Long id) { + return "%d%d%08d%d".formatted(39911, 810, id, 7000); + } + +} 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..b2d53c3dc 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 @@ -15,34 +15,51 @@ import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; import ru.clearing.classes.statics.data.account.Account; +import ru.clearing.classes.statics.data.company.ClearingMemberCategory; +import ru.clearing.classes.statics.data.company.Company; +import ru.clearing.classes.statics.data.company.relation.Relation; +import ru.clearing.platform.dictionary.AccountTypeDictionary; +import ru.spcex.clearing.account.config.BeanConfiguration; import ru.spcex.clearing.account.config.HazelcastServiceTestConfiguration; import ru.spcex.clearing.account.config.KafkaConfigTest; +import ru.spcex.clearing.account.config.validation.AccountValidationConfig; +import ru.spcex.clearing.account.config.validation.ValidationConfig; import ru.spcex.clearing.account.utils.MatcherFactory; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.ActionType; 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.CorrespondentAccountNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.account.CorrespondentAccountUpdateRequest; 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.RequestInfo; import ru.spcex.clearing.platform.messaging.service.Status; +import ru.spcex.platform.enumeration.*; +import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.iml.hazelcast.adapter.ImdgHazelcast; import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService; +import javax.annotation.PostConstruct; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.UUID; -import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; import static ru.spcex.clearing.account.config.HazelcastServiceTestConfiguration.currentID; import static ru.spcex.clearing.account.utils.MatcherFactory.usingIgnoringFieldsComparator; -import static ru.spcex.clearing.account.utils.TestUtils.addRecordToKafka; +import static ru.spcex.clearing.account.utils.TestUtils.*; @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = { + BeanConfiguration.class, + ValidationConfig.class, + AccountValidationConfig.class, AccountService.class, HazelcastServiceTestConfiguration.class, KafkaConfigTest.class}) @@ -50,8 +67,10 @@ 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"; + private static final Long companyId = 0L; + private static final Long relationId = 0L; @Autowired AccountService accountService; @Autowired @@ -63,8 +82,157 @@ class AccountServiceTest { @SpyBean private MockProducer producer; + private Imdg accountImdg; + private Imdg companyImdg; + private Imdg accountTypeDictionaryImdg; + private Imdg clearingMemberCategoryImdg; + private Imdg relationImdg; + + @PostConstruct + private void init() { + hazelcastServiceTest.waitAvailable(); + accountImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_Account, Account.class + ); + companyImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_Company, Company.class + ); + accountTypeDictionaryImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_AccountTypeDictionary, AccountTypeDictionary.class + ); + clearingMemberCategoryImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class + ); + relationImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_Relation, Relation.class + ); + + Company company = new Company(); + company.setId(companyId); + company.setWorkflowStatus(WorkflowStatus.Active.getKey()); + companyImdg.insert(company); + + AccountTypeDictionary accountTypeDictionary = new AccountTypeDictionary(); + accountTypeDictionary.setCode(AccountType.Corr.getKey()); + accountTypeDictionary.setName(AccountType.Corr.getKey()); + accountTypeDictionaryImdg.insert(accountTypeDictionary); + + ClearingMemberCategory clearingMemberCategory = new ClearingMemberCategory(); + clearingMemberCategory.setClearingMemberCategory(ClearingCategory.B.getKey()); + clearingMemberCategory.setCompanyId(companyId); + clearingMemberCategoryImdg.insert(clearingMemberCategory); + + Relation relation = new Relation(); + relation.setId(relationId); + relation.setConsumerId(companyId); + relation.setService(Service.MKR.getKey()); + relationImdg.insert(relation); + } + + @Test + void accountCorrespondentNew() { + String uniqueAccount = account + UUID.randomUUID(); + + CorrespondentAccountNewRequest correspondentAccountNewRequest = new CorrespondentAccountNewRequest(); + correspondentAccountNewRequest.setAccount(uniqueAccount); + correspondentAccountNewRequest.setAccountType(AccountType.Corr.getKey()); + correspondentAccountNewRequest.setCompanyId(companyId); + correspondentAccountNewRequest.setStatus(AccountStatus.ACTIVE.getKey()); + + Account predictableAccount = new Account(); + predictableAccount.setAccount(uniqueAccount); + predictableAccount.setAccountType(AccountType.Corr.getKey()); + predictableAccount.setCompanyId(companyId); + predictableAccount.setStatus(AccountStatus.ACTIVE.getKey()); + predictableAccount.setRelationId(relationId); + + String jsonString = getJsonStringForNew(correspondentAccountNewRequest, 0L); + + addRecordToKafka((MockConsumer) accountService.getConsumer(), + Consts.DESTINATION_CORRESPONDENT_ACCOUNT_NEW, + PARTITION, + 0, + jsonString); + + waitingWhenAddedRecordAndCheckIt(0L, producer, producerRecord); + + Account resultNew = accountImdg.getCollectionObjectsByFieldValues(Map.of("account", uniqueAccount)).iterator().next(); + predictableAccount.setId(resultNew.getId()); + predictableAccount.setUpdated(resultNew.getUpdated()); + predictableAccount.setCreated(resultNew.getCreated()); + ACCOUNT_MATCHER.assertMatch(resultNew, predictableAccount); + accountImdg.delete(resultNew); + } + + @Test + void accountCorrespondentUpdate() { + Account existAccount = new Account(); + existAccount.setAccount(account); + existAccount.setAccountType(AccountType.Corr.getKey()); + existAccount.setStatus(AccountStatus.CLOSE.getKey()); + existAccount.setCompanyId(companyId); + Long accountId = accountImdg.insert(existAccount); + + CorrespondentAccountUpdateRequest correspondentAccountUpdateRequest = new CorrespondentAccountUpdateRequest(); + correspondentAccountUpdateRequest.setAccount(account); + correspondentAccountUpdateRequest.setAccountType(AccountType.Corr.getKey()); + correspondentAccountUpdateRequest.setStatus(AccountStatus.ACTIVE.getKey()); + correspondentAccountUpdateRequest.setCompanyId(companyId); + correspondentAccountUpdateRequest.setId(accountId); + + + String jsonString = getJsonStringForUPDATE(correspondentAccountUpdateRequest, 0); + + //ACT + addRecordToKafka((MockConsumer) accountService.getConsumer(), + Consts.DESTINATION_CORRESPONDENT_ACCOUNT_UPDATE, + PARTITION, + 0, + jsonString); + + //ASSERT + waitingWhenAddedRecordAndCheckIt(0L, producer, producerRecord); + + Account resultUpdating = accountImdg.getSingleObjectByID(accountId); + existAccount.setUpdated(resultUpdating.getUpdated()); + ACCOUNT_MATCHER.assertMatch(resultUpdating, existAccount); + accountImdg.delete(resultUpdating); + } + + @Test + void accountCorrespondentBlock() { + Account existAccount = new Account(); + existAccount.setAccount(account); + existAccount.setAccountType(AccountType.Corr.getKey()); + existAccount.setStatus(AccountStatus.ACTIVE.getKey()); + existAccount.setCompanyId(companyId); + Long accountId = accountImdg.insert(existAccount); + + CommonDeleteRequest commonDeleteRequest = new CommonDeleteRequest(); + commonDeleteRequest.setId(accountId); + + String jsonString = getJsonStringForDELETE(commonDeleteRequest, 0); + + //ACT + addRecordToKafka((MockConsumer) accountService.getConsumer(), + Consts.DESTINATION_CORRESPONDENT_ACCOUNT_BLOCK, + PARTITION, + 0, + jsonString); + + //ASSERT + waitingWhenAddedRecordAndCheckIt(0L, producer, producerRecord); + + Account resultBlock = accountImdg.getSingleObjectByID(accountId); + existAccount.setStatus(AccountStatus.BLOCKED.getKey()); + existAccount.setUpdated(resultBlock.getUpdated()); + + ACCOUNT_MATCHER.assertMatch(existAccount, resultBlock); + accountImdg.delete(resultBlock); + } + /** - * {@link AccountService#accountNew(BaseRequest)}
+ * {@link AccountService#accountNewSdf01(BaseRequest)}
* Тест проверяет создание сущности {@link BaseRequest} в Hazelcast при передаче из Apache Kafka.
* Входной запрос {@link AccountSdf01Request}:
* {@link AccountSdfRequestPart#setSdfId} - текущий Id
@@ -74,7 +242,7 @@ class AccountServiceTest { * {@link AccountSdf01Request#setAccounts} - Collections.singletonList(AccountSdfRequestPart)
*/ @Test - void accountNew() throws InterruptedException { + void accountSdf01New() throws InterruptedException { //ARRANGE Long firstID = currentID.getAndIncrement(); Long secondID = currentID.getAndIncrement(); @@ -85,7 +253,6 @@ class AccountServiceTest { AccountSdf01Request accountSdf01Request = new AccountSdf01Request(); accountSdf01Request.setGroupingSdf01Id(firstID); accountSdf01Request.setAccounts(Collections.singletonList(accountSdfRequestPart)); - BaseRequest baseNewRequest = new BaseRequest<>(); baseNewRequest.setRequestPayload(accountSdf01Request); baseNewRequest.setId(firstID); @@ -114,33 +281,25 @@ class AccountServiceTest { Account predictableAccount = new Account(); predictableAccount.setAccount(account); - predictableAccount.setId(firstID); predictableAccount.setCompanyId(firstID); RequestInfo predictableRequestInfo = new RequestInfo(); predictableRequestInfo.setId(secondID); predictableRequestInfo.setStatus(Status.Processing); - //ACT - hazelcastServiceTest.waitTillReadyState(); - //KAFKA addRecordToKafka((MockConsumer) accountService.getConsumer(), TOPIC_ACCOUNT_NEW, PARTITION, 0, jsonBaseNewRequest); //waiting for kafka producer send message (finale event) - verify(producer, timeout(30_000L).times(1)) + verify(producer, timeout(30_000L).times(2)) .send(producerRecord.capture()); - BaseRequest baseRequestObject = (BaseRequest) producerRecord.getValue().value(); ImdgHazelcast accountImdg = (ImdgHazelcast) hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_Account, Account.class); - ImdgHazelcast requestInfoImdg = (ImdgHazelcast) hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_RequestInfo, RequestInfo.class); //ASSERT Account accountResult = accountImdg.getSingleObjectBySQL(String.format("account = %s", account)); - RequestInfo requestInfoResult = requestInfoImdg.getSingleObjectByID(baseRequestObject.getId()); - - assertEquals(Consts.STATEMENT_PROCESS, producerRecord.getValue().topic()); + predictableAccount.setId(accountResult.getId()); ACCOUNT_MATCHER.assertMatch(accountResult, predictableAccount); - REQUEST_INFO_MATCHER_MATCHER.assertMatch(requestInfoResult, predictableRequestInfo); + accountImdg.delete(accountResult); } } \ No newline at end of file diff --git a/clearing-parent/account-service/src/test/java/ru/spcex/clearing/account/service/BankAccountServiceTest.java b/clearing-parent/account-service/src/test/java/ru/spcex/clearing/account/service/BankAccountServiceTest.java index ad579b228..31d54b627 100644 --- a/clearing-parent/account-service/src/test/java/ru/spcex/clearing/account/service/BankAccountServiceTest.java +++ b/clearing-parent/account-service/src/test/java/ru/spcex/clearing/account/service/BankAccountServiceTest.java @@ -15,11 +15,17 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; 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.spcex.clearing.account.config.ErrorResolverConfig; +import ru.clearing.classes.statics.data.company.relation.Relation; +import ru.clearing.platform.dictionary.CurrencyCodeDictionary; +import ru.spcex.clearing.account.config.BeanConfiguration; import ru.spcex.clearing.account.config.HazelcastServiceTestConfiguration; import ru.spcex.clearing.account.config.KafkaConfigTest; -import ru.spcex.clearing.account.config.ValidationConfig; +import ru.spcex.clearing.account.config.validation.AccountValidationConfig; +import ru.spcex.clearing.account.config.validation.BankAccountValidationConfig; +import ru.spcex.clearing.account.config.validation.ValidationConfig; +import ru.spcex.clearing.account.errors.AccountError; import ru.spcex.clearing.account.utils.MatcherFactory.Matcher; import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.platform.messaging.domain.ActionType; @@ -29,11 +35,11 @@ import ru.spcex.clearing.platform.messaging.domain.cud.account.BankAccountNewReq import ru.spcex.clearing.platform.messaging.domain.cud.account.BankAccountUpdateRequest; import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest; import ru.spcex.clearing.platform.messaging.service.RequestInfoUpdate; -import ru.spcex.platform.enumeration.AccountType; -import ru.spcex.platform.enumeration.Allowed; -import ru.spcex.platform.enumeration.Status; +import ru.spcex.platform.enumeration.*; import ru.spcex.platform.imdg.api.Imdg; import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService; +import ru.spcex.platform.utils.enumeration.EnumMessage; +import ru.spcex.platform.utils.enumeration.IMessageResolver; import javax.annotation.PostConstruct; import java.util.concurrent.atomic.AtomicInteger; @@ -47,9 +53,12 @@ import static ru.spcex.clearing.platform.messaging.service.Status.Error; @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = { - ErrorResolverConfig.class, + AccountService.class, BankAccountService.class, ValidationConfig.class, + BankAccountValidationConfig.class, + AccountValidationConfig.class, + BeanConfiguration.class, HazelcastServiceTestConfiguration.class, KafkaConfigTest.class}) public class BankAccountServiceTest { @@ -59,7 +68,7 @@ public class BankAccountServiceTest { private static final int PARTITION = 0; private static final String TOPIC_ACCOUNT_NEW = Consts.DESTINATION_BANK_ACCOUNT_NEW; private static final String TOPIC_ACCOUNT_UPDATE = Consts.DESTINATION_BANK_ACCOUNT_UPDATE; - private static final String TOPIC_ACCOUNT_DELETE = Consts.DESTINATION_BANK_ACCOUNT_DELETE; + private static final String TOPIC_ACCOUNT_DELETE = Consts.DESTINATION_BANK_ACCOUNT_BLOCK; private static final Long ID = 0L; private static final AtomicInteger countRun = new AtomicInteger(1); private static final Long accountId = 12L; @@ -77,6 +86,12 @@ public class BankAccountServiceTest { protected Imdg companyImdg; private Imdg bankAccountImdg; private Imdg accountImdg; + private Imdg currencyCodeDictionaryImdg; + private Imdg clearingMemberCategoryImdg; + private Imdg relationImdg; + + @Autowired + private IMessageResolver messageResolver; @Autowired @Qualifier("hazelcastServiceTest") @@ -96,6 +111,19 @@ public class BankAccountServiceTest { companyImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_Company, Company.class); bankAccountImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_BankAccount, BankAccount.class); accountImdg = hazelcastServiceTest.getImdg(IMDGDistributedNames.Map_Account, Account.class); + currencyCodeDictionaryImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_CurrencyCodeDictionary, CurrencyCodeDictionary.class + ); + clearingMemberCategoryImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class + ); + relationImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_Relation, Relation.class + ); + CurrencyCodeDictionary currencyCodeDictionary = new CurrencyCodeDictionary(); + currencyCodeDictionary.setCode("RUB"); + currencyCodeDictionary.setName("RUB"); + currencyCodeDictionaryImdg.insert(currencyCodeDictionary); } /** @@ -116,10 +144,27 @@ public class BankAccountServiceTest { public void bankAccountNew() { //ARRANGE BankAccount predictableBankAccount = getBankAccount(); + Company company = getTestCompany(); - companyImdg.insert(company); + Long companyId = companyImdg.insert(company); + Long relationId = 777L; Account predictableAccount = getTestAccount(accountId, acc); + predictableAccount.setProcessingSign(null); + predictableAccount.setCompanyId(companyId); + predictableAccount.setRelationId(relationId); clearImdg(accountImdg); + + ClearingMemberCategory clearingMemberCategory = new ClearingMemberCategory(); + clearingMemberCategory.setClearingMemberCategory(ClearingCategory.B.getKey()); + clearingMemberCategory.setCompanyId(companyId); + clearingMemberCategoryImdg.insert(clearingMemberCategory); + + Relation relation = new Relation(); + relation.setId(relationId); + relation.setConsumerId(companyId); + relation.setService(Service.MKR.getKey()); + relationImdg.insert(relation); + BankAccountNewRequest bankAccountNewRequest = getBankAccountNewRequest(predictableBankAccount); String jsonString = getJsonStringForNew(bankAccountNewRequest, ID); @@ -160,60 +205,55 @@ public class BankAccountServiceTest { companyImdg.insert(company); BankAccountNewRequest bankAccountNewRequest = getBankAccountNewRequest(predictableBankAccount); + String errMsg; //AccountValidationRule.RequiredFields //WrongFieldValue bankAccountNewRequest.setCurrency(null); - checkError("(5004) args [currency]", bankAccountNewRequest); + errMsg = messageResolver.resolve(new EnumMessage(AccountError.RequiredFieldEmpty, "currency")); + checkError(errMsg, bankAccountNewRequest); + + bankAccountNewRequest.setCurrency("TT0"); + errMsg = messageResolver.resolve(new EnumMessage(AccountError.WrongFieldValue, "currency")); + checkError(errMsg, bankAccountNewRequest); bankAccountNewRequest.setCurrency(currency); bankAccountNewRequest.setBankIdentificationCode(null); - checkError("(5004) args [bankIdentificationCode]", bankAccountNewRequest); + errMsg = messageResolver.resolve(new EnumMessage(AccountError.RequiredFieldEmpty, "bankIdentificationCode")); + checkError(errMsg, bankAccountNewRequest); bankAccountNewRequest.setBankIdentificationCode(bankIdentificationCode); bankAccountNewRequest.setBankName(null); - checkError("(5004) args [bankName]", bankAccountNewRequest); + errMsg = messageResolver.resolve(new EnumMessage(AccountError.RequiredFieldEmpty, "bankName")); + checkError(errMsg, bankAccountNewRequest); bankAccountNewRequest.setBankName(bankName); bankAccountNewRequest.setAccount(null); - checkError("(5004) args [account]", bankAccountNewRequest); + errMsg = messageResolver.resolve(new EnumMessage(AccountError.RequiredFieldEmpty, "account")); + checkError(errMsg, bankAccountNewRequest); bankAccountNewRequest.setAccount(acc); bankAccountNewRequest.setDestination(null); - checkError("(5004) args [destination]", bankAccountNewRequest); + errMsg = messageResolver.resolve(new EnumMessage(AccountError.RequiredFieldEmpty, "destination")); + checkError(errMsg, bankAccountNewRequest); bankAccountNewRequest.setDestination(destination); bankAccountNewRequest.setCompanyId(null); - checkError("(5004) args [companyId]", bankAccountNewRequest); + errMsg = messageResolver.resolve(new EnumMessage(AccountError.RequiredFieldEmpty, "companyId")); + checkError(errMsg, bankAccountNewRequest); bankAccountNewRequest.setCompanyId(addresseeIdNew); - //AccountValidationRule.RubRequiredFields - //WrongFieldValue - bankAccountNewRequest.setCorrespondentAccount(null); - checkError("(5004) args [correspondentAccount]", bankAccountNewRequest); - - bankAccountNewRequest.setCorrespondentAccount(correspondentAccount); - bankAccountNewRequest.setCorrespondentAccountName(null); - checkError("(5004) args [correspondentAccountName]", bankAccountNewRequest); - - bankAccountNewRequest.setCorrespondentAccountName(correspondentAccountName); - bankAccountNewRequest.setTaxpayerIdentificationNumber(null); - checkError("(5004) args [taxpayerIdentificationNumber]", bankAccountNewRequest); - - bankAccountNewRequest.setTaxpayerIdentificationNumber(taxpayerIdentificationNumber); - bankAccountNewRequest.setTaxRegistrationReasonCode(null); - checkError("(5004) args [taxRegistrationReasonCode]", bankAccountNewRequest); - bankAccountNewRequest.setTaxRegistrationReasonCode(taxRegistrationReasonCode); - //AccountValidationRule.CompanyPresent //CompanyNotFound bankAccountNewRequest.setCompanyId(999924535239L); - checkError("(5013) args []", bankAccountNewRequest); + errMsg = messageResolver.resolve(new EnumMessage(AccountError.CompanyNotFound, "companyId")); + checkError(errMsg, bankAccountNewRequest); //CompanyNotActive company.setWorkflowStatus(Status.Blocked.getKey()); companyImdg.insert(company); bankAccountNewRequest.setCompanyId(company.getId()); - checkError("(5014) args []", bankAccountNewRequest); + errMsg = messageResolver.resolve(new EnumMessage(AccountError.CompanyNotActive, "companyId")); + checkError(errMsg, bankAccountNewRequest); //AccountValidationRule.AccountIsNew //AccountAlreadyExist @@ -221,7 +261,8 @@ public class BankAccountServiceTest { companyImdg.insert(company); Account existAccount = getTestAccount(accountId, acc); accountImdg.insert(existAccount); - checkError("(5010) args []", bankAccountNewRequest); + errMsg = messageResolver.resolve(new EnumMessage(AccountError.AccountAlreadyExist, "account")); + checkError(errMsg, bankAccountNewRequest); accountImdg.delete(existAccount); } @@ -269,6 +310,7 @@ public class BankAccountServiceTest { */ @Test void bankAccountUpdate() { + clearImdg(accountImdg); //ARRANGE // Company company = getTestCompany(); // companyImdg.insert(company); @@ -282,7 +324,7 @@ public class BankAccountServiceTest { predictableUpdateBankAccount.setBankIdentificationCode("88888"); predictableUpdateBankAccount.setCorrespondentAccount("894984646541316"); predictableUpdateBankAccount.setCorrespondentAccountName("BIK OF NEW BUNK"); - predictableUpdateBankAccount.setCurrency("EU"); + predictableUpdateBankAccount.setCurrency("RUB"); predictableUpdateBankAccount.setDestination("OOO NEW BUNK"); predictableUpdateBankAccount.setTaxpayerIdentificationNumber("65468461321"); predictableUpdateBankAccount.setTaxRegistrationReasonCode("532137"); @@ -309,12 +351,11 @@ public class BankAccountServiceTest { //ASSERT waitingWhenAddedRecordAndCheckIt(ID, producer, producerRecord); - Account accountResult = accountImdg.getSingleObjectBySQL(String.format("account = %s", acc)); - BankAccount resultUpdating = bankAccountImdg.getSingleObjectBySQL(String.format("account = %s or companyId = %s", acc, addresseeIdNew)); + Account accountResult = accountImdg.getSingleObjectByID(predictableAccount.getId()); + BankAccount resultUpdating = bankAccountImdg.getSingleObjectByID(predictableUpdateBankAccount.getId()); + predictableAccount.setUpdated(accountResult.getUpdated()); predictableUpdateBankAccount.setAccountId(resultUpdating.getAccountId()); predictableUpdateBankAccount.setCompanyId(resultUpdating.getCompanyId()); - predictableAccount.setUpdated(accountResult.getUpdated()); - BANK_ACCOUNT_MATCHER.assertMatch(resultUpdating, predictableUpdateBankAccount); ACCOUNT_MATCHER.assertMatch(accountResult, predictableAccount); } @@ -332,6 +373,7 @@ public class BankAccountServiceTest { bankAccountImdg.insert(bankAccountExists); Account account = new Account(); account.setId(accountId); + account.setStatus(WorkflowStatus.Active.getKey()); accountImdg.insert(account); CommonDeleteRequest commonDeleteRequest = new CommonDeleteRequest(); diff --git a/clearing-parent/account-service/src/test/java/ru/spcex/clearing/account/service/ClearingAccountServiceTest.java b/clearing-parent/account-service/src/test/java/ru/spcex/clearing/account/service/ClearingAccountServiceTest.java new file mode 100644 index 000000000..da67ac384 --- /dev/null +++ b/clearing-parent/account-service/src/test/java/ru/spcex/clearing/account/service/ClearingAccountServiceTest.java @@ -0,0 +1,218 @@ +package ru.spcex.clearing.account.service; + +import org.apache.kafka.clients.consumer.MockConsumer; +import org.apache.kafka.clients.producer.MockProducer; +import org.apache.kafka.clients.producer.ProducerRecord; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import ru.clearing.classes.statics.data.account.Account; +import ru.clearing.classes.statics.data.account.ClearingAccount; +import ru.clearing.classes.statics.data.company.ClearingMemberCategory; +import ru.clearing.classes.statics.data.company.Company; +import ru.clearing.classes.statics.data.company.relation.Relation; +import ru.clearing.platform.dictionary.AccountTypeDictionary; +import ru.clearing.platform.dictionary.ClearingAccountTypeDictionary; +import ru.spcex.clearing.account.config.BeanConfiguration; +import ru.spcex.clearing.account.config.HazelcastServiceTestConfiguration; +import ru.spcex.clearing.account.config.KafkaConfigTest; +import ru.spcex.clearing.account.config.validation.AccountValidationConfig; +import ru.spcex.clearing.account.config.validation.ClearingAccountValidationConfig; +import ru.spcex.clearing.account.config.validation.ValidationConfig; +import ru.spcex.clearing.account.utils.MatcherFactory; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.Consts; +import ru.spcex.clearing.platform.messaging.domain.cud.account.ClearingAccountNewRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.account.ClearingAccountUpdateRequest; +import ru.spcex.platform.enumeration.*; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService; + +import javax.annotation.PostConstruct; +import java.util.Map; + +import static ru.spcex.clearing.account.utils.MatcherFactory.usingIgnoringFieldsComparator; +import static ru.spcex.clearing.account.utils.TestUtils.*; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = { + BeanConfiguration.class, + ValidationConfig.class, + ClearingAccountValidationConfig.class, + AccountValidationConfig.class, + AccountService.class, + ClearingAccountService.class, + HazelcastServiceTestConfiguration.class, + KafkaConfigTest.class}) +class ClearingAccountServiceTest { + public static final MatcherFactory.Matcher CLEARING_ACCOUNT_MATCHER = usingIgnoringFieldsComparator(); + public static final MatcherFactory.Matcher ACCOUNT_MATCHER = usingIgnoringFieldsComparator("created", "updated"); + private static final int PARTITION = 0; + private static final Long companyId = 0L; + private static final Long relationId = 0L; + private static final String CLEARING_ACCOUNT_TYPE_DICT = "A"; + private static final String ACCOUNT_VALUE = "account-value"; + private static final String TRADING_CODE = "trading-code"; + + @Autowired + ClearingAccountService clearingAccountService; + + @Autowired + @Qualifier("hazelcastServiceTest") + private HazelcastService hazelcastServiceTest; + + @Captor + private ArgumentCaptor producerRecord; + @SpyBean + private MockProducer producer; + + private Imdg clearingAccountImdg; + private Imdg accountImdg; + private Imdg companyImdg; + private Imdg clearingAccountTypeDictionaryImdg; + private Imdg accountTypeDictionaryImdg; + private Imdg clearingMemberCategoryImdg; + private Imdg relationImdg; + + + @PostConstruct + private void init() { + hazelcastServiceTest.waitAvailable(); + clearingAccountImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_ClearingAccount, ClearingAccount.class + ); + accountImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_Account, Account.class + ); + + companyImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_Company, Company.class + ); + accountTypeDictionaryImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_AccountTypeDictionary, AccountTypeDictionary.class + ); + clearingAccountTypeDictionaryImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_ClearingAccountTypeDictionary, ClearingAccountTypeDictionary.class + ); + clearingMemberCategoryImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class + ); + relationImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_Relation, Relation.class + ); + + Company company = new Company(); + company.setId(companyId); + company.setWorkflowStatus(WorkflowStatus.Active.getKey()); + company.setTradingCode(TRADING_CODE); + companyImdg.insert(company); + + AccountTypeDictionary accountTypeDictionary = new AccountTypeDictionary(); + accountTypeDictionary.setCode(AccountType.Clrn.getKey()); + accountTypeDictionary.setName(AccountType.Clrn.getKey()); + accountTypeDictionaryImdg.insert(accountTypeDictionary); + + ClearingAccountTypeDictionary clearingAccountTypeDictionary = new ClearingAccountTypeDictionary(); + clearingAccountTypeDictionary.setName(CLEARING_ACCOUNT_TYPE_DICT); + clearingAccountTypeDictionary.setCode(CLEARING_ACCOUNT_TYPE_DICT); + clearingAccountTypeDictionaryImdg.insert(clearingAccountTypeDictionary); + + ClearingMemberCategory clearingMemberCategory = new ClearingMemberCategory(); + clearingMemberCategory.setClearingMemberCategory(ClearingCategory.B.getKey()); + clearingMemberCategory.setCompanyId(companyId); + clearingMemberCategoryImdg.insert(clearingMemberCategory); + + Relation relation = new Relation(); + relation.setId(relationId); + relation.setConsumerId(companyId); + relation.setService(Service.MKR.getKey()); + relationImdg.insert(relation); + + } + + @Test + void clearingAccountNew() { + ClearingAccountNewRequest clearingAccountNewRequest = new ClearingAccountNewRequest(); + clearingAccountNewRequest.setAccount(ACCOUNT_VALUE); + clearingAccountNewRequest.setCompanyId(companyId); + clearingAccountNewRequest.setClearingAccountType(CLEARING_ACCOUNT_TYPE_DICT); + + String jsonString = getJsonStringForNew(clearingAccountNewRequest, 0L); + + addRecordToKafka((MockConsumer) clearingAccountService.getConsumer(), + Consts.DESTINATION_CLEARING_ACCOUNT_NEW, + PARTITION, + 0, + jsonString); + + waitingWhenAddedRecordAndCheckIt(0L, producer, producerRecord); + + Account predictableAccount = new Account(); + predictableAccount.setAccount(ACCOUNT_VALUE); + predictableAccount.setAccountType(AccountType.Clrn.getKey()); + predictableAccount.setStatus(AccountStatus.ACTIVE.getKey()); + predictableAccount.setRelationId(relationId); + predictableAccount.setCompanyId(companyId); + + ClearingAccount predictableClearingAccount = new ClearingAccount(); + predictableClearingAccount.setCompanyId(companyId); + predictableClearingAccount.setClearingAccountType(CLEARING_ACCOUNT_TYPE_DICT); + + Account resultAccountNew = accountImdg.getSingleObjectByFieldValues(Map.of("accountType", AccountType.Clrn.getKey())); + ClearingAccount resultClearingAccountNew = clearingAccountImdg.getSingleObjectByFieldValues(Map.of("accountId", resultAccountNew.getId())); + + predictableAccount.setId(resultAccountNew.getId()); + predictableClearingAccount.setAccountId(resultAccountNew.getId()); + predictableClearingAccount.setId(resultClearingAccountNew.getId()); + + ACCOUNT_MATCHER.assertMatch(resultAccountNew, predictableAccount); + CLEARING_ACCOUNT_MATCHER.assertMatch(resultClearingAccountNew, predictableClearingAccount); + + clearingAccountImdg.delete(resultClearingAccountNew); + accountImdg.delete(resultAccountNew); + } + + @Test + void clearingAccountUpdate() { + Account existAccount = new Account(); + existAccount.setAccount(ACCOUNT_VALUE); + existAccount.setStatus(AccountStatus.ACTIVE.getKey()); + existAccount.setAccountType(AccountType.Clrn.getKey()); + Long accountId = accountImdg.insert(existAccount); + + ClearingAccount existClearingAccount = new ClearingAccount(); + existClearingAccount.setAccountId(accountId); + existClearingAccount.setClearingAccountType(CLEARING_ACCOUNT_TYPE_DICT); + existClearingAccount.setCompanyId(companyId); + + Account predictableAccount = new Account(); + predictableAccount.setAccount(ACCOUNT_VALUE); + predictableAccount.setStatus(AccountStatus.BLOCKED.getKey()); + predictableAccount.setAccountType(AccountType.Clrn.getKey()); + + clearingAccountImdg.insert(existClearingAccount); + + ClearingAccountUpdateRequest clearingAccountUpdateRequest = new ClearingAccountUpdateRequest(); + clearingAccountUpdateRequest.setAccount(ACCOUNT_VALUE); + clearingAccountUpdateRequest.setStatus(0); + clearingAccountUpdateRequest.setDeal(TRADING_CODE); + + String jsonString = getJsonStringForUPDATE(clearingAccountUpdateRequest, 0L); + + addRecordToKafka((MockConsumer) clearingAccountService.getConsumer(), Consts.DESTINATION_CLEARING_ACCOUNT_UPDATE, PARTITION, 0, jsonString); + waitingWhenAddedRecordAndCheckIt(0L, producer, producerRecord); + + Account accountResult = accountImdg.getSingleObjectByID(accountId); + predictableAccount.setId(accountResult.getId()); + predictableAccount.setUpdated(accountResult.getUpdated()); + + ACCOUNT_MATCHER.assertMatch(accountResult, predictableAccount); + } + +} \ No newline at end of file diff --git a/clearing-parent/account-service/src/test/java/ru/spcex/clearing/account/service/DepoAccountServiceTest.java b/clearing-parent/account-service/src/test/java/ru/spcex/clearing/account/service/DepoAccountServiceTest.java new file mode 100644 index 000000000..0d6ea0bcb --- /dev/null +++ b/clearing-parent/account-service/src/test/java/ru/spcex/clearing/account/service/DepoAccountServiceTest.java @@ -0,0 +1,180 @@ +package ru.spcex.clearing.account.service; + +import org.apache.kafka.clients.consumer.MockConsumer; +import org.apache.kafka.clients.producer.MockProducer; +import org.apache.kafka.clients.producer.ProducerRecord; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import ru.clearing.classes.statics.data.account.Account; +import ru.clearing.classes.statics.data.account.DepoAccount; +import ru.clearing.classes.statics.data.company.ClearingMemberCategory; +import ru.clearing.classes.statics.data.company.Company; +import ru.clearing.classes.statics.data.company.relation.Relation; +import ru.clearing.platform.dictionary.AccountTypeDictionary; +import ru.clearing.platform.dictionary.DepoAccountTypeDictionary; +import ru.spcex.clearing.account.config.BeanConfiguration; +import ru.spcex.clearing.account.config.HazelcastServiceTestConfiguration; +import ru.spcex.clearing.account.config.KafkaConfigTest; +import ru.spcex.clearing.account.config.validation.AccountValidationConfig; +import ru.spcex.clearing.account.config.validation.DepoAccountValidationConfig; +import ru.spcex.clearing.account.config.validation.ValidationConfig; +import ru.spcex.clearing.account.utils.MatcherFactory; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.Consts; +import ru.spcex.clearing.platform.messaging.domain.cud.account.DepoAccountNewRequest; +import ru.spcex.platform.enumeration.*; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService; + +import javax.annotation.PostConstruct; +import java.util.Map; + +import static ru.spcex.clearing.account.utils.MatcherFactory.usingIgnoringFieldsComparator; +import static ru.spcex.clearing.account.utils.TestUtils.*; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = { + BeanConfiguration.class, + ValidationConfig.class, + DepoAccountValidationConfig.class, + AccountValidationConfig.class, + AccountService.class, + DepoAccountService.class, + HazelcastServiceTestConfiguration.class, + KafkaConfigTest.class}) +class DepoAccountServiceTest { + public static final MatcherFactory.Matcher CLEARING_ACCOUNT_MATCHER = usingIgnoringFieldsComparator(); + public static final MatcherFactory.Matcher ACCOUNT_MATCHER = usingIgnoringFieldsComparator("created", "updated"); + private static final int PARTITION = 0; + private static final Long companyId = 0L; + private static final Long relationId = 0L; + private static final String DEPO_ACCOUNT_TYPE_DICT = "A"; + private static final String ACCOUNT_VALUE = "account-value"; + private static final String TRADING_CODE = "trading-code"; + + @Autowired + DepoAccountService depoAccountService; + + @Autowired + @Qualifier("hazelcastServiceTest") + private HazelcastService hazelcastServiceTest; + + @Captor + private ArgumentCaptor producerRecord; + @SpyBean + private MockProducer producer; + + private Imdg depoAccountImdg; + private Imdg accountImdg; + private Imdg companyImdg; + private Imdg depoAccountTypeDictionaryImdg; + private Imdg accountTypeDictionaryImdg; + private Imdg clearingMemberCategoryImdg; + private Imdg relationImdg; + + + @PostConstruct + private void init() { + hazelcastServiceTest.waitAvailable(); + depoAccountImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_DepoAccount, DepoAccount.class + ); + accountImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_Account, Account.class + ); + + companyImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_Company, Company.class + ); + accountTypeDictionaryImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_AccountTypeDictionary, AccountTypeDictionary.class + ); + depoAccountTypeDictionaryImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_DepoAccountTypeDictionary, DepoAccountTypeDictionary.class + ); + clearingMemberCategoryImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class + ); + relationImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_Relation, Relation.class + ); + + Company company = new Company(); + company.setId(companyId); + company.setWorkflowStatus(WorkflowStatus.Active.getKey()); + company.setTradingCode(TRADING_CODE); + companyImdg.insert(company); + + AccountTypeDictionary accountTypeDictionary = new AccountTypeDictionary(); + accountTypeDictionary.setCode(AccountType.Depo.getKey()); + accountTypeDictionary.setName(AccountType.Depo.getKey()); + accountTypeDictionaryImdg.insert(accountTypeDictionary); + + DepoAccountTypeDictionary depoAccountTypeDictionary = new DepoAccountTypeDictionary(); + depoAccountTypeDictionary.setName(DEPO_ACCOUNT_TYPE_DICT); + depoAccountTypeDictionary.setCode(DEPO_ACCOUNT_TYPE_DICT); + depoAccountTypeDictionaryImdg.insert(depoAccountTypeDictionary); + + ClearingMemberCategory clearingMemberCategory = new ClearingMemberCategory(); + clearingMemberCategory.setClearingMemberCategory(ClearingCategory.B.getKey()); + clearingMemberCategory.setCompanyId(companyId); + clearingMemberCategoryImdg.insert(clearingMemberCategory); + + Relation relation = new Relation(); + relation.setId(relationId); + relation.setConsumerId(companyId); + relation.setService(Service.MKR.getKey()); + relationImdg.insert(relation); + + } + + @Test + void depoAccountNew() { + DepoAccountNewRequest depoAccountNewRequest = new DepoAccountNewRequest(); + depoAccountNewRequest.setAccount(ACCOUNT_VALUE); + depoAccountNewRequest.setCompanyId(companyId); + depoAccountNewRequest.setDepoAccountType(DEPO_ACCOUNT_TYPE_DICT); + + String jsonString = getJsonStringForNew(depoAccountNewRequest, 0L); + + addRecordToKafka((MockConsumer) depoAccountService.getConsumer(), + Consts.DESTINATION_DEPO_ACCOUNT_NEW, + PARTITION, + 0, + jsonString); + + waitingWhenAddedRecordAndCheckIt(0L, producer, producerRecord); + + Account predictableAccount = new Account(); + predictableAccount.setAccount(ACCOUNT_VALUE); + predictableAccount.setAccountType(AccountType.Depo.getKey()); + predictableAccount.setStatus(AccountStatus.ACTIVE.getKey()); + predictableAccount.setRelationId(relationId); + predictableAccount.setCompanyId(companyId); + + DepoAccount predictableDepoAccount = new DepoAccount(); + predictableDepoAccount.setCompanyId(companyId); + predictableDepoAccount.setDepoAccountType(DEPO_ACCOUNT_TYPE_DICT); + + Account resultAccountNew = accountImdg.getSingleObjectByFieldValues(Map.of("accountType", AccountType.Depo.getKey())); + DepoAccount resultDepoAccountNew = depoAccountImdg.getSingleObjectByFieldValues(Map.of("accountId", resultAccountNew.getId())); + + predictableAccount.setId(resultAccountNew.getId()); + predictableDepoAccount.setAccountId(resultAccountNew.getId()); + predictableDepoAccount.setId(resultDepoAccountNew.getId()); + + ACCOUNT_MATCHER.assertMatch(resultAccountNew, predictableAccount); + CLEARING_ACCOUNT_MATCHER.assertMatch(resultDepoAccountNew, predictableDepoAccount); + + depoAccountImdg.delete(resultDepoAccountNew); + accountImdg.delete(resultAccountNew); + } + +} \ No newline at end of file diff --git a/clearing-parent/account-service/src/test/java/ru/spcex/clearing/account/service/InformationAccountServiceTest.java b/clearing-parent/account-service/src/test/java/ru/spcex/clearing/account/service/InformationAccountServiceTest.java new file mode 100644 index 000000000..176245ab5 --- /dev/null +++ b/clearing-parent/account-service/src/test/java/ru/spcex/clearing/account/service/InformationAccountServiceTest.java @@ -0,0 +1,170 @@ +package ru.spcex.clearing.account.service; + +import org.apache.kafka.clients.consumer.MockConsumer; +import org.apache.kafka.clients.producer.MockProducer; +import org.apache.kafka.clients.producer.ProducerRecord; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import ru.clearing.classes.statics.data.account.Account; +import ru.clearing.classes.statics.data.account.InformationAccount; +import ru.clearing.classes.statics.data.company.ClearingMemberCategory; +import ru.clearing.classes.statics.data.company.Company; +import ru.clearing.classes.statics.data.company.relation.Relation; +import ru.clearing.platform.dictionary.AccountTypeDictionary; +import ru.spcex.clearing.account.config.BeanConfiguration; +import ru.spcex.clearing.account.config.HazelcastServiceTestConfiguration; +import ru.spcex.clearing.account.config.KafkaConfigTest; +import ru.spcex.clearing.account.config.validation.AccountValidationConfig; +import ru.spcex.clearing.account.config.validation.InformationAccountValidationConfig; +import ru.spcex.clearing.account.config.validation.ValidationConfig; +import ru.spcex.clearing.account.utils.MatcherFactory; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.Consts; +import ru.spcex.clearing.platform.messaging.domain.cud.account.InformationAccountNewRequest; +import ru.spcex.platform.enumeration.*; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService; + +import javax.annotation.PostConstruct; +import java.util.Map; + +import static ru.spcex.clearing.account.utils.MatcherFactory.usingIgnoringFieldsComparator; +import static ru.spcex.clearing.account.utils.TestUtils.*; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = { + BeanConfiguration.class, + ValidationConfig.class, + InformationAccountValidationConfig.class, + AccountValidationConfig.class, + AccountService.class, + InformationAccountService.class, + HazelcastServiceTestConfiguration.class, + KafkaConfigTest.class}) +class InformationAccountServiceTest { + public static final MatcherFactory.Matcher INFORMATION_ACCOUNT_MATCHER = usingIgnoringFieldsComparator(); + public static final MatcherFactory.Matcher ACCOUNT_MATCHER = usingIgnoringFieldsComparator("created", "updated"); + private static final int PARTITION = 0; + private static final String account = "123456789123"; + private static final Long companyId = 0L; + private static final Long relationId = 0L; + private Long anltAccountId; + + @Autowired + InformationAccountService informationAccountService; + + @Autowired + @Qualifier("hazelcastServiceTest") + private HazelcastService hazelcastServiceTest; + + @Captor + private ArgumentCaptor producerRecord; + @SpyBean + private MockProducer producer; + + private Imdg informationAccountImdg; + private Imdg accountImdg; + private Imdg companyImdg; + private Imdg accountTypeDictionaryImdg; + private Imdg clearingMemberCategoryImdg; + private Imdg relationImdg; + + + @PostConstruct + private void init() { + hazelcastServiceTest.waitAvailable(); + informationAccountImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_InformationAccount, InformationAccount.class + ); + accountImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_Account, Account.class + ); + + companyImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_Company, Company.class + ); + accountTypeDictionaryImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_AccountTypeDictionary, AccountTypeDictionary.class + ); + clearingMemberCategoryImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class + ); + relationImdg = hazelcastServiceTest.getImdg( + IMDGDistributedNames.Map_Relation, Relation.class + ); + + Company company = new Company(); + company.setId(companyId); + company.setWorkflowStatus(WorkflowStatus.Active.getKey()); + companyImdg.insert(company); + + AccountTypeDictionary accountTypeDictionary = new AccountTypeDictionary(); + accountTypeDictionary.setCode(AccountType.Info.getKey()); + accountTypeDictionary.setName(AccountType.Info.getKey()); + accountTypeDictionaryImdg.insert(accountTypeDictionary); + + ClearingMemberCategory clearingMemberCategory = new ClearingMemberCategory(); + clearingMemberCategory.setClearingMemberCategory(ClearingCategory.B.getKey()); + clearingMemberCategory.setCompanyId(companyId); + clearingMemberCategoryImdg.insert(clearingMemberCategory); + + Relation relation = new Relation(); + relation.setId(relationId); + relation.setConsumerId(companyId); + relation.setService(Service.MKR.getKey()); + relationImdg.insert(relation); + + Account accountAnlt = new Account(); + accountAnlt.setAccountType(AccountType.Anlt.getKey()); + accountAnlt.setCompanyId(1L); + anltAccountId = accountImdg.insert(accountAnlt); + } + + @Test + void accountInformationNew() { + InformationAccountNewRequest InformationAccountNewRequest = new InformationAccountNewRequest(); + InformationAccountNewRequest.setCompanyId(companyId); + + String jsonString = getJsonStringForNew(InformationAccountNewRequest, 0L); + + addRecordToKafka((MockConsumer) informationAccountService.getConsumer(), + Consts.DESTINATION_INFORMATION_ACCOUNT_NEW, + PARTITION, + 0, + jsonString); + + waitingWhenAddedRecordAndCheckIt(0L, producer, producerRecord); + + Account predictableAccount = new Account(); + predictableAccount.setAccountType(AccountType.Info.getKey()); + predictableAccount.setStatus(AccountStatus.ACTIVE.getKey()); + predictableAccount.setRelationId(relationId); + predictableAccount.setCompanyId(companyId); + + InformationAccount predictableInfoAccount = new InformationAccount(); + predictableInfoAccount.setCompanyId(companyId); + predictableInfoAccount.setClearingAccountId(anltAccountId); + + Account resultAccountNew = accountImdg.getSingleObjectByFieldValues(Map.of("accountType", AccountType.Info.getKey())); + InformationAccount resultInfoAccountNew = informationAccountImdg.getSingleObjectByFieldValues(Map.of("accountId", resultAccountNew.getId())); + + predictableAccount.setId(resultAccountNew.getId()); + predictableAccount.setAccount(informationAccountService.generateInfoAccount(resultInfoAccountNew.getId())); + predictableInfoAccount.setAccountId(resultAccountNew.getId()); + predictableInfoAccount.setId(resultInfoAccountNew.getId()); + + ACCOUNT_MATCHER.assertMatch(resultAccountNew, predictableAccount); + INFORMATION_ACCOUNT_MATCHER.assertMatch(resultInfoAccountNew, predictableInfoAccount); + + informationAccountImdg.delete(resultInfoAccountNew); + accountImdg.delete(resultAccountNew); + } + +} \ No newline at end of file diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/account/AccountController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/account/AccountController.java index 12e0b79f9..1cebcb051 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/account/AccountController.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/account/AccountController.java @@ -55,7 +55,7 @@ public class AccountController extends AbstractQueueController { public CudResponse add( @ApiParam(value = "Параметры команды в JSON формате.", required = true) @RequestBody AccountNewAction accountNewAction) throws ExecutionException, InterruptedException { - return processRequest(Consts.DESTINATION_ACCOUNT_NEW, accountNewAction); + return processRequest(Consts.DESTINATION_CORRESPONDENT_ACCOUNT_NEW, accountNewAction); } @ApiOperation(value = "update account.") @@ -68,7 +68,7 @@ public class AccountController extends AbstractQueueController { @ApiParam(value = "Новые значения полей объекта.", required = true) @RequestBody AccountUpdateAction accountUpdateAction) throws ExecutionException, InterruptedException { accountUpdateAction.setId(id); - return processRequest(Consts.DESTINATION_ACCOUNT_UPDATE, accountUpdateAction); + return processRequest(Consts.DESTINATION_CORRESPONDENT_ACCOUNT_UPDATE, accountUpdateAction); } @ApiOperation(value = "delete account.") @@ -79,7 +79,7 @@ public class AccountController extends AbstractQueueController { @PathVariable("id") Long id) throws ExecutionException, InterruptedException { CommonDeleteAction deleteAction = new CommonDeleteAction(); deleteAction.setId(id); - return processRequest(Consts.DESTINATION_ACCOUNT_DELETE, deleteAction); + return processRequest(Consts.DESTINATION_CORRESPONDENT_ACCOUNT_BLOCK, deleteAction); } } diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/account/BankAccountController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/account/BankAccountController.java index 662624850..fd927a33b 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/account/BankAccountController.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/queue/account/BankAccountController.java @@ -69,7 +69,7 @@ public class BankAccountController extends AbstractQueueController { @PathVariable("id") Long id) throws ExecutionException, InterruptedException { CommonDeleteAction deleteAction = new CommonDeleteAction(); deleteAction.setId(id); - return processRequest(Consts.DESTINATION_BANK_ACCOUNT_DELETE, deleteAction); + return processRequest(Consts.DESTINATION_BANK_ACCOUNT_BLOCK, deleteAction); } @ApiOperation(value = "get bank account.") diff --git a/clearing-parent/backend-api/src/test/java/ru/spcex/clearing/backendapi/controller/queue/account/AccountControllerTest.java b/clearing-parent/backend-api/src/test/java/ru/spcex/clearing/backendapi/controller/queue/account/AccountControllerTest.java index b00ffc9a0..38c4f02de 100644 --- a/clearing-parent/backend-api/src/test/java/ru/spcex/clearing/backendapi/controller/queue/account/AccountControllerTest.java +++ b/clearing-parent/backend-api/src/test/java/ru/spcex/clearing/backendapi/controller/queue/account/AccountControllerTest.java @@ -46,7 +46,7 @@ class AccountControllerTest extends AbstractControllerTest { //ACT and ASSERT checkAddingByRestApi(REST_URL, accountNewAction); - checkSendedMessegeFromKafka(Consts.DESTINATION_ACCOUNT_NEW, accountNewAction); + checkSendedMessegeFromKafka(Consts.DESTINATION_CORRESPONDENT_ACCOUNT_NEW, accountNewAction); } /** @@ -69,7 +69,7 @@ class AccountControllerTest extends AbstractControllerTest { //ACT and ASSERT checkUpdatingWithIdVolidationByRestApi(IMDGDistributedNames.Map_Account, account, REST_URL, accountUpdateAction, id); - checkSendedMessegeFromKafka(Consts.DESTINATION_ACCOUNT_UPDATE, accountUpdateAction); + checkSendedMessegeFromKafka(Consts.DESTINATION_CORRESPONDENT_ACCOUNT_UPDATE, accountUpdateAction); } /** @@ -88,7 +88,7 @@ class AccountControllerTest extends AbstractControllerTest { //ACT and ASSERT checkDeletingWithIdVolidationByRestApi(IMDGDistributedNames.Map_Account, account, REST_URL, id); - checkSendedMessegeFromKafka(Consts.DESTINATION_ACCOUNT_DELETE, deleteAction); + checkSendedMessegeFromKafka(Consts.DESTINATION_CORRESPONDENT_ACCOUNT_BLOCK, deleteAction); } diff --git a/clearing-parent/backend-api/src/test/java/ru/spcex/clearing/backendapi/controller/queue/account/BankAccountControllerTest.java b/clearing-parent/backend-api/src/test/java/ru/spcex/clearing/backendapi/controller/queue/account/BankAccountControllerTest.java index 6c60d38e8..4ddd90e6e 100644 --- a/clearing-parent/backend-api/src/test/java/ru/spcex/clearing/backendapi/controller/queue/account/BankAccountControllerTest.java +++ b/clearing-parent/backend-api/src/test/java/ru/spcex/clearing/backendapi/controller/queue/account/BankAccountControllerTest.java @@ -134,7 +134,7 @@ class BankAccountControllerTest extends AbstractControllerTest { deleteAction.setId(id); //ACT and ASSERT checkDeletingByRestApi(REST_URL, id); - checkSendedMessegeFromKafka(Consts.DESTINATION_BANK_ACCOUNT_DELETE, deleteAction); + checkSendedMessegeFromKafka(Consts.DESTINATION_BANK_ACCOUNT_BLOCK, deleteAction); } /** 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/clearing-parent/clearing-validation/src/main/java/ru/spcex/clearing/validation/common/rules/FieldRequiredRule.java b/clearing-parent/clearing-validation/src/main/java/ru/spcex/clearing/validation/common/rules/FieldRequiredRule.java index eaa468190..43c6e0e0a 100644 --- a/clearing-parent/clearing-validation/src/main/java/ru/spcex/clearing/validation/common/rules/FieldRequiredRule.java +++ b/clearing-parent/clearing-validation/src/main/java/ru/spcex/clearing/validation/common/rules/FieldRequiredRule.java @@ -16,6 +16,7 @@ import java.util.function.Function; * @param getter Метод получения значения * @param errorEmptyRequiredValue Ошибка, которая будет возвращена, если поле пустое * @param additionalChecks Дополнительные проверки, связанные с этим полем + * @param required Флаг обязательности поля * @param Класс проверяемого объекта * @param Класс проверяемого значения */ @@ -23,9 +24,29 @@ public record FieldRequiredRule( String fieldName, Function getter, IErrorEnumId errorEmptyRequiredValue, + boolean required, Function[] additionalChecks ) implements IValidationRule> { + /** + * @param fieldName Название поля + * @param getter Метод получения значения + * @param errorEmptyRequiredValue Ошибка, которая будет возвращена, если поле пустое + * @param additionalChecks Дополнительные проверки, связанные с этим полем + * @param required Флаг обязательности поля + * @param Класс проверяемого объекта + * @param Класс проверяемого значения + */ + @SafeVarargs + public static FieldRequiredRule instance(String fieldName, + Function getter, + IErrorEnumId errorEmptyRequiredValue, + boolean required, + Function... additionalChecks) { + if (errorEmptyRequiredValue == null) throw new IllegalArgumentException("Empty errorEmptyRequiredValue"); + return new FieldRequiredRule<>(fieldName, getter, errorEmptyRequiredValue, required, additionalChecks); + } + /** * @param fieldName Название поля * @param getter Метод получения значения @@ -40,18 +61,17 @@ public record FieldRequiredRule( IErrorEnumId errorEmptyRequiredValue, Function... additionalChecks) { if (errorEmptyRequiredValue == null) throw new IllegalArgumentException("Empty errorEmptyRequiredValue"); - return new FieldRequiredRule<>(fieldName, getter, errorEmptyRequiredValue, additionalChecks); + return new FieldRequiredRule<>(fieldName, getter, errorEmptyRequiredValue, true, additionalChecks); } @Override public Optional validate(ImdgValidationContext context) { R validatedObject = context.getValidatedObject(); V value = getter.apply(validatedObject); - if (value == null) return of(errorEmptyRequiredValue, fieldName); + if (required && value == null) return of(errorEmptyRequiredValue, fieldName); for (Function additionalCheck : additionalChecks) { IErrorEnumId validationError = additionalCheck.apply(value); - if (validationError != null) - return of(validationError, fieldName); + if (validationError != null) return of(validationError, fieldName); } return empty(); } diff --git a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/AccountType.java b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/AccountType.java index 51184296e..8f8ad6fdb 100644 --- a/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/AccountType.java +++ b/platform-parent/platform-enum/src/main/java/ru/spcex/platform/enumeration/AccountType.java @@ -3,7 +3,7 @@ package ru.spcex.platform.enumeration; import ru.spcex.platform.utils.enumeration.IEnumKey; public enum AccountType implements IEnumKey { - Clrn("CLRN"), Bank("BANK"), Info("INFO"), Tran("TRAN"), Corr("CORR"), Anlt("ANLT"); + Clrn("CLRN"), Bank("BANK"), Info("INFO"), Tran("TRAN"), Corr("CORR"), Anlt("ANLT"), Depo("DEPO"); private final String key; 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 04ec6af5c..51410a656 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 @@ -54,12 +54,24 @@ public interface Consts { String DESTINATION_CLEARING_MEMBER_CATEGORY_UPDATE = "clearing-member-category-update"; String DESTINATION_CLEARING_MEMBER_CATEGORY_DELETE = "clearing-member-category-delete"; - String DESTINATION_ACCOUNT_DELETE = "account-delete"; - String DESTINATION_ACCOUNT_UPDATE = "account-update"; - String DESTINATION_ACCOUNT_NEW = "account-new"; - String DESTINATION_BANK_ACCOUNT_DELETE = "bank-account-delete"; + String DESTINATION_DEPO_ACCOUNT_NEW = "depo-account-new"; + + String DESTINATION_CLEARING_ACCOUNT_NEW = "clearing-account-new"; + String DESTINATION_CLEARING_ACCOUNT_UPDATE = "clearing-account-update"; + + String DESTINATION_INFORMATION_ACCOUNT_NEW = "information-account-new"; + + String DESTINATION_CORRESPONDENT_ACCOUNT_NEW = "correspondent-account-new"; + String DESTINATION_CORRESPONDENT_ACCOUNT_UPDATE = "correspondent-account-update"; + String DESTINATION_CORRESPONDENT_ACCOUNT_BLOCK = "correspondent-account-block"; + + String DESTINATION_BANK_ACCOUNT_BLOCK = "bank-account-block"; String DESTINATION_BANK_ACCOUNT_UPDATE = "bank-account-update"; String DESTINATION_BANK_ACCOUNT_NEW = "bank-account-new"; + + @Deprecated + String ACCOUNT_NEW_SDF01 = "account-new-sdf01"; + String DESTINATION_RELATION_UPDATE = "relation-update"; String DESTINATION_PROFILE_DOCUMENT_NEW = "profile-document-new"; String DESTINATION_PROFILE_DOCUMENT_UPDATE = "profile-document-update"; diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/ClearingAccountNewRequest.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/ClearingAccountNewRequest.java new file mode 100644 index 000000000..2de9404db --- /dev/null +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/ClearingAccountNewRequest.java @@ -0,0 +1,39 @@ +package ru.spcex.clearing.platform.messaging.domain.cud.account; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ClearingAccountNewRequest { + @JsonProperty + public String account; + + @JsonProperty + public String clearingAccountType; + + @JsonProperty + public Long companyId; + + + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + + public String getClearingAccountType() { + return clearingAccountType; + } + + public void setClearingAccountType(String clearingAccountType) { + this.clearingAccountType = clearingAccountType; + } + + public Long getCompanyId() { + return companyId; + } + + public void setCompanyId(Long companyId) { + this.companyId = companyId; + } +} diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/ClearingAccountUpdateRequest.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/ClearingAccountUpdateRequest.java new file mode 100644 index 000000000..bfbb51211 --- /dev/null +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/ClearingAccountUpdateRequest.java @@ -0,0 +1,38 @@ +package ru.spcex.clearing.platform.messaging.domain.cud.account; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ClearingAccountUpdateRequest { + @JsonProperty + public String account; + + @JsonProperty + public Integer status; + + @JsonProperty + public String deal; + + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public String getDeal() { + return deal; + } + + public void setDeal(String deal) { + this.deal = deal; + } +} diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/CorrespondentAccountNewRequest.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/CorrespondentAccountNewRequest.java new file mode 100644 index 000000000..dc33c7dbe --- /dev/null +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/CorrespondentAccountNewRequest.java @@ -0,0 +1,49 @@ +package ru.spcex.clearing.platform.messaging.domain.cud.account; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class CorrespondentAccountNewRequest { + @JsonProperty + public Long companyId; + + @JsonProperty + public String account; + + @JsonProperty + public String status; + + @JsonProperty + public String accountType; + + public Long getCompanyId() { + return companyId; + } + + public void setCompanyId(Long companyId) { + this.companyId = companyId; + } + + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getAccountType() { + return accountType; + } + + public void setAccountType(String accountType) { + this.accountType = accountType; + } +} diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/CorrespondentAccountUpdateRequest.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/CorrespondentAccountUpdateRequest.java new file mode 100644 index 000000000..24afc0ee5 --- /dev/null +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/CorrespondentAccountUpdateRequest.java @@ -0,0 +1,60 @@ +package ru.spcex.clearing.platform.messaging.domain.cud.account; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class CorrespondentAccountUpdateRequest { + @JsonProperty + public Long id; + + @JsonProperty + public Long companyId; + + @JsonProperty + public String account; + + @JsonProperty + public String status; + + @JsonProperty + public String accountType; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getCompanyId() { + return companyId; + } + + public void setCompanyId(Long companyId) { + this.companyId = companyId; + } + + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getAccountType() { + return accountType; + } + + public void setAccountType(String accountType) { + this.accountType = accountType; + } +} diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/DepoAccountNewRequest.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/DepoAccountNewRequest.java new file mode 100644 index 000000000..efc416b62 --- /dev/null +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/DepoAccountNewRequest.java @@ -0,0 +1,39 @@ +package ru.spcex.clearing.platform.messaging.domain.cud.account; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class DepoAccountNewRequest { + @JsonProperty + public String account; + + @JsonProperty + public String depoAccountType; + + @JsonProperty + public Long companyId; + + + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + + public String getDepoAccountType() { + return depoAccountType; + } + + public void setDepoAccountType(String depoAccountType) { + this.depoAccountType = depoAccountType; + } + + public Long getCompanyId() { + return companyId; + } + + public void setCompanyId(Long companyId) { + this.companyId = companyId; + } +} diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/InformationAccountNewRequest.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/InformationAccountNewRequest.java new file mode 100644 index 000000000..6b7b9636f --- /dev/null +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/InformationAccountNewRequest.java @@ -0,0 +1,16 @@ +package ru.spcex.clearing.platform.messaging.domain.cud.account; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class InformationAccountNewRequest { + @JsonProperty + public Long companyId; + + public Long getCompanyId() { + return companyId; + } + + public void setCompanyId(Long companyId) { + this.companyId = companyId; + } +} diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/sdf01/AccountSdf01Request.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/sdf01/AccountSdf01Request.java index 2e9cb13a2..ac51a7e37 100644 --- a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/sdf01/AccountSdf01Request.java +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/sdf01/AccountSdf01Request.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import java.util.List; +@Deprecated public class AccountSdf01Request { private Long groupingSdf01Id; diff --git a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/sdf01/AccountSdfRequestPart.java b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/sdf01/AccountSdfRequestPart.java index 863d1a974..987235af7 100644 --- a/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/sdf01/AccountSdfRequestPart.java +++ b/platform-parent/platform-messaging/src/main/java/ru/spcex/clearing/platform/messaging/domain/cud/account/sdf01/AccountSdfRequestPart.java @@ -2,6 +2,7 @@ package ru.spcex.clearing.platform.messaging.domain.cud.account.sdf01; import com.fasterxml.jackson.annotation.JsonProperty; +@Deprecated public class AccountSdfRequestPart { @JsonProperty private Long sdfId;