From b6a9a2791df84d80035dc089600b96075c4aab8a Mon Sep 17 00:00:00 2001 From: rrpawar96 Date: Sat, 18 Dec 2021 17:16:40 +0530 Subject: [PATCH] FINERACT-1391:AccountNumberPrefixPreference --- .../data/AccountNumberFormatData.java | 13 +++++-- .../AccountNumberFormatDataValidator.java | 12 +++++- .../domain/AccountNumberFormat.java | 14 ++++++- .../AccountNumberFormatEnumerations.java | 16 +++++--- .../service/AccountNumberFormatConstants.java | 2 + ...ntNumberFormatReadPlatformServiceImpl.java | 6 ++- ...WritePlatformServiceJpaRepositoryImpl.java | 11 +++++- .../client/domain/AccountNumberGenerator.java | 38 ++++++++++++++++++- .../V220_1__prefix_type_account_number.sql | 23 +++++++++++ 9 files changed, 117 insertions(+), 18 deletions(-) create mode 100644 fineract-provider/src/main/resources/sql/migrations/core_db/V220_1__prefix_type_account_number.sql diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/data/AccountNumberFormatData.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/data/AccountNumberFormatData.java index 37393224a..c04979fa5 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/data/AccountNumberFormatData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/data/AccountNumberFormatData.java @@ -34,12 +34,15 @@ public class AccountNumberFormatData implements Serializable { private List accountTypeOptions; private Map> prefixTypeOptions; - public AccountNumberFormatData(final Long id, final EnumOptionData accountType, final EnumOptionData prefixType) { - this(id, accountType, prefixType, null, null); + private String prefixCharacter; + + public AccountNumberFormatData(final Long id, final EnumOptionData accountType, final EnumOptionData prefixType, + final String prefixCharacter) { + this(id, accountType, prefixType, null, null, prefixCharacter); } public AccountNumberFormatData(final List accountTypeOptions, Map> prefixTypeOptions) { - this(null, null, null, accountTypeOptions, prefixTypeOptions); + this(null, null, null, accountTypeOptions, prefixTypeOptions, null); } public void templateOnTop(List accountTypeOptions, Map> prefixTypeOptions) { @@ -48,12 +51,14 @@ public class AccountNumberFormatData implements Serializable { } private AccountNumberFormatData(final Long id, final EnumOptionData accountType, final EnumOptionData prefixType, - final List accountTypeOptions, Map> prefixTypeOptions) { + final List accountTypeOptions, Map> prefixTypeOptions, + final String prefixCharacter) { this.id = id; this.accountType = accountType; this.prefixType = prefixType; this.accountTypeOptions = accountTypeOptions; this.prefixTypeOptions = prefixTypeOptions; + this.prefixCharacter = prefixCharacter; } public Long getId() { diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/data/AccountNumberFormatDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/data/AccountNumberFormatDataValidator.java index 09c8a4253..7bdbe2271 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/data/AccountNumberFormatDataValidator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/data/AccountNumberFormatDataValidator.java @@ -51,10 +51,11 @@ public class AccountNumberFormatDataValidator { private static final Logger LOG = LoggerFactory.getLogger(AccountNumberFormatDataValidator.class); private static final Set ACCOUNT_NUMBER_FORMAT_CREATE_REQUEST_DATA_PARAMETERS = new HashSet<>( - Arrays.asList(AccountNumberFormatConstants.accountTypeParamName, AccountNumberFormatConstants.prefixTypeParamName)); + Arrays.asList(AccountNumberFormatConstants.accountTypeParamName, AccountNumberFormatConstants.prefixTypeParamName, + AccountNumberFormatConstants.prefixCharacterParamName)); private static final Set ACCOUNT_NUMBER_FORMAT_UPDATE_REQUEST_DATA_PARAMETERS = new HashSet<>( - Arrays.asList(AccountNumberFormatConstants.prefixTypeParamName)); + Arrays.asList(AccountNumberFormatConstants.prefixTypeParamName, AccountNumberFormatConstants.prefixCharacterParamName)); @Autowired public AccountNumberFormatDataValidator(final FromJsonHelper fromApiJsonHelper) { @@ -84,6 +85,13 @@ public class AccountNumberFormatDataValidator { DataValidatorBuilder dataValidatorForValidatingPrefixType = baseDataValidator.reset() .parameter(AccountNumberFormatConstants.prefixTypeParamName).value(prefixType).notNull().integerGreaterThanZero(); + if (prefixType.equals(AccountNumberPrefixType.PREFIX_SHORT_NAME.getValue())) { + final String prefixCharacter = this.fromApiJsonHelper + .extractStringNamed(AccountNumberFormatConstants.prefixCharacterParamName, element); + + baseDataValidator.reset().parameter(AccountNumberFormatConstants.prefixTypeParamName).value(prefixCharacter).notBlank(); + } + /** * Permitted values for prefix type vary based on the actual selected accountType, carry out this validation * only if data validation errors do not exist for both entity type and prefix type diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/domain/AccountNumberFormat.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/domain/AccountNumberFormat.java index fa4025383..77be4fc6f 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/domain/AccountNumberFormat.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/domain/AccountNumberFormat.java @@ -37,21 +37,29 @@ public class AccountNumberFormat extends AbstractPersistableCustom { @Column(name = AccountNumberFormatConstants.PREFIX_TYPE_ENUM_COLUMN_NAME, nullable = true) private Integer prefixEnum; + @Column(name = AccountNumberFormatConstants.PREFIX_CHARACTER_COLUMN_NAME, nullable = true) + private String prefixCharacter; + protected AccountNumberFormat() { // } - public AccountNumberFormat(EntityAccountType entityAccountType, AccountNumberPrefixType prefixType) { + public AccountNumberFormat(EntityAccountType entityAccountType, AccountNumberPrefixType prefixType, String prefixCharacter) { this.accountTypeEnum = entityAccountType.getValue(); if (prefixType != null) { this.prefixEnum = prefixType.getValue(); } + this.prefixCharacter = prefixCharacter; } public Integer getAccountTypeEnum() { return this.accountTypeEnum; } + public String getPrefixCharacter() { + return this.prefixCharacter; + } + public EntityAccountType getAccountType() { return EntityAccountType.fromInt(this.accountTypeEnum); } @@ -75,4 +83,8 @@ public class AccountNumberFormat extends AbstractPersistableCustom { public void setPrefix(AccountNumberPrefixType accountNumberPrefixType) { setPrefixEnum(accountNumberPrefixType.getValue()); } + + public void setPrefixCharacter(String prefixCharacter) { + this.prefixCharacter = prefixCharacter; + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/domain/AccountNumberFormatEnumerations.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/domain/AccountNumberFormatEnumerations.java index 37649e23e..8e1b2f50c 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/domain/AccountNumberFormatEnumerations.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/domain/AccountNumberFormatEnumerations.java @@ -35,13 +35,16 @@ public final class AccountNumberFormatEnumerations { } public static final Set accountNumberPrefixesForClientAccounts = Collections - .unmodifiableSet(new HashSet<>(Arrays.asList(AccountNumberPrefixType.OFFICE_NAME, AccountNumberPrefixType.CLIENT_TYPE))); + .unmodifiableSet(new HashSet<>(Arrays.asList(AccountNumberPrefixType.OFFICE_NAME, AccountNumberPrefixType.CLIENT_TYPE, + AccountNumberPrefixType.PREFIX_SHORT_NAME))); - public static final Set accountNumberPrefixesForLoanAccounts = Collections.unmodifiableSet( - new HashSet<>(Arrays.asList(AccountNumberPrefixType.OFFICE_NAME, AccountNumberPrefixType.LOAN_PRODUCT_SHORT_NAME))); + public static final Set accountNumberPrefixesForLoanAccounts = Collections + .unmodifiableSet(new HashSet<>(Arrays.asList(AccountNumberPrefixType.OFFICE_NAME, + AccountNumberPrefixType.LOAN_PRODUCT_SHORT_NAME, AccountNumberPrefixType.PREFIX_SHORT_NAME))); - public static final Set accountNumberPrefixesForSavingsAccounts = Collections.unmodifiableSet( - new HashSet<>(Arrays.asList(AccountNumberPrefixType.OFFICE_NAME, AccountNumberPrefixType.SAVINGS_PRODUCT_SHORT_NAME))); + public static final Set accountNumberPrefixesForSavingsAccounts = Collections + .unmodifiableSet(new HashSet<>(Arrays.asList(AccountNumberPrefixType.OFFICE_NAME, + AccountNumberPrefixType.SAVINGS_PRODUCT_SHORT_NAME, AccountNumberPrefixType.PREFIX_SHORT_NAME))); public static final Set accountNumberPrefixesForCenters = Collections .unmodifiableSet(new HashSet<>(Collections.singletonList(AccountNumberPrefixType.OFFICE_NAME))); @@ -54,7 +57,8 @@ public final class AccountNumberFormatEnumerations { OFFICE_NAME(1, "accountNumberPrefixType.officeName"), CLIENT_TYPE(101, "accountNumberPrefixType.clientType"), LOAN_PRODUCT_SHORT_NAME(201, "accountNumberPrefixType.loanProductShortName"), SAVINGS_PRODUCT_SHORT_NAME(301, - "accountNumberPrefixType.savingsProductShortName"); + "accountNumberPrefixType.savingsProductShortName"), PREFIX_SHORT_NAME(401, + "accountNumberPrefixType.prefixShortName"); private final Integer value; private final String code; diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/service/AccountNumberFormatConstants.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/service/AccountNumberFormatConstants.java index 0bce265c0..5800e2361 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/service/AccountNumberFormatConstants.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/service/AccountNumberFormatConstants.java @@ -40,6 +40,7 @@ public final class AccountNumberFormatConstants { public static final String idParamName = "id"; public static final String accountTypeParamName = "accountType"; public static final String prefixTypeParamName = "prefixType"; + public static final String prefixCharacterParamName = "prefixCharacter"; // response parameters @@ -62,5 +63,6 @@ public final class AccountNumberFormatConstants { public static final String ACCOUNT_TYPE_ENUM_COLUMN_NAME = "account_type_enum"; public static final String PREFIX_TYPE_ENUM_COLUMN_NAME = "prefix_type_enum"; public static final String ACCOUNT_TYPE_UNIQUE_CONSTRAINT_NAME = "account_type_enum"; + public static final String PREFIX_CHARACTER_COLUMN_NAME = "prefix_character"; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/service/AccountNumberFormatReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/service/AccountNumberFormatReadPlatformServiceImpl.java index d25c2911c..22a887808 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/service/AccountNumberFormatReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/service/AccountNumberFormatReadPlatformServiceImpl.java @@ -64,7 +64,8 @@ public class AccountNumberFormatReadPlatformServiceImpl implements AccountNumber AccountNumberFormatMapper() { final StringBuilder builder = new StringBuilder(400); - builder.append(" anf.id as id, anf.account_type_enum as accountTypeEnum, anf.prefix_type_enum as prefixTypeEnum"); + builder.append( + " anf.id as id, anf.account_type_enum as accountTypeEnum, anf.prefix_type_enum as prefixTypeEnum, anf.prefix_character as prefixCharacter"); builder.append(" from c_account_number_format anf "); this.schema = builder.toString(); @@ -80,13 +81,14 @@ public class AccountNumberFormatReadPlatformServiceImpl implements AccountNumber final Long id = rs.getLong("id"); final Integer accountTypeEnum = rs.getInt("accountTypeEnum"); final Integer prefixTypeEnum = JdbcSupport.getInteger(rs, "prefixTypeEnum"); + final String prefixCharacter = rs.getString("prefixCharacter"); final EnumOptionData accountNumberType = AccountNumberFormatEnumerations.entityAccountType(accountTypeEnum); EnumOptionData prefixType = null; if (prefixTypeEnum != null) { prefixType = AccountNumberFormatEnumerations.accountNumberPrefixType(prefixTypeEnum); } - return new AccountNumberFormatData(id, accountNumberType, prefixType); + return new AccountNumberFormatData(id, accountNumberType, prefixType, prefixCharacter); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/service/AccountNumberFormatWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/service/AccountNumberFormatWritePlatformServiceJpaRepositoryImpl.java index 36ae1e3a5..f45818728 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/service/AccountNumberFormatWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/accountnumberformat/service/AccountNumberFormatWritePlatformServiceJpaRepositoryImpl.java @@ -68,7 +68,9 @@ public class AccountNumberFormatWritePlatformServiceJpaRepositoryImpl implements accountNumberPrefixType = AccountNumberPrefixType.fromInt(prefixTypeId); } - AccountNumberFormat accountNumberFormat = new AccountNumberFormat(entityAccountType, accountNumberPrefixType); + String prefixCharacter = command.stringValueOfParameterNamed(AccountNumberFormatConstants.prefixCharacterParamName); + + AccountNumberFormat accountNumberFormat = new AccountNumberFormat(entityAccountType, accountNumberPrefixType, prefixCharacter); this.accountNumberFormatRepository.save(accountNumberFormat); @@ -106,6 +108,13 @@ public class AccountNumberFormatWritePlatformServiceJpaRepositoryImpl implements accountNumberFormatForUpdate.setPrefix(accountNumberPrefixType); } + if (command.isChangeInStringParameterNamed(AccountNumberFormatConstants.prefixCharacterParamName, + accountNumberFormatForUpdate.getPrefixCharacter())) { + final String newValue = command.stringValueOfParameterNamed(AccountNumberFormatConstants.prefixCharacterParamName); + actualChanges.put(AccountNumberFormatConstants.prefixCharacterParamName, newValue); + accountNumberFormatForUpdate.setPrefixCharacter(newValue); + } + if (!actualChanges.isEmpty()) { this.accountNumberFormatRepository.saveAndFlush(accountNumberFormatForUpdate); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/AccountNumberGenerator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/AccountNumberGenerator.java index 6a3bb31fc..1195bd69b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/AccountNumberGenerator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/AccountNumberGenerator.java @@ -23,6 +23,7 @@ import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.apache.fineract.infrastructure.accountnumberformat.domain.AccountNumberFormat; import org.apache.fineract.infrastructure.accountnumberformat.domain.AccountNumberFormatEnumerations.AccountNumberPrefixType; +import org.apache.fineract.infrastructure.accountnumberformat.domain.AccountNumberFormatRepository; import org.apache.fineract.infrastructure.codes.domain.CodeValue; import org.apache.fineract.infrastructure.configuration.data.GlobalConfigurationPropertyData; import org.apache.fineract.infrastructure.configuration.service.ConfigurationReadPlatformService; @@ -48,11 +49,15 @@ public class AccountNumberGenerator { private static final String LOAN_PRODUCT_SHORT_NAME = "loanProductShortName"; private static final String SAVINGS_PRODUCT_SHORT_NAME = "savingsProductShortName"; private static final String SHARE_PRODUCT_SHORT_NAME = "sharesProductShortName"; + private static final String PREFIX_SHORT_NAME = "prefixShortName"; + private final AccountNumberFormatRepository accountNumberFormatRepository; private final ConfigurationReadPlatformService configurationReadPlatformService; @Autowired - public AccountNumberGenerator(final ConfigurationReadPlatformService configurationReadPlatformService) { + public AccountNumberGenerator(final ConfigurationReadPlatformService configurationReadPlatformService, + final AccountNumberFormatRepository accountNumberFormatRepository) { this.configurationReadPlatformService = configurationReadPlatformService; + this.accountNumberFormatRepository = accountNumberFormatRepository; } public String generate(Client client, AccountNumberFormat accountNumberFormat) { @@ -101,7 +106,6 @@ public class AccountNumberGenerator { if (customLength.getValue() != null) { accountMaxLength = customLength.getValue().intValue(); } - } String accountNumber = StringUtils.leftPad(propertyMap.get(ID), accountMaxLength, '0'); @@ -125,6 +129,10 @@ public class AccountNumberGenerator { prefix = propertyMap.get(SAVINGS_PRODUCT_SHORT_NAME); break; + case PREFIX_SHORT_NAME: + generatePrefix(propertyMap, propertyMap.get(ID), accountMaxLength, accountNumberFormat); + prefix = propertyMap.get(PREFIX_SHORT_NAME); + break; } // FINERACT-590 @@ -133,12 +141,38 @@ public class AccountNumberGenerator { if (prefix != null) { prefix = prefix.substring(0, Math.min(prefix.length(), 10)); } + if (accountNumberPrefixType.getValue().equals(AccountNumberPrefixType.PREFIX_SHORT_NAME.getValue())) { + Integer prefixLength = prefix.length(); + Integer numberLength = accountMaxLength - prefixLength; + accountNumber = StringUtils.leftPad(propertyMap.get(ID), numberLength, '0'); + } else { + accountNumber = StringUtils.leftPad(accountNumber, Integer.valueOf(propertyMap.get(ID).length()), '0'); + } accountNumber = StringUtils.overlay(accountNumber, prefix, 0, 0); } return accountNumber; } + private Map generatePrefix(Map propertyMap, String accountNumber, Integer accountMaxLength, + AccountNumberFormat accountNumberFormat) { + + String prefix = accountNumberFormat.getPrefixCharacter(); + Integer prefixLength = prefix.length(); + + Integer totalLength = prefixLength + Integer.valueOf(propertyMap.get(ID).length()); + + prefixLength = totalLength - accountMaxLength; + + if (prefixLength > 0) { + prefix = prefix.substring(0, prefix.length() - prefixLength); + } + + propertyMap.put(PREFIX_SHORT_NAME, prefix); + + return propertyMap; + } + public String generateGroupAccountNumber(Group group, AccountNumberFormat accountNumberFormat) { Map propertyMap = new HashMap<>(); propertyMap.put(ID, group.getId().toString()); diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V220_1__prefix_type_account_number.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V220_1__prefix_type_account_number.sql new file mode 100644 index 000000000..47bab73f3 --- /dev/null +++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V220_1__prefix_type_account_number.sql @@ -0,0 +1,23 @@ +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, +-- software distributed under the License is distributed on an +-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +-- KIND, either express or implied. See the License for the +-- specific language governing permissions and limitations +-- under the License. +-- + + + +ALTER TABLE `c_account_number_format` + ADD COLUMN `prefix_character` VARCHAR(50) NULL DEFAULT NULL AFTER `prefix_type_enum`;