FINERACT-2421: Rework code value handling in E2E

This commit is contained in:
Adam Saghy
2026-01-16 17:59:14 +01:00
parent 0f73ae1eb7
commit 0891adb267
18 changed files with 328 additions and 148 deletions
@@ -30,6 +30,7 @@ import org.apache.fineract.client.feign.util.CallFailedRuntimeException;
import org.apache.fineract.client.models.PostCodeValuesDataRequest;
import org.apache.fineract.client.models.PostCodesRequest;
import org.apache.fineract.client.models.PutCodeValuesDataRequest;
import org.apache.fineract.test.data.codevalue.CodeNames;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@@ -40,44 +41,26 @@ import org.springframework.stereotype.Component;
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CodeGlobalInitializerStep implements FineractGlobalInitializerStep {
public static final String CODE_NAME_FINANCIAL_INSTRUMENT = "financial_instrument";
public static final String CODE_NAME_TRANSACTION_TYPE = "transaction_type";
public static final String CODE_NAME_BANKRUPTCY_TAG = "bankruptcy_tag";
public static final String CODE_NAME_PENDING_FRAUD_TAG = "pending_fraud_tag";
public static final String CODE_NAME_PENDING_DECEASED_TAG = "pending_deceased_tag";
public static final String CODE_NAME_HARDSHIP_TAG = "hardship_tag";
public static final String CODE_NAME_ACTIVE_DUTY_TAG = "active_duty_tag";
public static final Long CODE_VALUE_ADDRESS_TYPE_ID = 29L;
public static final String CODE_VALUE_ADDRESS_TYPE_RESIDENTIAL = "Residential address";
public static final String CODE_VALUE_ADDRESS_TYPE_OFFICE = "Office address";
public static final Long CODE_VALUE_COUNTRY_ID = 28L;
public static final String CODE_VALUE_COUNTRY_GERMANY = "Germany";
public static final Long CODE_VALUE_STATE_ID = 27L;
public static final String CODE_VALUE_STATE_BERLIN = "Berlin";
public static final Long CODE_VALUE_FINANCIAL_INSTRUMENT_ID = 39L;
public static final String CODE_VALUE_FINANCIAL_INSTRUMENT_DEBIT = "debit_card";
public static final String CODE_VALUE_FINANCIAL_INSTRUMENT_CREDIT = "credit_card";
public static final String CODE_VALUE_FINANCIAL_INSTRUMENT_FRAUD = "Fraud";
public static final String CODE_VALUE_FINANCIAL_INSTRUMENT_DELINQUENT = "Delinquent";
public static final String CODE_VALUE_FINANCIAL_INSTRUMENT_OTHER = "Other";
public static final Long CODE_VALUE_TRANSACTION_TYPE_ID = 40L;
public static final String CODE_VALUE_CHARGE_OFF_REASON_FRAUD = "Fraud";
public static final String CODE_VALUE_CHARGE_OFF_REASON_DELINQUENT = "Delinquent";
public static final String CODE_VALUE_CHARGE_OFF_REASON_OTHER = "Other";
public static final String CODE_VALUE_TRANSACTION_TYPE_SCHEDULED_PAYMENT = "scheduled_payment";
public static final Long CODE_VALUE_BANKRUPTCY_TAG_ID = 41L;
public static final String CODE_VALUE_BANKRUPTCY_TAG_PENDING = "pending_bankruptcy";
public static final String CODE_VALUE_BANKRUPTCY_TAG_BANKRUPTCY = "bankruptcy";
public static final Long CODE_VALUE_PENDING_FRAUD_TAG_ID = 42L;
public static final String CODE_VALUE_PENDING_FRAUD_TAG_PENDING = "pending_fraud";
public static final String CODE_VALUE_PENDING_FRAUD_TAG_FRAUD = "fraud";
public static final Long CODE_VALUE_PENDING_DECEASED_TAG_ID = 43L;
public static final String CODE_VALUE_PENDING_DECEASED_TAG_PENDING = "pending_deceased";
public static final String CODE_VALUE_PENDING_DECEASED_TAG_DECEASED = "deceased";
public static final Long CODE_VALUE_HARDSHIP_TAG_ID = 44L;
public static final String CODE_VALUE_HARDSHIP_TAG_ACTIVE = "active";
public static final String CODE_VALUE_HARDSHIP_TAG_INACTIVE = "inactive";
public static final Long CODE_VALUE_ACTIVE_DUTY_TAG_ID = 45L;
public static final String CODE_VALUE_ACTIVE_DUTY_TAG_ACTIVE = "active";
public static final String CODE_VALUE_ACTIVE_DUTY_TAG_INACTIVE = "inactive";
public static final Long CODE_VALUE_CUSTOMER_IDENTIFIERS_ID = 1L;
public static final String CODE_VALUE_CUSTOMER_IDENTIFIERS_1 = "Passport";
public static final String CODE_VALUE_CUSTOMER_IDENTIFIERS_2 = "Id";
public static final String CODE_VALUE_CUSTOMER_IDENTIFIERS_3 = "Drivers License";
@@ -86,37 +69,30 @@ public class CodeGlobalInitializerStep implements FineractGlobalInitializerStep
public static final String CODE_VALUE_CUSTOMER_IDENTIFIERS_6 = "TIN";
public static final String CODE_VALUE_CUSTOMER_IDENTIFIERS_7 = "ITIN";
public static final String CODE_VALUE_CUSTOMER_IDENTIFIERS_8 = "EIN";
public static final Long CODE_VALUE_GENDER_ID = 4L;
public static final String CODE_VALUE_GENDER_FEMALE = "Female";
public static final String CODE_VALUE_GENDER_MALE = "Male";
public static final Long CODE_VALUE_CLIENT_TYPE_ID = 16L;
public static final String CODE_VALUE_CLIENT_TYPE_CORPORATE = "Corporate";
public static final String CODE_VALUE_CLIENT_TYPE_LEGAL = "Legal";
public static final String CODE_VALUE_CLIENT_TYPE_NON_LEGAL = "Non-legal";
public static final Long CODE_VALUE_CLIENT_CLASSIFICATION_ID = 17L;
public static final String CODE_VALUE_CLIENT_CLASSIFICATION_LAWYER = "Lawyer";
public static final String CODE_VALUE_CLIENT_CLASSIFICATION_DIRECTOR = "Director";
public static final String CODE_VALUE_CLIENT_CLASSIFICATION_NONE = "None";
public static final Long CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_ID = 31L;
public static final String CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_SPOUSE = "Spouse";
public static final String CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_FATHER = "Father";
public static final String CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_MOTHER = "Mother";
public static final String CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_CHILD = "Child";
public static final Long CODE_VALUE_FAMILY_MEMBER_PROFESSION_ID = 32L;
public static final String CODE_VALUE_FAMILY_MEMBER_PROFESSION_EMPLOYEE = "Employee";
public static final String CODE_VALUE_FAMILY_MEMBER_PROFESSION_SELF_EMPLOYED = "Self-Employed";
public static final Long CODE_VALUE_FAMILY_MARITAL_STATUS_ID = 30L;
public static final String CODE_VALUE_FAMILY_MARITAL_STATUS_MARRIED = "Married";
public static final String CODE_VALUE_FAMILY_MARITAL_STATUS_SINGLE = "Single";
public static final String CODE_VALUE_FAMILY_MARITAL_STATUS_WIDOWED = "Widowed";
public static final Long CODE_VALUE_CONSTITUTION_ID = 24L;
public static final String CODE_VALUE_CONSTITUTION_TEST = "Test";
public static final Long CODE_VALUE_RESCHEDULE_REASON_ID = 23L;
public static final String CODE_VALUE_RESCHEDULE_REASON_TEST = "Test";
public static final Long CODE_VALUE_WRITE_OFF_REASON_ID = 26L;
public static final String CODE_VALUE_WRITE_OFF_REASON_TEST_1 = "Bad Debt";
public static final String CODE_VALUE_WRITE_OFF_REASON_TEST_2 = "Forgiven";
public static final String CODE_VALUE_WRITE_OFF_REASON_TEST_3 = "Test";
public static final String BUYDOWN_FEE_TRANSACTION_CLASSIFICATION_VALUE = "buydown_fee_transaction_classification_value";
public static final String CAPITALIZED_INCOME_TRANSACTION_CLASSIFICATION_VALUE = "capitalized_income_transaction_classification_value";
private final FineractFeignClient fineractClient;
@@ -131,61 +107,64 @@ public class CodeGlobalInitializerStep implements FineractGlobalInitializerStep
List<String> addressNames = new ArrayList<>();
addressNames.add(CODE_VALUE_ADDRESS_TYPE_RESIDENTIAL);
addressNames.add(CODE_VALUE_ADDRESS_TYPE_OFFICE);
createCodeValues(CODE_VALUE_ADDRESS_TYPE_ID, addressNames);
createCodeValues(CodeNames.ADDRESS_TYPE.getValue(), addressNames);
// Country
List<String> countryNames = new ArrayList<>();
countryNames.add(CODE_VALUE_COUNTRY_GERMANY);
createCodeValues(CODE_VALUE_COUNTRY_ID, countryNames);
createCodeValues(CodeNames.COUNTRY.getValue(), countryNames);
// State
List<String> stateNames = new ArrayList<>();
stateNames.add(CODE_VALUE_STATE_BERLIN);
createCodeValues(CODE_VALUE_STATE_ID, stateNames);
createCodeValues(CodeNames.STATE.getValue(), stateNames);
// financial instrument
List<String> financialInstrumentNames = new ArrayList<>();
financialInstrumentNames.add(CODE_VALUE_FINANCIAL_INSTRUMENT_DEBIT);
financialInstrumentNames.add(CODE_VALUE_FINANCIAL_INSTRUMENT_CREDIT);
financialInstrumentNames.add(CODE_VALUE_FINANCIAL_INSTRUMENT_FRAUD);
financialInstrumentNames.add(CODE_VALUE_FINANCIAL_INSTRUMENT_DELINQUENT);
financialInstrumentNames.add(CODE_VALUE_FINANCIAL_INSTRUMENT_OTHER);
createCodeValues(CODE_VALUE_FINANCIAL_INSTRUMENT_ID, financialInstrumentNames);
createCodeValues(CodeNames.FINANCIAL_INSTRUMENT.getValue(), financialInstrumentNames);
List<String> chargeOffReasonNames = new ArrayList<>();
chargeOffReasonNames.add(CODE_VALUE_CHARGE_OFF_REASON_FRAUD);
chargeOffReasonNames.add(CODE_VALUE_CHARGE_OFF_REASON_DELINQUENT);
chargeOffReasonNames.add(CODE_VALUE_CHARGE_OFF_REASON_OTHER);
createCodeValues(CodeNames.CHARGE_OFF.getValue(), chargeOffReasonNames);
// transaction type
List<String> transactionTypeNames = new ArrayList<>();
transactionTypeNames.add(CODE_VALUE_TRANSACTION_TYPE_SCHEDULED_PAYMENT);
createCodeValues(CODE_VALUE_TRANSACTION_TYPE_ID, transactionTypeNames);
createCodeValues(CodeNames.TRANSACTION_TYPE.getValue(), transactionTypeNames);
// bankruptcy tag
List<String> bankruptcyTagNames = new ArrayList<>();
bankruptcyTagNames.add(CODE_VALUE_BANKRUPTCY_TAG_PENDING);
bankruptcyTagNames.add(CODE_VALUE_BANKRUPTCY_TAG_BANKRUPTCY);
createCodeValues(CODE_VALUE_BANKRUPTCY_TAG_ID, bankruptcyTagNames);
createCodeValues(CodeNames.BANKRUPTCY_TAG.getValue(), bankruptcyTagNames);
// pending fraud tag
List<String> pendingFraudTagNames = new ArrayList<>();
pendingFraudTagNames.add(CODE_VALUE_PENDING_FRAUD_TAG_PENDING);
pendingFraudTagNames.add(CODE_VALUE_PENDING_FRAUD_TAG_FRAUD);
createCodeValues(CODE_VALUE_PENDING_FRAUD_TAG_ID, pendingFraudTagNames);
createCodeValues(CodeNames.PENDING_FRAUD_TAG.getValue(), pendingFraudTagNames);
// pending deceased tag
List<String> pendingDeceasedTagNames = new ArrayList<>();
pendingDeceasedTagNames.add(CODE_VALUE_PENDING_DECEASED_TAG_PENDING);
pendingDeceasedTagNames.add(CODE_VALUE_PENDING_DECEASED_TAG_DECEASED);
createCodeValues(CODE_VALUE_PENDING_DECEASED_TAG_ID, pendingDeceasedTagNames);
createCodeValues(CodeNames.PENDING_DECEASED_TAG.getValue(), pendingDeceasedTagNames);
// hardship tag
List<String> hardshipTagNames = new ArrayList<>();
hardshipTagNames.add(CODE_VALUE_HARDSHIP_TAG_ACTIVE);
hardshipTagNames.add(CODE_VALUE_HARDSHIP_TAG_INACTIVE);
createCodeValues(CODE_VALUE_HARDSHIP_TAG_ID, hardshipTagNames);
createCodeValues(CodeNames.HARDSHIP_TAG.getValue(), hardshipTagNames);
// active duty tag
List<String> activeDutyTagNames = new ArrayList<>();
activeDutyTagNames.add(CODE_VALUE_ACTIVE_DUTY_TAG_ACTIVE);
activeDutyTagNames.add(CODE_VALUE_ACTIVE_DUTY_TAG_INACTIVE);
createCodeValues(CODE_VALUE_ACTIVE_DUTY_TAG_ID, activeDutyTagNames);
createCodeValues(CodeNames.ACTIVE_DUTY_TAG.getValue(), activeDutyTagNames);
// customer identifiers put/post
List<String> customerIdentifierNamesPut = new ArrayList<>();
@@ -193,34 +172,34 @@ public class CodeGlobalInitializerStep implements FineractGlobalInitializerStep
customerIdentifierNamesPut.add(CODE_VALUE_CUSTOMER_IDENTIFIERS_2);
customerIdentifierNamesPut.add(CODE_VALUE_CUSTOMER_IDENTIFIERS_3);
customerIdentifierNamesPut.add(CODE_VALUE_CUSTOMER_IDENTIFIERS_4);
updateCodeValues(CODE_VALUE_CUSTOMER_IDENTIFIERS_ID, customerIdentifierNamesPut);
updateCodeValues(CodeNames.CUSTOMER_IDENTIFIER.getValue(), customerIdentifierNamesPut);
List<String> customerIdentifierNamesPost = new ArrayList<>();
customerIdentifierNamesPost.add(CODE_VALUE_CUSTOMER_IDENTIFIERS_5);
customerIdentifierNamesPost.add(CODE_VALUE_CUSTOMER_IDENTIFIERS_6);
customerIdentifierNamesPost.add(CODE_VALUE_CUSTOMER_IDENTIFIERS_7);
customerIdentifierNamesPost.add(CODE_VALUE_CUSTOMER_IDENTIFIERS_8);
createCodeValues(CODE_VALUE_CUSTOMER_IDENTIFIERS_ID, customerIdentifierNamesPost);
createCodeValues(CodeNames.CUSTOMER_IDENTIFIER.getValue(), customerIdentifierNamesPost);
// gender
List<String> genderNames = new ArrayList<>();
genderNames.add(CODE_VALUE_GENDER_FEMALE);
genderNames.add(CODE_VALUE_GENDER_MALE);
createCodeValues(CODE_VALUE_GENDER_ID, genderNames);
createCodeValues(CodeNames.GENDER.getValue(), genderNames);
// client type
List<String> clientTypeNames = new ArrayList<>();
clientTypeNames.add(CODE_VALUE_CLIENT_TYPE_CORPORATE);
clientTypeNames.add(CODE_VALUE_CLIENT_TYPE_LEGAL);
clientTypeNames.add(CODE_VALUE_CLIENT_TYPE_NON_LEGAL);
createCodeValues(CODE_VALUE_CLIENT_TYPE_ID, clientTypeNames);
createCodeValues(CodeNames.CLIENT_TYPE.getValue(), clientTypeNames);
// client classification
List<String> clientClassificationNames = new ArrayList<>();
clientClassificationNames.add(CODE_VALUE_CLIENT_CLASSIFICATION_LAWYER);
clientClassificationNames.add(CODE_VALUE_CLIENT_CLASSIFICATION_DIRECTOR);
clientClassificationNames.add(CODE_VALUE_CLIENT_CLASSIFICATION_NONE);
createCodeValues(CODE_VALUE_CLIENT_CLASSIFICATION_ID, clientClassificationNames);
createCodeValues(CodeNames.CLIENT_CLASSIFICATION.getValue(), clientClassificationNames);
// add family member - relationship
List<String> familyMemberRelationshipNames = new ArrayList<>();
@@ -228,40 +207,51 @@ public class CodeGlobalInitializerStep implements FineractGlobalInitializerStep
familyMemberRelationshipNames.add(CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_FATHER);
familyMemberRelationshipNames.add(CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_MOTHER);
familyMemberRelationshipNames.add(CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_CHILD);
createCodeValues(CODE_VALUE_FAMILY_MEMBER_RELATIONSHIP_ID, familyMemberRelationshipNames);
createCodeValues(CodeNames.FAMILY_MEMBER_RELATIONSHIP.getValue(), familyMemberRelationshipNames);
// add family member - profession
List<String> familyMemberProfessionNames = new ArrayList<>();
familyMemberProfessionNames.add(CODE_VALUE_FAMILY_MEMBER_PROFESSION_EMPLOYEE);
familyMemberProfessionNames.add(CODE_VALUE_FAMILY_MEMBER_PROFESSION_SELF_EMPLOYED);
createCodeValues(CODE_VALUE_FAMILY_MEMBER_PROFESSION_ID, familyMemberProfessionNames);
createCodeValues(CodeNames.FAMILY_MEMBER_PROFESSION.getValue(), familyMemberProfessionNames);
// add family member - marital status
List<String> familyMemberMaritalStatusNames = new ArrayList<>();
familyMemberMaritalStatusNames.add(CODE_VALUE_FAMILY_MARITAL_STATUS_MARRIED);
familyMemberMaritalStatusNames.add(CODE_VALUE_FAMILY_MARITAL_STATUS_SINGLE);
familyMemberMaritalStatusNames.add(CODE_VALUE_FAMILY_MARITAL_STATUS_WIDOWED);
createCodeValues(CODE_VALUE_FAMILY_MARITAL_STATUS_ID, familyMemberMaritalStatusNames);
createCodeValues(CodeNames.FAMILY_MARITAL_STATUS.getValue(), familyMemberMaritalStatusNames);
// add constitution (for client creation as Entity)
List<String> constitutionNames = new ArrayList<>();
constitutionNames.add(CODE_VALUE_CONSTITUTION_TEST);
createCodeValues(CODE_VALUE_CONSTITUTION_ID, constitutionNames);
createCodeValues(CodeNames.CONSTITUTION.getValue(), constitutionNames);
// add LoanRescheduleReason
List<String> rescheduleReasonNames = new ArrayList<>();
rescheduleReasonNames.add(CODE_VALUE_RESCHEDULE_REASON_TEST);
createCodeValues(CODE_VALUE_RESCHEDULE_REASON_ID, rescheduleReasonNames);
createCodeValues(CodeNames.LOAN_RESCHEDULE_REASON.getValue(), rescheduleReasonNames);
// add Write-off reasons
List<String> writeOffReasonNames = new ArrayList<>();
writeOffReasonNames.add(CODE_VALUE_WRITE_OFF_REASON_TEST_1);
writeOffReasonNames.add(CODE_VALUE_WRITE_OFF_REASON_TEST_2);
writeOffReasonNames.add(CODE_VALUE_WRITE_OFF_REASON_TEST_3);
createCodeValues(CODE_VALUE_WRITE_OFF_REASON_ID, writeOffReasonNames);
createCodeValues(CodeNames.WRITE_OFF_REASON.getValue(), writeOffReasonNames);
// Add buy down fee transaction classification
List<String> buydownFeeTransactionClassificationName = new ArrayList<>();
buydownFeeTransactionClassificationName.add(BUYDOWN_FEE_TRANSACTION_CLASSIFICATION_VALUE);
createCodeValues(CodeNames.BUYDOWN_FEE_TRANSACTION_CLASSIFICATION.getValue(), buydownFeeTransactionClassificationName);
// Add capitalized income transaction classification
List<String> capitalizedIncomeTransactionClassificationName = new ArrayList<>();
capitalizedIncomeTransactionClassificationName.add(CAPITALIZED_INCOME_TRANSACTION_CLASSIFICATION_VALUE);
createCodeValues(CodeNames.CAPITALIZED_INCOME_TRANSACTION_CLASSIFICATION.getValue(),
capitalizedIncomeTransactionClassificationName);
}
public void createCodeValues(Long codeId, List<String> codeValueNames) {
public void createCodeValues(String codeName, List<String> codeValueNames) {
codeValueNames.forEach(name -> {
Integer position = codeValueNames.indexOf(name);
PostCodeValuesDataRequest postCodeValuesDataRequest = new PostCodeValuesDataRequest();
@@ -270,7 +260,7 @@ public class CodeGlobalInitializerStep implements FineractGlobalInitializerStep
postCodeValuesDataRequest.position(position);
try {
executeVoid(() -> fineractClient.codeValues().createCodeValue(codeId, postCodeValuesDataRequest, Map.of()));
executeVoid(() -> fineractClient.codeValues().createCodeValue1(codeName, postCodeValuesDataRequest, Map.of()));
log.debug("Code value '{}' created successfully", name);
} catch (CallFailedRuntimeException e) {
if (e.getStatus() == 403 && e.getDeveloperMessage() != null && e.getDeveloperMessage().contains("already exists")) {
@@ -282,7 +272,7 @@ public class CodeGlobalInitializerStep implements FineractGlobalInitializerStep
});
}
public void updateCodeValues(Long codeId, List<String> codeValueNames) {
public void updateCodeValues(String codeName, List<String> codeValueNames) {
codeValueNames.forEach(name -> {
int position = codeValueNames.indexOf(name) + 1;
PutCodeValuesDataRequest putCodeValuesDataRequest = new PutCodeValuesDataRequest();
@@ -290,19 +280,19 @@ public class CodeGlobalInitializerStep implements FineractGlobalInitializerStep
putCodeValuesDataRequest.name(name);
putCodeValuesDataRequest.position(position);
executeVoid(() -> fineractClient.codeValues().updateCodeValue(codeId, (long) position, putCodeValuesDataRequest, Map.of()));
executeVoid(() -> fineractClient.codeValues().updateCodeValue1(codeName, (long) position, putCodeValuesDataRequest, Map.of()));
});
}
private void createCodeNames() {
List<String> codesNameList = new ArrayList<>();
codesNameList.add(CODE_NAME_FINANCIAL_INSTRUMENT);
codesNameList.add(CODE_NAME_TRANSACTION_TYPE);
codesNameList.add(CODE_NAME_BANKRUPTCY_TAG);
codesNameList.add(CODE_NAME_PENDING_FRAUD_TAG);
codesNameList.add(CODE_NAME_PENDING_DECEASED_TAG);
codesNameList.add(CODE_NAME_HARDSHIP_TAG);
codesNameList.add(CODE_NAME_ACTIVE_DUTY_TAG);
codesNameList.add(CodeNames.FINANCIAL_INSTRUMENT.getValue());
codesNameList.add(CodeNames.TRANSACTION_TYPE.getValue());
codesNameList.add(CodeNames.BANKRUPTCY_TAG.getValue());
codesNameList.add(CodeNames.PENDING_FRAUD_TAG.getValue());
codesNameList.add(CodeNames.PENDING_DECEASED_TAG.getValue());
codesNameList.add(CodeNames.HARDSHIP_TAG.getValue());
codesNameList.add(CodeNames.ACTIVE_DUTY_TAG.getValue());
codesNameList.forEach(codeName -> {
try {
@@ -62,6 +62,7 @@ import org.apache.fineract.test.data.OverAppliedCalculationType;
import org.apache.fineract.test.data.PreClosureInterestCalculationRule;
import org.apache.fineract.test.data.RecalculationRestFrequencyType;
import org.apache.fineract.test.data.TransactionProcessingStrategyCode;
import org.apache.fineract.test.data.codevalue.CodeNames;
import org.apache.fineract.test.data.codevalue.CodeValue;
import org.apache.fineract.test.data.codevalue.CodeValueResolver;
import org.apache.fineract.test.data.codevalue.DefaultCodeValue;
@@ -3697,7 +3698,9 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
List<PostClassificationToIncomeAccountMappings> buydownfeeClassificationToIncomeAccountMappings = new ArrayList<>();
PostClassificationToIncomeAccountMappings classificationToIncomeAccountMappings = new PostClassificationToIncomeAccountMappings();
classificationToIncomeAccountMappings.setClassificationCodeValueId(25L);
long classificationId = codeValueResolver.resolve(CodeNames.BUYDOWN_FEE_TRANSACTION_CLASSIFICATION.getValue(),
CodeGlobalInitializerStep.BUYDOWN_FEE_TRANSACTION_CLASSIFICATION_VALUE);
classificationToIncomeAccountMappings.setClassificationCodeValueId(classificationId);
classificationToIncomeAccountMappings.setIncomeAccountId(10L);
buydownfeeClassificationToIncomeAccountMappings.add(classificationToIncomeAccountMappings);
@@ -3736,7 +3739,10 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
List<PostClassificationToIncomeAccountMappings> capitalizedIncomeClassificationToIncomeAccountMappings = new ArrayList<>();
PostClassificationToIncomeAccountMappings classificationToIncomeAccountMappingsCapitalizedIncome = new PostClassificationToIncomeAccountMappings();
classificationToIncomeAccountMappingsCapitalizedIncome.setClassificationCodeValueId(24L);
long capitalizedIncomeClassificationId = codeValueResolver.resolve(
CodeNames.CAPITALIZED_INCOME_TRANSACTION_CLASSIFICATION.getValue(),
CodeGlobalInitializerStep.CAPITALIZED_INCOME_TRANSACTION_CLASSIFICATION_VALUE);
classificationToIncomeAccountMappingsCapitalizedIncome.setClassificationCodeValueId(capitalizedIncomeClassificationId);
classificationToIncomeAccountMappingsCapitalizedIncome.setIncomeAccountId(15L);
capitalizedIncomeClassificationToIncomeAccountMappings.add(classificationToIncomeAccountMappingsCapitalizedIncome);
@@ -3232,7 +3232,7 @@ Feature:Feature: Buy Down Fees
And Admin successfully approves the loan on "01 January 2024" with "100" amount and expected disbursement date on "01 January 2024"
And Admin successfully disburse the loan on "01 January 2024" with "100" EUR transaction amount
Then Loan status will be "ACTIVE"
When Admin adds buy down fee with "AUTOPAY" payment type to the loan on "01 January 2024" with "50" EUR transaction amount and "buydown_fee_transaction_classification" classification
When Admin adds buy down fee with "AUTOPAY" payment type to the loan on "01 January 2024" with "50" EUR transaction amount and "buydown_fee_transaction_classification_value" classification
Then Loan Repayment schedule has 3 periods, with the following data for periods:
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| | | 01 January 2024 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | |
@@ -3841,7 +3841,7 @@ Feature:Feature: Buy Down Fees
| LP2_PROGRESSIVE_ADVANCED_PAYMENT_ALLOCATION_BUYDOWN_FEES_CLASSIFICATION_INCOME_MAP | 01 January 2024 | 350 | 7 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 3 | MONTHS | 1 | MONTHS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
And Admin successfully approves the loan on "01 January 2024" with "350" amount and expected disbursement date on "01 January 2024"
And Admin successfully disburse the loan on "01 January 2024" with "100" EUR transaction amount
And Admin adds buy down fee with "AUTOPAY" payment type to the loan on "01 January 2024" with "50" EUR transaction amount and classification: pending_bankruptcy
When Admin adds buy down fee with "AUTOPAY" payment type to the loan on "01 January 2024" with "50" EUR transaction amount and "buydown_fee_transaction_classification_value" classification
And Admin sets the business date to "02 January 2024"
And Admin runs inline COB job for Loan
Then Loan Transactions tab has a "BUY_DOWN_FEE" transaction with date "01 January 2024" which has the following Journal entries:
@@ -3868,7 +3868,7 @@ Feature:Feature: Buy Down Fees
And Admin adds buy down fee with "AUTOPAY" payment type to the loan on "01 January 2024" with "50" EUR transaction amount
And Admin sets the business date to "02 January 2024"
And Admin runs inline COB job for Loan
And Admin adds buy down fee with "AUTOPAY" payment type to the loan on "02 January 2024" with "20" EUR transaction amount and classification: pending_bankruptcy
When Admin adds buy down fee with "AUTOPAY" payment type to the loan on "02 January 2024" with "20" EUR transaction amount and "buydown_fee_transaction_classification_value" classification
And Admin sets the business date to "03 January 2024"
And Admin runs inline COB job for Loan
Then Loan Transactions tab has a "BUY_DOWN_FEE" transaction with date "01 January 2024" which has the following Journal entries:
@@ -3902,7 +3902,7 @@ Feature:Feature: Buy Down Fees
And Admin successfully approves the loan on "01 January 2024" with "100" amount and expected disbursement date on "01 January 2024"
And Admin successfully disburse the loan on "01 January 2024" with "100" EUR transaction amount
Then Loan status will be "ACTIVE"
When Admin adds buy down fee with "AUTOPAY" payment type to the loan on "01 January 2024" with "50" EUR transaction amount and classification: pending_bankruptcy
When Admin adds buy down fee with "AUTOPAY" payment type to the loan on "01 January 2024" with "50" EUR transaction amount and "buydown_fee_transaction_classification_value" classification
Then Loan Repayment schedule has 3 periods, with the following data for periods:
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| | | 01 January 2024 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | |
@@ -3920,7 +3920,7 @@ Feature:Feature: Buy Down Fees
| Type | Account code | Account name | Debit | Credit |
| EXPENSE | 450280 | Buy Down Expense | 50.0 | |
| LIABILITY | 145024 | Deferred Capitalized Income | | 50.0 |
And Loan Transactions tab has a "Buy Down Fee" transaction with date "01 January 2024" which has classification code value "pending_bankruptcy"
And Loan Transactions tab has a "Buy Down Fee" transaction with date "01 January 2024" which has classification code value "buydown_fee_transaction_classification_value"
And Buy down fee contains the following data:
| Date | Fee Amount | Amortized Amount | Not Yet Amortized Amount | Adjusted Amount | Charged Off Amount |
| 01 January 2024 | 50.0 | 0.0 | 50.0 | 0.0 | 0.0 |
@@ -7673,7 +7673,7 @@ Feature: Capitalized Income
And Admin successfully disburse the loan on "1 January 2024" with "900" EUR transaction amount
Then Loan status will be "ACTIVE"
When Admin sets the business date to "2 January 2024"
And Admin adds capitalized income with "AUTOPAY" payment type to the loan on "2 January 2024" with "100" EUR transaction amount and "capitalized_income_transaction_classification" classification
And Admin adds capitalized income with "AUTOPAY" payment type to the loan on "2 January 2024" with "100" EUR transaction amount and "capitalized_income_transaction_classification_value" classification
Then Loan Repayment schedule has 2 periods, with the following data for periods:
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| | | 01 January 2024 | | 900.0 | | | 0.0 | | 0.0 | 0.0 | | | |
@@ -8277,7 +8277,7 @@ Feature: Capitalized Income
Then Loan is closed with zero outstanding balance and it's all installments have obligations met
@TestRailId:C4096
Scenario: Verify GL entries for Capitalized Income Amortization - UC2: Amortization for Capitalized Income with classification rule: pending_bankruptcy
Scenario: Verify GL entries for Capitalized Income Amortization - UC2: Amortization for Capitalized Income with classification rule: capitalized_income_transaction_classification_value
When Admin sets the business date to "01 January 2024"
And Admin creates a client with random data
When Admin creates a fully customized loan with the following data:
@@ -8285,7 +8285,7 @@ Feature: Capitalized Income
| LP2_PROGRESSIVE_ADV_PMNT_ALLOCATION_CAPITALIZED_INCOME_ADJ_CUSTOM_ALLOC_CLASSIFICATION_INCOME_MAP | 01 January 2024 | 350 | 7 | DECLINING_BALANCE | DAILY | EQUAL_INSTALLMENTS | 3 | MONTHS | 1 | MONTHS | 3 | 0 | 0 | 0 | ADVANCED_PAYMENT_ALLOCATION |
And Admin successfully approves the loan on "01 January 2024" with "350" amount and expected disbursement date on "01 January 2024"
And Admin successfully disburse the loan on "01 January 2024" with "100" EUR transaction amount
And Admin adds capitalized income with "AUTOPAY" payment type to the loan on "01 January 2024" with "50" EUR transaction amount and classification: scheduled_payment
And Admin adds capitalized income with "AUTOPAY" payment type to the loan on "01 January 2024" with "50" EUR transaction amount and "capitalized_income_transaction_classification_value" classification
When Admin sets the business date to "02 January 2024"
And Admin runs inline COB job for Loan
Then Loan Transactions tab has a "CAPITALIZED_INCOME" transaction with date "01 January 2024" which has the following Journal entries:
@@ -8301,7 +8301,7 @@ Feature: Capitalized Income
Then Loan is closed with zero outstanding balance and it's all installments have obligations met
@TestRailId:C4097
Scenario: Verify GL entries for Capitalized Income Amortization - UC3: Amortization for Capitalized Incomes with NO classification and with classification rule: pending_bankruptcy
Scenario: Verify GL entries for Capitalized Income Amortization - UC3: Amortization for Capitalized Incomes with NO classification and with classification rule: capitalized_income_transaction_classification_value
When Admin sets the business date to "01 January 2024"
And Admin creates a client with random data
When Admin creates a fully customized loan with the following data:
@@ -8312,7 +8312,7 @@ Feature: Capitalized Income
And Admin adds capitalized income with "AUTOPAY" payment type to the loan on "01 January 2024" with "50" EUR transaction amount
When Admin sets the business date to "02 January 2024"
And Admin runs inline COB job for Loan
And Admin adds capitalized income with "AUTOPAY" payment type to the loan on "02 January 2024" with "20" EUR transaction amount and classification: scheduled_payment
And Admin adds capitalized income with "AUTOPAY" payment type to the loan on "02 January 2024" with "20" EUR transaction amount and "capitalized_income_transaction_classification_value" classification
When Admin sets the business date to "03 January 2024"
And Admin runs inline COB job for Loan
Then Loan Transactions tab has a "CAPITALIZED_INCOME" transaction with date "01 January 2024" which has the following Journal entries:
@@ -8346,7 +8346,7 @@ Feature: Capitalized Income
And Admin successfully approves the loan on "01 January 2024" with "200" amount and expected disbursement date on "01 January 2024"
And Admin successfully disburse the loan on "01 January 2024" with "100" EUR transaction amount
Then Loan status will be "ACTIVE"
And Admin adds capitalized income with "AUTOPAY" payment type to the loan on "01 January 2024" with "50" EUR transaction amount and classification: scheduled_payment
And Admin adds capitalized income with "AUTOPAY" payment type to the loan on "01 January 2024" with "50" EUR transaction amount and "capitalized_income_transaction_classification_value" classification
Then Loan Repayment schedule has 3 periods, with the following data for periods:
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| | | 01 January 2024 | | 100.0 | | | 0.0 | | 0.0 | 0.0 | | | |
@@ -8365,7 +8365,7 @@ Feature: Capitalized Income
| Type | Account code | Account name | Debit | Credit |
| ASSET | 112601 | Loans Receivable | 50.0 | |
| LIABILITY | 145024 | Deferred Capitalized Income | | 50.0 |
And Loan Transactions tab has a "Capitalized Income" transaction with date "01 January 2024" which has classification code value "scheduled_payment"
And Loan Transactions tab has a "Capitalized Income" transaction with date "01 January 2024" which has classification code value "capitalized_income_transaction_classification_value"
Then LoanCapitalizedIncomeTransactionCreatedBusinessEvent is raised on "01 January 2024"
And Admin adds capitalized income adjustment with "AUTOPAY" payment type to the loan on "01 January 2024" with "25" EUR transaction amount
Then Loan Transactions tab has the following data:
@@ -187,26 +187,22 @@ Feature: LoanProduct
When Admin sets the business date to "12 December 2021"
When Admin creates a client with random data
And Admin successfully creates a new customised Loan submitted on date: "12 December 2021", with Principal: "1000", a loanTermFrequency: 1 months, and numberOfRepayments: 1
Then Loan Product Charge-Off reasons options from loan product template have 5 options, with the following data:
Then Loan Product Charge-Off reasons options from loan product template have 3 options, with the following data:
| Charge-Off Reason Name | Description | Position | Is Active | Is Mandatory |
| debit_card | | 0 | true | false |
| credit_card | | 1 | true | false |
| Fraud | | 2 | true | false |
| Delinquent | | 3 | true | false |
| Other | | 4 | true | false |
| Fraud | | 0 | true | false |
| Delinquent | | 1 | true | false |
| Other | | 2 | true | false |
@TestRailId:C3482
Scenario: As a user I would like to verify Charge-Off reasons options in specific loan product response
When Admin sets the business date to "12 December 2021"
When Admin creates a client with random data
And Admin successfully creates a new customised Loan submitted on date: "12 December 2021", with Principal: "1000", a loanTermFrequency: 1 months, and numberOfRepayments: 1
Then Loan Product "LP1" Charge-Off reasons options from specific loan product have 5 options, with the following data:
Then Loan Product "LP1" Charge-Off reasons options from specific loan product have 3 options, with the following data:
| Charge-Off Reason Name | Description | Position | Is Active | Is Mandatory |
| debit_card | | 0 | true | false |
| credit_card | | 1 | true | false |
| Fraud | | 2 | true | false |
| Delinquent | | 3 | true | false |
| Other | | 4 | true | false |
| Fraud | | 0 | true | false |
| Delinquent | | 1 | true | false |
| Other | | 2 | true | false |
@TestRailId:C3587
Scenario: As a user I would like to verify interestRecognitionOnDisbursementDate=false flag in loan product response