FINERACT-1971 Repayment schedule period - Incorrect values after charge with huge amount
This commit is contained in:
committed by
Adam Saghy
parent
d9414a6e7e
commit
22f7972f60
+5
-1
@@ -269,9 +269,13 @@ public final class MathUtil {
|
|||||||
|
|
||||||
/** @return sum the values considering null values */
|
/** @return sum the values considering null values */
|
||||||
public static BigDecimal add(BigDecimal... amounts) {
|
public static BigDecimal add(BigDecimal... amounts) {
|
||||||
|
return add(MoneyHelper.getMathContext(), amounts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BigDecimal add(MathContext mc, BigDecimal... amounts) {
|
||||||
BigDecimal result = null;
|
BigDecimal result = null;
|
||||||
for (BigDecimal amount : amounts) {
|
for (BigDecimal amount : amounts) {
|
||||||
result = add(result, amount, MoneyHelper.getMathContext());
|
result = add(result, amount, mc);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -33,7 +33,7 @@ public class MoneyHelper {
|
|||||||
|
|
||||||
private static RoundingMode roundingMode = null;
|
private static RoundingMode roundingMode = null;
|
||||||
private static MathContext mathContext;
|
private static MathContext mathContext;
|
||||||
private static final int PRECISION = 12;
|
public static final int PRECISION = 19;
|
||||||
|
|
||||||
private static ConfigurationDomainService staticConfigurationDomainService;
|
private static ConfigurationDomainService staticConfigurationDomainService;
|
||||||
|
|
||||||
|
|||||||
+8
-4
@@ -19,11 +19,13 @@
|
|||||||
package org.apache.fineract.portfolio.loanaccount.loanschedule.data;
|
package org.apache.fineract.portfolio.loanaccount.loanschedule.data;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.math.MathContext;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||||
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||||
|
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Immutable data object that represents a period of a loan schedule.
|
* Immutable data object that represents a period of a loan schedule.
|
||||||
@@ -156,11 +158,13 @@ public final class LoanSchedulePeriodData {
|
|||||||
final BigDecimal totalPaidLateForPeriod, final BigDecimal totalWaived, final BigDecimal totalWrittenOff,
|
final BigDecimal totalPaidLateForPeriod, final BigDecimal totalWaived, final BigDecimal totalWrittenOff,
|
||||||
final BigDecimal totalCredits, final boolean isDownPayment, final BigDecimal totalAccruedInterest) {
|
final BigDecimal totalCredits, final boolean isDownPayment, final BigDecimal totalAccruedInterest) {
|
||||||
|
|
||||||
BigDecimal totalDue = MathUtil.add(principalOriginalDue, interestDue, feeChargesDue, penaltyChargesDue);
|
final MathContext mc = MoneyHelper.getMathContext();
|
||||||
BigDecimal totalOutstanding = MathUtil.add(principalOutstanding, interestOutstanding, feeChargesOutstanding,
|
|
||||||
|
BigDecimal totalDue = MathUtil.add(mc, principalOriginalDue, interestDue, feeChargesDue, penaltyChargesDue);
|
||||||
|
BigDecimal totalOutstanding = MathUtil.add(mc, principalOutstanding, interestOutstanding, feeChargesOutstanding,
|
||||||
penaltyChargesOutstanding);
|
penaltyChargesOutstanding);
|
||||||
BigDecimal totalActualCostOfLoanForPeriod = MathUtil.add(interestDue, feeChargesDue, penaltyChargesDue);
|
BigDecimal totalActualCostOfLoanForPeriod = MathUtil.add(mc, interestDue, feeChargesDue, penaltyChargesDue);
|
||||||
BigDecimal totalInstallmentAmount = MathUtil.add(principalOriginalDue, interestDue);
|
BigDecimal totalInstallmentAmount = MathUtil.add(mc, principalOriginalDue, interestDue);
|
||||||
|
|
||||||
return builder().period(periodNumber) //
|
return builder().period(periodNumber) //
|
||||||
.fromDate(fromDate) //
|
.fromDate(fromDate) //
|
||||||
|
|||||||
-3
@@ -1226,7 +1226,6 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
|||||||
Set<Long> disbursementPeriodIds = new HashSet<>();
|
Set<Long> disbursementPeriodIds = new HashSet<>();
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
|
|
||||||
final Long loanId = rs.getLong("loanId");
|
|
||||||
final Integer period = JdbcSupport.getInteger(rs, "period");
|
final Integer period = JdbcSupport.getInteger(rs, "period");
|
||||||
LocalDate fromDate = JdbcSupport.getLocalDate(rs, "fromDate");
|
LocalDate fromDate = JdbcSupport.getLocalDate(rs, "fromDate");
|
||||||
final LocalDate dueDate = JdbcSupport.getLocalDate(rs, "dueDate");
|
final LocalDate dueDate = JdbcSupport.getLocalDate(rs, "dueDate");
|
||||||
@@ -1307,8 +1306,6 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
|||||||
final BigDecimal totalOutstandingForPeriod = principalOutstanding.add(interestOutstanding).add(feeChargesOutstanding)
|
final BigDecimal totalOutstandingForPeriod = principalOutstanding.add(interestOutstanding).add(feeChargesOutstanding)
|
||||||
.add(penaltyChargesOutstanding);
|
.add(penaltyChargesOutstanding);
|
||||||
|
|
||||||
final BigDecimal totalActualCostOfLoanForPeriod = interestActualDue.add(feeChargesActualDue).add(penaltyChargesActualDue);
|
|
||||||
|
|
||||||
totalRepaymentExpected = totalRepaymentExpected.plus(totalDueForPeriod);
|
totalRepaymentExpected = totalRepaymentExpected.plus(totalDueForPeriod);
|
||||||
totalRepayment = totalRepayment.plus(totalPaidForPeriod);
|
totalRepayment = totalRepayment.plus(totalPaidForPeriod);
|
||||||
totalPaidInAdvance = totalPaidInAdvance.plus(totalPaidInAdvanceForPeriod);
|
totalPaidInAdvance = totalPaidInAdvance.plus(totalPaidInAdvanceForPeriod);
|
||||||
|
|||||||
+35
@@ -296,6 +296,41 @@ public class LoanRepaymentScheduleForChargesAfterMaturityTest extends BaseLoanIn
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void incorrectValueAfterCharge() {
|
||||||
|
runAt("20 December 2024", () -> {
|
||||||
|
// Create Client
|
||||||
|
Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
|
||||||
|
// Create Loan Product
|
||||||
|
PostLoanProductsRequest product = createOnePeriod30DaysLongNoInterestPeriodicAccrualProductWithAdvancedPaymentAllocation()
|
||||||
|
.minPrincipal(100.0);
|
||||||
|
PostLoanProductsResponse loanProductResponse = loanProductHelper.createLoanProduct(product);
|
||||||
|
Long loanProductId = loanProductResponse.getResourceId();
|
||||||
|
|
||||||
|
// Apply and Approve Loan
|
||||||
|
Long loanId = applyAndApproveLoan(clientId, loanProductId, "20 December 2024", 800.0, 4, req -> {
|
||||||
|
req.setRepaymentEvery(30);
|
||||||
|
req.setLoanTermFrequency(120);
|
||||||
|
req.setTransactionProcessingStrategyCode("advanced-payment-allocation-strategy");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Disburse Loan
|
||||||
|
disburseLoan(loanId, BigDecimal.valueOf(800.00), "20 December 2024");
|
||||||
|
|
||||||
|
// add charge with a huge amount
|
||||||
|
addCharge(loanId, false, 123456789012.12, "23 December 2024");
|
||||||
|
|
||||||
|
// verify repayment schedule
|
||||||
|
verifyRepaymentSchedule(loanId, //
|
||||||
|
installment(800.0, null, "20 December 2024"), //
|
||||||
|
installment(200.0, 0.0, 123456789212.12, false, "19 January 2025"), //
|
||||||
|
installment(200.0, 0.0, 200.0, false, "18 February 2025"), //
|
||||||
|
installment(200.0, 0.0, 200.0, false, "20 March 2025"), //
|
||||||
|
installment(200.0, 0.0, 200.0, false, "19 April 2025")//
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private Long createLoanProductWithMultiDisbursalAndRepayments() {
|
private Long createLoanProductWithMultiDisbursalAndRepayments() {
|
||||||
boolean multiDisburseEnabled = true;
|
boolean multiDisburseEnabled = true;
|
||||||
PostLoanProductsRequest product = createOnePeriod30DaysLongNoInterestPeriodicAccrualProduct();
|
PostLoanProductsRequest product = createOnePeriod30DaysLongNoInterestPeriodicAccrualProduct();
|
||||||
|
|||||||
+4
-4
@@ -96,12 +96,12 @@ public class MultiActivityAccrualsTest extends BaseLoanIntegrationTest {
|
|||||||
|
|
||||||
verifyTransactions(loanId, //
|
verifyTransactions(loanId, //
|
||||||
transaction(600.0, "Disbursement", "09 August 2024", 600.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
|
transaction(600.0, "Disbursement", "09 August 2024", 600.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0),
|
||||||
transaction(20.00, "Accrual", "09 December 2024", 0, 0, 20.00, 0, 0, 0.0, 0.0),
|
transaction(19.98, "Accrual", "09 December 2024", 0, 0, 19.98, 0, 0, 0.0, 0.0),
|
||||||
transaction(5.0, "Accrual Activity", "09 September 2024", 0, 0, 5.0, 0, 0, 0.0, 0.0),
|
transaction(4.99, "Accrual Activity", "09 September 2024", 0, 0, 4.99, 0, 0, 0.0, 0.0),
|
||||||
transaction(5.0, "Accrual Activity", "09 October 2024", 0, 0, 5.0, 0, 0, 0.0, 0.0),
|
transaction(5.0, "Accrual Activity", "09 October 2024", 0, 0, 5.0, 0, 0, 0.0, 0.0),
|
||||||
transaction(5.0, "Accrual Activity", "09 November 2024", 0, 0, 5.0, 0, 0, 0.0, 0.0),
|
transaction(4.99, "Accrual Activity", "09 November 2024", 0, 0, 4.99, 0, 0, 0.0, 0.0),
|
||||||
transaction(5.0, "Accrual Activity", "09 December 2024", 0, 0, 5.0, 0, 0, 0.0, 0.0),
|
transaction(5.0, "Accrual Activity", "09 December 2024", 0, 0, 5.0, 0, 0, 0.0, 0.0),
|
||||||
transaction(700.00, "Repayment", "09 December 2024", 0, 600.00, 20.0, 0, 0, 0.0, 80.0));
|
transaction(700.00, "Repayment", "09 December 2024", 0, 600.00, 19.98, 0, 0, 0.0, 80.02));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user