FINERACT-2232: Capitalized income - Add Capitalized income to Loan

This commit is contained in:
Adam Saghy
2025-04-30 10:23:55 +02:00
parent e10542838e
commit 752dd4a10e
31 changed files with 902 additions and 234 deletions
@@ -33,7 +33,8 @@ public enum TransactionType {
CHARGE_OFF("chargeOff"), //
CHARGE_ADJUSTMENT("chargeAdjustment"), //
INTEREST_PAYMENT_WAIVER("interestPaymentWaiver"), //
REPAYMENT_AT_DISBURSEMENT("repaymentAtDisbursement"); //
REPAYMENT_AT_DISBURSEMENT("repaymentAtDisbursement"), //
CAPITALIZED_INCOME("capitalizedIncome"),;
public final String value;
@@ -21,19 +21,31 @@ package org.apache.fineract.test.data.accounttype;
public enum DefaultAccountType implements AccountType {
// Asset
LOANS_RECEIVABLE("Loans Receivable"), INTEREST_FEE_RECEIVABLE("Interest/Fee Receivable"), OTHER_RECEIVABLES(
"Other Receivables"), UNC_RECEIVABLE("UNC Receivable"), FUND_RECEIVABLES(
"Fund Receivables"), TRANSFER_IN_SUSPENSE_ACCOUNT("Transfer in suspense account"), ASSET_TRANSFER("Asset transfer"),
LOANS_RECEIVABLE("Loans Receivable"), //
INTEREST_FEE_RECEIVABLE("Interest/Fee Receivable"), //
OTHER_RECEIVABLES("Other Receivables"), //
UNC_RECEIVABLE("UNC Receivable"), //
FUND_RECEIVABLES("Fund Receivables"), //
TRANSFER_IN_SUSPENSE_ACCOUNT("Transfer in suspense account"), //
ASSET_TRANSFER("Asset transfer"), //
// Income
DEFERRED_INTEREST_REVENUE("Deferred Interest Revenue"), RETAINED_EARNINGS_PRIOR_YEAR("Retained Earnings Prior Year"), INTEREST_INCOME(
"Interest Income"), FEE_INCOME("Fee Income"), FEE_CHARGE_OFF(
"Fee Charge Off"), RECOVERIES("Recoveries"), INTEREST_INCOME_CHARGE_OFF("Interest Income Charge Off"),
DEFERRED_INTEREST_REVENUE("Deferred Interest Revenue"), //
RETAINED_EARNINGS_PRIOR_YEAR("Retained Earnings Prior Year"), //
INTEREST_INCOME("Interest Income"), //
FEE_INCOME("Fee Income"), //
FEE_CHARGE_OFF("Fee Charge Off"), //
RECOVERIES("Recoveries"), //
INTEREST_INCOME_CHARGE_OFF("Interest Income Charge Off"), //
// Liability
AA_SUSPENSE_BALANCE("AA Suspense Balance"), SUSPENSE_CLEARING_ACCOUNT("Suspense/Clearing account"), OVERPAYMENT_ACCOUNT(
"Overpayment account"),
AA_SUSPENSE_BALANCE("AA Suspense Balance"), //
SUSPENSE_CLEARING_ACCOUNT("Suspense/Clearing account"), //
OVERPAYMENT_ACCOUNT("Overpayment account"), //
DEFERRED_CAPITALIZED_INCOME("Deferred Capitalized Income"), //
// Expense
CREDIT_LOSS_BAD_DEBT("Credit Loss/Bad Debt"), CREDIT_LOSS_BAD_DEBT_FRAUD("Credit Loss/Bad Debt-Fraud"), GOODWILL_EXPENSE_ACCOUNT(
"Goodwill Expense Account"), WRITTEN_OFF("Written off");
CREDIT_LOSS_BAD_DEBT("Credit Loss/Bad Debt"), //
CREDIT_LOSS_BAD_DEBT_FRAUD("Credit Loss/Bad Debt-Fraud"), //
GOODWILL_EXPENSE_ACCOUNT("Goodwill Expense Account"), //
WRITTEN_OFF("Written off"); //
private final String customName;
@@ -1613,7 +1613,7 @@ public class LoanProductsRequestFactory {
.capitalizedIncomeStrategy(PostLoanProductsRequest.CapitalizedIncomeStrategyEnum.EQUAL_AMORTIZATION)//
.capitalizedIncomeCalculationType(PostLoanProductsRequest.CapitalizedIncomeCalculationTypeEnum.FLAT)//
.capitalizedIncomeType(PostLoanProductsRequest.CapitalizedIncomeTypeEnum.INTEREST)
.deferredIncomeLiabilityAccountId(accountTypeResolver.resolve(DefaultAccountType.OVERPAYMENT_ACCOUNT))
.deferredIncomeLiabilityAccountId(accountTypeResolver.resolve(DefaultAccountType.DEFERRED_CAPITALIZED_INCOME))
.incomeFromCapitalizationAccountId(accountTypeResolver.resolve(DefaultAccountType.INTEREST_INCOME))
.enableIncomeCapitalization(true);//
}
@@ -59,6 +59,7 @@ public class GLGlobalInitializerStep implements FineractGlobalInitializerStep {
public static final String GLA_NAME_19 = "Goodwill Expense Account";
public static final String GLA_NAME_20 = "Interest Income Charge Off";
public static final String GLA_NAME_21 = "Asset transfer";
public static final String GLA_NAME_22 = "Deferred Capitalized Income";
public static final String GLA_GL_CODE_1 = "112601";
public static final String GLA_GL_CODE_2 = "112603";
public static final String GLA_GL_CODE_3 = "145800";
@@ -80,6 +81,7 @@ public class GLGlobalInitializerStep implements FineractGlobalInitializerStep {
public static final String GLA_GL_CODE_19 = "744003";
public static final String GLA_GL_CODE_20 = "404001";
public static final String GLA_GL_CODE_21 = "146000";
public static final String GLA_GL_CODE_22 = "145024";
private final GeneralLedgerAccountApi glaApi;
@@ -149,5 +151,8 @@ public class GLGlobalInitializerStep implements FineractGlobalInitializerStep {
PostGLAccountsRequest postGLAccountsRequest21 = GLAccountRequestFactory.defaultGLAccountRequest(GLA_NAME_21, GLA_GL_CODE_21,
GLA_TYPE_ASSET, GLA_USAGE_DETAIL, true);
glaApi.createGLAccount1(postGLAccountsRequest21).execute();
PostGLAccountsRequest postGLAccountsRequest22 = GLAccountRequestFactory.defaultGLAccountRequest(GLA_NAME_22, GLA_GL_CODE_22,
GLA_TYPE_LIABILITY, GLA_USAGE_DETAIL, true);
glaApi.createGLAccount1(postGLAccountsRequest22).execute();
}
}
@@ -1024,34 +1024,6 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_INTEREST_RECALCULATION,
responseLoanProductsRequestLP2AdvancedpaymentInterestEmiActualActualInterestRefundInterestRecalculation);
// LP2 with progressive loan schedule + horizontal + interest EMI + actual/actual + interest refund with
// Merchant issued and Payment refund + interest recalculation + Multidisbursement
// (LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_INTEREST_RECALCULATION_MULTIDISB)
String name97 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_INTEREST_RECALCULATION_MULTIDISB
.getName();
PostLoanProductsRequest loanProductsRequestLP2AdvancedpaymentInterestEmiActualActualInterestRefundRecalculationMultiDisb = loanProductsRequestFactory
.defaultLoanProductsRequestLP2Emi()//
.isInterestRecalculationEnabled(true)//
.preClosureInterestCalculationStrategy(1)//
.rescheduleStrategyMethod(4)//
.interestRecalculationCompoundingMethod(0)//
.recalculationRestFrequencyType(2)//
.recalculationRestFrequencyInterval(1)//
.name(name97)//
.multiDisburseLoan(true)//
.disallowExpectedDisbursements(true)//
.maxTrancheCount(10)//
.outstandingLoanBalance(10000.0)//
.supportedInterestRefundTypes(Arrays.asList("MERCHANT_ISSUED_REFUND", "PAYOUT_REFUND"))//
.paymentAllocation(List.of(//
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT")));//
Response<PostLoanProductsResponse> responseLoanProductsRequestLP2AdvancedpaymentInterestEmiActualActualInterestRefundInterestRecalculationMultidisb = loanProductsApi
.createLoanProduct(loanProductsRequestLP2AdvancedpaymentInterestEmiActualActualInterestRefundRecalculationMultiDisb)
.execute();
TestContext.INSTANCE.set(
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_INTEREST_RECALCULATION_MULTIDISB,
responseLoanProductsRequestLP2AdvancedpaymentInterestEmiActualActualInterestRefundInterestRecalculationMultidisb);
// LP2 with progressive loan schedule + horizontal + interest EMI + 360/30 + multidisbursement + downpayment +
// interest recalculation
// 25%, auto disabled
@@ -2421,6 +2393,34 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
.createLoanProduct(loanProductsRequestLP2ProgressiveAdvPaymentCapitalizedIncome).execute();
TestContext.INSTANCE.set(TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_PROGRESSIVE_ADV_PYMNT_CAPITALIZED_INCOME,
responseLoanProductsRequestLP2ProgressiveAdvPaymentCapitalizedIncome);
// LP2 with progressive loan schedule + horizontal + interest EMI + actual/actual + interest refund with
// Merchant issued and Payment refund + interest recalculation + Multidisbursement
// (LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_INTEREST_RECALCULATION_MULTIDISB)
String name98 = DefaultLoanProduct.LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_INTEREST_RECALCULATION_MULTIDISB
.getName();
PostLoanProductsRequest loanProductsRequestLP2AdvancedpaymentInterestEmiActualActualInterestRefundRecalculationMultiDisb = loanProductsRequestFactory
.defaultLoanProductsRequestLP2Emi()//
.isInterestRecalculationEnabled(true)//
.preClosureInterestCalculationStrategy(1)//
.rescheduleStrategyMethod(4)//
.interestRecalculationCompoundingMethod(0)//
.recalculationRestFrequencyType(2)//
.recalculationRestFrequencyInterval(1)//
.name(name98)//
.multiDisburseLoan(true)//
.disallowExpectedDisbursements(true)//
.maxTrancheCount(10)//
.outstandingLoanBalance(10000.0)//
.supportedInterestRefundTypes(Arrays.asList("MERCHANT_ISSUED_REFUND", "PAYOUT_REFUND"))//
.paymentAllocation(List.of(//
createPaymentAllocation("DEFAULT", "NEXT_INSTALLMENT")));//
Response<PostLoanProductsResponse> responseLoanProductsRequestLP2AdvancedpaymentInterestEmiActualActualInterestRefundInterestRecalculationMultidisb = loanProductsApi
.createLoanProduct(loanProductsRequestLP2AdvancedpaymentInterestEmiActualActualInterestRefundRecalculationMultiDisb)
.execute();
TestContext.INSTANCE.set(
TestContextKey.DEFAULT_LOAN_PRODUCT_CREATE_RESPONSE_LP2_ADV_PYMNT_INTEREST_DAILY_EMI_ACTUAL_ACTUAL_INTEREST_REFUND_INTEREST_RECALCULATION_MULTIDISB,
responseLoanProductsRequestLP2AdvancedpaymentInterestEmiActualActualInterestRefundInterestRecalculationMultidisb);
}
public static AdvancedPaymentData createPaymentAllocation(String transactionType, String futureInstallmentAllocationRule,