FINERACT-2326: add installment amount in multiples of handling to flat interest emi calculation

This commit is contained in:
mark.vituska
2025-07-30 13:17:05 +02:00
committed by Adam Saghy
parent 00d613175c
commit 0728ffc2ad
3 changed files with 8 additions and 13 deletions
@@ -3168,6 +3168,7 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
.daysInMonthType(DaysInMonthType.DAYS30.value)// .daysInMonthType(DaysInMonthType.DAYS30.value)//
.enableDownPayment(false)// .enableDownPayment(false)//
.enableAutoRepaymentForDownPayment(null)// .enableAutoRepaymentForDownPayment(null)//
.installmentAmountInMultiplesOf(null)//
.disbursedAmountPercentageForDownPayment(null)// .disbursedAmountPercentageForDownPayment(null)//
.multiDisburseLoan(true)// .multiDisburseLoan(true)//
.disallowExpectedDisbursements(true)// .disallowExpectedDisbursements(true)//
@@ -3197,6 +3198,7 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
.recalculationRestFrequencyType(RecalculationRestFrequencyType.SAME_AS_REPAYMENT.value)// .recalculationRestFrequencyType(RecalculationRestFrequencyType.SAME_AS_REPAYMENT.value)//
.enableDownPayment(false)// .enableDownPayment(false)//
.enableAutoRepaymentForDownPayment(null)// .enableAutoRepaymentForDownPayment(null)//
.installmentAmountInMultiplesOf(null)//
.disbursedAmountPercentageForDownPayment(null)// .disbursedAmountPercentageForDownPayment(null)//
.multiDisburseLoan(true)// .multiDisburseLoan(true)//
.disallowExpectedDisbursements(true)// .disallowExpectedDisbursements(true)//
@@ -3230,6 +3232,7 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
.recalculationRestFrequencyType(RecalculationRestFrequencyType.SAME_AS_REPAYMENT.value)// .recalculationRestFrequencyType(RecalculationRestFrequencyType.SAME_AS_REPAYMENT.value)//
.enableDownPayment(false)// .enableDownPayment(false)//
.enableAutoRepaymentForDownPayment(null)// .enableAutoRepaymentForDownPayment(null)//
.installmentAmountInMultiplesOf(null)//
.disbursedAmountPercentageForDownPayment(null)// .disbursedAmountPercentageForDownPayment(null)//
.multiDisburseLoan(true)// .multiDisburseLoan(true)//
.disallowExpectedDisbursements(true)// .disallowExpectedDisbursements(true)//
@@ -3259,6 +3262,7 @@ public class LoanProductGlobalInitializerStep implements FineractGlobalInitializ
.loanScheduleProcessingType("HORIZONTAL")// .loanScheduleProcessingType("HORIZONTAL")//
.enableDownPayment(false)// .enableDownPayment(false)//
.enableAutoRepaymentForDownPayment(null)// .enableAutoRepaymentForDownPayment(null)//
.installmentAmountInMultiplesOf(null)//
.disbursedAmountPercentageForDownPayment(null)// .disbursedAmountPercentageForDownPayment(null)//
.multiDisburseLoan(true)// .multiDisburseLoan(true)//
.disallowExpectedDisbursements(true)// .disallowExpectedDisbursements(true)//
@@ -3204,8 +3204,6 @@ Feature: LoanRepayment
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 1000.0 | 0 | 0 | 0 | 1000.0 | 0.0 | 0 | 0 | 1000 | | 1000.0 | 0 | 0 | 0 | 1000.0 | 0.0 | 0 | 0 | 1000 |
# TODO fix progressive interest mode FLAT does not respect in multiples of
@Skip
@TestRailId:C3129 @AdvancedPaymentAllocation @TestRailId:C3129 @AdvancedPaymentAllocation
Scenario: Verify installment due date logic for monthly installments - last day of the month Scenario: Verify installment due date logic for monthly installments - last day of the month
When Admin sets the business date to "31 January 2024" When Admin sets the business date to "31 January 2024"
@@ -3249,8 +3247,6 @@ Feature: LoanRepayment
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 250.0 | 0.0 | 0.0 | 750.0 | | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 250.0 | 0.0 | 0.0 | 750.0 |
# TODO fix progressive interest mode FLAT does not respect in multiples of
@Skip
@TestRailId:C3130 @AdvancedPaymentAllocation @TestRailId:C3130 @AdvancedPaymentAllocation
Scenario: Verify installment due date logic for monthly installments - last day of the month, expected and real disbursement dates are different Scenario: Verify installment due date logic for monthly installments - last day of the month, expected and real disbursement dates are different
When Admin sets the business date to "30 January 2024" When Admin sets the business date to "30 January 2024"
@@ -3295,8 +3291,6 @@ Feature: LoanRepayment
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 250.0 | 0.0 | 0.0 | 750.0 | | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 250.0 | 0.0 | 0.0 | 750.0 |
# TODO fix progressive interest mode FLAT does not respect in multiples of
@Skip
@TestRailId:C3131 @AdvancedPaymentAllocation @TestRailId:C3131 @AdvancedPaymentAllocation
Scenario: Verify installment due date logic for monthly installments - last day of the month, repayment start calculated from Submitted on date - submit, approve, disburse on same date Scenario: Verify installment due date logic for monthly installments - last day of the month, repayment start calculated from Submitted on date - submit, approve, disburse on same date
When Admin sets the business date to "31 January 2024" When Admin sets the business date to "31 January 2024"
@@ -3340,8 +3334,6 @@ Feature: LoanRepayment
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 250.0 | 0.0 | 0.0 | 750.0 | | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 250.0 | 0.0 | 0.0 | 750.0 |
# TODO fix progressive interest mode FLAT does not respect in multiples of
@Skip
@TestRailId:C3132 @AdvancedPaymentAllocation @TestRailId:C3132 @AdvancedPaymentAllocation
Scenario: Verify installment due date logic for monthly installments - last day of the month, repayment start calculated from Submitted on date - submit and approve on same date, disburse on next day Scenario: Verify installment due date logic for monthly installments - last day of the month, repayment start calculated from Submitted on date - submit and approve on same date, disburse on next day
When Admin sets the business date to "31 January 2024" When Admin sets the business date to "31 January 2024"
@@ -3386,8 +3378,6 @@ Feature: LoanRepayment
| Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding | | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
| 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 250.0 | 0.0 | 0.0 | 750.0 | | 1000.0 | 0.0 | 0.0 | 0.0 | 1000.0 | 250.0 | 0.0 | 0.0 | 750.0 |
# TODO fix progressive interest mode FLAT does not respect in multiples of
@Skip
@TestRailId:C3133 @AdvancedPaymentAllocation @TestRailId:C3133 @AdvancedPaymentAllocation
Scenario: Verify installment due date logic for monthly installments - last day of the month, repayment start calculated from Submitted on date - submit and approve on same date, expected disbursement date on next day Scenario: Verify installment due date logic for monthly installments - last day of the month, repayment start calculated from Submitted on date - submit and approve on same date, expected disbursement date on next day
When Admin sets the business date to "31 January 2024" When Admin sets the business date to "31 January 2024"
@@ -926,10 +926,11 @@ public final class ProgressiveEMICalculator implements EMICalculator {
.plus(sumOfInterest).minus(alreadyRepaidPrincipals); .plus(sumOfInterest).minus(alreadyRepaidPrincipals);
Money periodEmi = total.dividedBy(repaymentPeriods.size(), mc); Money periodEmi = total.dividedBy(repaymentPeriods.size(), mc);
Money remainder = total.minus(periodEmi.multipliedBy(repaymentPeriods.size(), mc)); Money periodEmiInMultiplesOf = applyInstallmentAmountInMultiplesOf(scheduleModel, periodEmi);
Money remainder = total.minus(periodEmiInMultiplesOf.multipliedBy(repaymentPeriods.size(), mc));
repaymentPeriods.forEach(rp -> { repaymentPeriods.forEach(rp -> {
Money emi = rp.equals(last) ? periodEmi.add(remainder) : periodEmi; Money emi = rp.equals(last) ? periodEmiInMultiplesOf.add(remainder) : periodEmiInMultiplesOf;
rp.setEmi(emi); rp.setEmi(emi);
rp.setOriginalEmi(emi); rp.setOriginalEmi(emi);
rp.getInterestPeriods().forEach(InterestPeriod::updateOutstandingLoanBalance); rp.getInterestPeriods().forEach(InterestPeriod::updateOutstandingLoanBalance);