FINERACT-1981: fix progressive accruals on late repayment
This commit is contained in:
+32
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.loanaccount.data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class AccrualBalances {
|
||||
|
||||
private BigDecimal interestPortion = BigDecimal.ZERO;
|
||||
private BigDecimal feePortion = BigDecimal.ZERO;
|
||||
private BigDecimal penaltyPortion = BigDecimal.ZERO;
|
||||
}
|
||||
+47
-7
@@ -56,6 +56,7 @@ import org.apache.fineract.infrastructure.event.business.service.BusinessEventNo
|
||||
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.AccrualBalances;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.AccrualChargeData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.AccrualPeriodData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.AccrualPeriodsData;
|
||||
@@ -698,13 +699,52 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing
|
||||
LoanRepaymentScheduleInstallment lastInstallment = loan.getLastLoanRepaymentScheduleInstallment();
|
||||
LocalDate lastDueDate = lastInstallment.getDueDate();
|
||||
if (isProgressiveAccrual(loan)) {
|
||||
AccrualPeriodsData accrualPeriods = calculateAccrualAmounts(loan, lastDueDate, true);
|
||||
for (AccrualPeriodData period : accrualPeriods.getPeriods()) {
|
||||
Money interestAccrued = period.getTransactionAccrued();
|
||||
Money feeAccrued = period.getFeeTransactionAccrued();
|
||||
Money penaltyAccrued = period.getPenaltyTransactionAccrued();
|
||||
LoanRepaymentScheduleInstallment installment = loan.fetchRepaymentScheduleInstallment(period.getInstallmentNumber());
|
||||
installment.updateAccrualPortion(interestAccrued, feeAccrued, penaltyAccrued);
|
||||
AccrualBalances accrualBalances = new AccrualBalances();
|
||||
accrualTransactions.forEach(lt -> {
|
||||
switch (lt.getTypeOf()) {
|
||||
case ACCRUAL -> {
|
||||
accrualBalances.setFeePortion(MathUtil.add(accrualBalances.getFeePortion(), lt.getFeeChargesPortion()));
|
||||
accrualBalances.setPenaltyPortion(MathUtil.add(accrualBalances.getPenaltyPortion(), lt.getPenaltyChargesPortion()));
|
||||
accrualBalances.setInterestPortion(MathUtil.add(accrualBalances.getInterestPortion(), lt.getInterestPortion()));
|
||||
}
|
||||
case ACCRUAL_ADJUSTMENT -> {
|
||||
accrualBalances.setFeePortion(MathUtil.subtract(accrualBalances.getFeePortion(), lt.getFeeChargesPortion()));
|
||||
accrualBalances
|
||||
.setPenaltyPortion(MathUtil.subtract(accrualBalances.getPenaltyPortion(), lt.getPenaltyChargesPortion()));
|
||||
accrualBalances
|
||||
.setInterestPortion(MathUtil.subtract(accrualBalances.getInterestPortion(), lt.getInterestPortion()));
|
||||
}
|
||||
default -> throw new IllegalStateException("Unexpected value: " + lt.getTypeOf());
|
||||
}
|
||||
});
|
||||
for (LoanRepaymentScheduleInstallment installment : loan.getRepaymentScheduleInstallments()) {
|
||||
BigDecimal maximumAccruableInterest = MathUtil.nullToZero(installment.getInterestCharged());
|
||||
BigDecimal maximumAccruableFee = MathUtil.nullToZero(installment.getFeeChargesCharged());
|
||||
BigDecimal maximumAccruablePenalty = MathUtil.nullToZero(installment.getPenaltyCharges());
|
||||
|
||||
if (MathUtil.isLessThanOrEqualTo(maximumAccruableInterest, accrualBalances.getInterestPortion())) {
|
||||
installment.setInterestAccrued(maximumAccruableInterest);
|
||||
accrualBalances.setInterestPortion(accrualBalances.getInterestPortion().subtract(maximumAccruableInterest));
|
||||
} else {
|
||||
installment.setInterestAccrued(accrualBalances.getInterestPortion());
|
||||
accrualBalances.setInterestPortion(BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
if (MathUtil.isLessThanOrEqualTo(maximumAccruableFee, accrualBalances.getFeePortion())) {
|
||||
installment.setFeeAccrued(maximumAccruableFee);
|
||||
accrualBalances.setFeePortion(accrualBalances.getFeePortion().subtract(maximumAccruableFee));
|
||||
} else {
|
||||
installment.setFeeAccrued(accrualBalances.getFeePortion());
|
||||
accrualBalances.setFeePortion(BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
if (MathUtil.isLessThanOrEqualTo(maximumAccruablePenalty, accrualBalances.getPenaltyPortion())) {
|
||||
installment.setPenaltyAccrued(maximumAccruablePenalty);
|
||||
accrualBalances.setPenaltyPortion(accrualBalances.getPenaltyPortion().subtract(maximumAccruablePenalty));
|
||||
} else {
|
||||
installment.setPenaltyAccrued(accrualBalances.getPenaltyPortion());
|
||||
accrualBalances.setPenaltyPortion(BigDecimal.ZERO);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
List<LoanRepaymentScheduleInstallment> installments = loan.getRepaymentScheduleInstallments();
|
||||
|
||||
Reference in New Issue
Block a user