FINERACT-1724: Periodic accrual fix for charge on disbursement date

This commit is contained in:
Adam Saghy
2023-05-10 07:51:39 +02:00
committed by Arnold Gálovics
parent 70c93484f4
commit 0458643d8f
2 changed files with 77 additions and 2 deletions
@@ -1323,12 +1323,17 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
private void applyPeriodicAccruals(final Collection<LoanTransaction> accruals) {
List<LoanRepaymentScheduleInstallment> installments = getRepaymentScheduleInstallments();
for (LoanRepaymentScheduleInstallment installment : installments) {
Money interest = Money.zero(getCurrency());
Money fee = Money.zero(getCurrency());
Money penality = Money.zero(getCurrency());
for (LoanTransaction loanTransaction : accruals) {
if (loanTransaction.getTransactionDate().isAfter(installment.getFromDate())
&& !loanTransaction.getTransactionDate().isAfter(installment.getDueDate())) {
boolean isInRange = installment.isFirstPeriod()
? !loanTransaction.getTransactionDate().isBefore(installment.getFromDate())
&& !loanTransaction.getTransactionDate().isAfter(installment.getDueDate())
: loanTransaction.getTransactionDate().isAfter(installment.getFromDate())
&& !loanTransaction.getTransactionDate().isAfter(installment.getDueDate());
if (isInRange) {
interest = interest.plus(loanTransaction.getInterestPortion(getCurrency()));
fee = fee.plus(loanTransaction.getFeeChargesPortion(getCurrency()));
penality = penality.plus(loanTransaction.getPenaltyChargesPortion(getCurrency()));
@@ -545,6 +545,8 @@ public class LoanChargeSpecificDueDateTest {
responseSpec);
assertNotNull(postLoansLoanIdChargesResponse);
periodicAccrualAccountingHelper.runPeriodicAccrualAccounting(operationDate);
// Get loan details expecting to have a delinquency classification
getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
validateLoanAccount(getLoansLoanIdResponse, Double.valueOf(principalAmount), Double.valueOf("10.00"), true);
@@ -565,6 +567,74 @@ public class LoanChargeSpecificDueDateTest {
validateLoanAccount(getLoansLoanIdResponse, Double.parseDouble(principalAmount) * 2, Double.valueOf("20.00"), true);
}
@Test
public void testApplyLoanSpecificDueDatePenaltyAccrualWithDisbursementDateWithMultipleDisbursement() {
final LocalDate todaysDate = Utils.getLocalDateOfTenant();
// Client and Loan account creation
final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2012");
final GetLoanProductsProductIdResponse getLoanProductsProductResponse = createLoanProductWithPeriodicAccrual(loanTransactionHelper,
null);
assertNotNull(getLoanProductsProductResponse);
// Older date to have more than one overdue installment
LocalDate transactionDate = todaysDate.minusDays(2);
String operationDate = Utils.dateFormatter.format(transactionDate);
log.info("Operation date {}", transactionDate);
// Create Loan Account
final Integer loanId = createLoanAccount(loanTransactionHelper, clientId.toString(),
getLoanProductsProductResponse.getId().toString(), operationDate, "12", "0");
// Get loan details
GetLoansLoanIdResponse getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
validateLoanAccount(getLoansLoanIdResponse, Double.valueOf(principalAmount), Double.valueOf("0.00"), true);
// Apply Loan Charge with specific due date
final String feeAmount = "10.00";
String payloadJSON = ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, feeAmount, true);
final PostChargesResponse postChargesResponse = ChargesHelper.createLoanCharge(requestSpec, responseSpec, payloadJSON);
assertNotNull(postChargesResponse);
final Long loanChargeId = postChargesResponse.getResourceId();
assertNotNull(loanChargeId);
payloadJSON = LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(loanChargeId.toString(), operationDate, feeAmount);
PostLoansLoanIdChargesResponse postLoansLoanIdChargesResponse = loanTransactionHelper.addChargeForLoan(loanId, payloadJSON,
responseSpec);
assertNotNull(postLoansLoanIdChargesResponse);
periodicAccrualAccountingHelper.runPeriodicAccrualAccounting(operationDate);
// Get loan details expecting to have a delinquency classification
getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
validateLoanAccount(getLoansLoanIdResponse, Double.valueOf(principalAmount), Double.valueOf("10.00"), true);
transactionDate = transactionDate.plusDays(1);
operationDate = Utils.dateFormatter.format(transactionDate);
loanTransactionHelper.disburseLoan((long) loanId, new PostLoansLoanIdRequest().actualDisbursementDate(operationDate)
.transactionAmount(new BigDecimal("1000")).locale("en").dateFormat("dd MMMM yyyy"));
// Get loan details expecting to have a delinquency classification
getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
validateLoanAccount(getLoansLoanIdResponse, Double.parseDouble(principalAmount) * 2, Double.valueOf("10.00"), true);
periodicAccrualAccountingHelper.runPeriodicAccrualAccounting(operationDate);
operationDate = Utils.dateFormatter.format(transactionDate.plusMonths(1));
payloadJSON = LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(loanChargeId.toString(), operationDate, feeAmount);
postLoansLoanIdChargesResponse = loanTransactionHelper.addChargeForLoan(loanId, payloadJSON, responseSpec);
transactionDate = transactionDate.plusDays(1);
operationDate = Utils.dateFormatter.format(transactionDate);
periodicAccrualAccountingHelper.runPeriodicAccrualAccounting(operationDate);
// Get loan details expecting to have a delinquency classification
getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
validateLoanAccount(getLoansLoanIdResponse, Double.parseDouble(principalAmount) * 2, Double.valueOf("20.00"), true);
}
private GetLoanProductsProductIdResponse createLoanProduct(final LoanTransactionHelper loanTransactionHelper,
final Integer delinquencyBucketId) {
final HashMap<String, Object> loanProductMap = new LoanProductTestBuilder().build(null, delinquencyBucketId);