FINERACT-2421: Disbursement charge amount incorrect calculation
This commit is contained in:
committed by
Adam Saghy
parent
2620c61afa
commit
1d1876edfd
+1
-1
@@ -216,7 +216,7 @@ public class DelinquencyReadPlatformServiceImpl implements DelinquencyReadPlatfo
|
||||
// Calculate available amount: (approved + over applied) - expected tranches - disbursed - capitalized income
|
||||
if (loan.isMultiDisburmentLoan() && loan.getDisbursementDetails() != null) {
|
||||
final BigDecimal expectedDisbursementAmount = loan.getDisbursementDetails().stream()
|
||||
.filter(detail -> detail.actualDisbursementDate() == null).map(LoanDisbursementDetails::principal)
|
||||
.filter(detail -> detail.actualDisbursementDate() == null).map(LoanDisbursementDetails::getPrincipal)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
approvedWithOverApplied = approvedWithOverApplied.subtract(expectedDisbursementAmount);
|
||||
}
|
||||
|
||||
+5
@@ -22,6 +22,8 @@ import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
|
||||
|
||||
@@ -30,6 +32,7 @@ import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanSchedul
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
@Accessors(chain = true)
|
||||
public final class DisbursementData implements LoanPrincipalRelatedDataHolder, Comparable<DisbursementData> {
|
||||
|
||||
private final Long id;
|
||||
@@ -41,6 +44,8 @@ public final class DisbursementData implements LoanPrincipalRelatedDataHolder, C
|
||||
private final String loanChargeId;
|
||||
private final BigDecimal chargeAmount;
|
||||
private final BigDecimal waivedChargeAmount;
|
||||
@Setter
|
||||
private BigDecimal disburseChargeAmount;
|
||||
|
||||
// import fields
|
||||
private transient Integer rowIndex;
|
||||
|
||||
+4
-4
@@ -814,7 +814,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
if (isMultiDisburmentLoan()) {
|
||||
for (LoanDisbursementDetails disbursementDetail : getDisbursementDetails()) {
|
||||
if (disbursementDetail.actualDisbursementDate() != null) {
|
||||
principal = principal.add(disbursementDetail.principal());
|
||||
principal = principal.add(disbursementDetail.getPrincipal());
|
||||
}
|
||||
}
|
||||
return principal;
|
||||
@@ -999,7 +999,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
if (!details.isEmpty()) {
|
||||
principal = BigDecimal.ZERO;
|
||||
for (LoanDisbursementDetails disbursementDetails : details) {
|
||||
principal = principal.add(disbursementDetails.principal());
|
||||
principal = principal.add(disbursementDetails.getPrincipal());
|
||||
}
|
||||
}
|
||||
return principal;
|
||||
@@ -1303,7 +1303,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
public LoanDisbursementDetails getDisbursementDetails(final LocalDate transactionDate, final BigDecimal transactionAmount) {
|
||||
for (LoanDisbursementDetails disbursementDetail : this.disbursementDetails) {
|
||||
if (!disbursementDetail.isReversed() && disbursementDetail.getDisbursementDate().equals(transactionDate)
|
||||
&& (disbursementDetail.principal().compareTo(transactionAmount) == 0)) {
|
||||
&& (disbursementDetail.getPrincipal().compareTo(transactionAmount) == 0)) {
|
||||
return disbursementDetail;
|
||||
}
|
||||
}
|
||||
@@ -1317,7 +1317,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
Collection<LoanDisbursementDetails> loanDisburseDetails = this.getDisbursementDetails();
|
||||
for (LoanDisbursementDetails details : loanDisburseDetails) {
|
||||
if (details.actualDisbursementDate() != null) {
|
||||
principalAmount = principalAmount.add(details.principal());
|
||||
principalAmount = principalAmount.add(details.getPrincipal());
|
||||
}
|
||||
}
|
||||
} else if (isApproved()) {
|
||||
|
||||
+2
-4
@@ -26,10 +26,12 @@ import jakarta.persistence.Table;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Objects;
|
||||
import lombok.Getter;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.DisbursementData;
|
||||
|
||||
@Getter
|
||||
@Entity
|
||||
@Table(name = "m_loan_disbursement_detail")
|
||||
public class LoanDisbursementDetails extends AbstractPersistableCustom<Long> {
|
||||
@@ -107,10 +109,6 @@ public class LoanDisbursementDetails extends AbstractPersistableCustom<Long> {
|
||||
return this.actualDisbursementDate;
|
||||
}
|
||||
|
||||
public BigDecimal principal() {
|
||||
return this.principal;
|
||||
}
|
||||
|
||||
public void updatePrincipal(BigDecimal principal) {
|
||||
this.principal = principal;
|
||||
}
|
||||
|
||||
+1
-1
@@ -108,7 +108,7 @@ public class LoanRepaymentScheduleProcessingWrapper {
|
||||
&& loanCharge.getLoan().isMultiDisburmentLoan()) {
|
||||
for (final LoanDisbursementDetails loanDisbursementDetails : loanCharge.getLoan().getDisbursementDetails()) {
|
||||
if (!DateUtils.isAfter(loanDisbursementDetails.expectedDisbursementDate(), loanCharge.getDueDate())) {
|
||||
amount = amount.add(loanDisbursementDetails.principal());
|
||||
amount = amount.add(loanDisbursementDetails.getPrincipal());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -132,7 +132,7 @@ public class SingleLoanChargeRepaymentScheduleProcessingWrapper {
|
||||
// Then we need to get as of this loan charge due date how much amount disbursed.
|
||||
for (final LoanDisbursementDetails loanDisbursementDetails : loan.getDisbursementDetails()) {
|
||||
if (!DateUtils.isAfter(loanDisbursementDetails.expectedDisbursementDate(), loanCharge.getDueDate())) {
|
||||
baseAmount = MathUtil.add(baseAmount, loanDisbursementDetails.principal());
|
||||
baseAmount = MathUtil.add(baseAmount, loanDisbursementDetails.getPrincipal());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@ public class LoanMapper {
|
||||
BigDecimal waivedChargeAmount = null;
|
||||
disbursementData.add(
|
||||
new DisbursementData(loanDisbursementDetails.getId(), loan.getId(), expectedDisbursementDate, actualDisbursementDate,
|
||||
loanDisbursementDetails.principal(), loan.getNetDisbursalAmount(), null, null, waivedChargeAmount));
|
||||
loanDisbursementDetails.getPrincipal(), loan.getNetDisbursalAmount(), null, null, waivedChargeAmount));
|
||||
}
|
||||
|
||||
return disbursementData;
|
||||
|
||||
+1
-1
@@ -88,7 +88,7 @@ public class LoanApprovedAmountWritePlatformServiceImpl implements LoanApprovedA
|
||||
changes.put("oldApprovedAmount", loan.getApprovedPrincipal());
|
||||
|
||||
BigDecimal expectedDisbursementAmount = loan.getDisbursementDetails().stream().filter(t -> t.actualDisbursementDate() == null)
|
||||
.map(LoanDisbursementDetails::principal).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
.map(LoanDisbursementDetails::getPrincipal).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
|
||||
BigDecimal oldAvailableDisbursement = loan.getApprovedPrincipal().subtract(loan.getSummary().getTotalPrincipal())
|
||||
.subtract(expectedDisbursementAmount);
|
||||
|
||||
+1
-1
@@ -187,7 +187,7 @@ public class LoanBalanceService {
|
||||
charge.resetToOriginal(loan.getCurrency());
|
||||
}
|
||||
}
|
||||
loan.getLoanRepaymentScheduleDetail().setPrincipal(loan.getDisbursedAmount().subtract(disbursementDetail.principal()));
|
||||
loan.getLoanRepaymentScheduleDetail().setPrincipal(loan.getDisbursedAmount().subtract(disbursementDetail.getPrincipal()));
|
||||
disbursementDetail.updateActualDisbursementDate(null);
|
||||
disbursementDetail.reverse();
|
||||
updateLoanSummaryDerivedFields(loan);
|
||||
|
||||
+24
-12
@@ -251,7 +251,9 @@ public class LoanChargeService {
|
||||
case PERCENT_OF_AMOUNT_AND_INTEREST -> {
|
||||
final BigDecimal totalInterestCharged = loan.getTotalInterest();
|
||||
if (loan.isMultiDisburmentLoan() && loanCharge.isDisbursementCharge()) {
|
||||
yield getTotalAllTrancheDisbursementAmount(loan).getAmount().add(totalInterestCharged);
|
||||
yield sumMultiDisbursementAmounts(loan, false).getAmount().add(totalInterestCharged);
|
||||
} else if (loan.isMultiDisburmentLoan() && loanCharge.isTrancheDisbursementCharge()) {
|
||||
yield sumMultiDisbursementAmounts(loan, true).getAmount().add(totalInterestCharged);
|
||||
} else {
|
||||
yield loan.getPrincipal().getAmount().add(totalInterestCharged);
|
||||
}
|
||||
@@ -259,7 +261,7 @@ public class LoanChargeService {
|
||||
case PERCENT_OF_INTEREST -> loan.getTotalInterest();
|
||||
case PERCENT_OF_DISBURSEMENT_AMOUNT -> {
|
||||
if (loanCharge.getTrancheDisbursementCharge() != null) {
|
||||
yield loanCharge.getTrancheDisbursementCharge().getloanDisbursementDetails().principal();
|
||||
yield loanCharge.getTrancheDisbursementCharge().getloanDisbursementDetails().getPrincipal();
|
||||
} else {
|
||||
yield loan.getPrincipal().getAmount();
|
||||
}
|
||||
@@ -449,7 +451,7 @@ public class LoanChargeService {
|
||||
if (loanCharge.getLoan().isMultiDisburmentLoan() && loanCharge.isSpecifiedDueDate()) {
|
||||
for (final LoanDisbursementDetails loanDisbursementDetails : loanCharge.getLoan().getDisbursementDetails()) {
|
||||
if (!DateUtils.isAfter(loanDisbursementDetails.expectedDisbursementDate(), loanCharge.getDueDate())) {
|
||||
amountPercentageAppliedTo = amountPercentageAppliedTo.add(loanDisbursementDetails.principal());
|
||||
amountPercentageAppliedTo = amountPercentageAppliedTo.add(loanDisbursementDetails.getPrincipal());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -465,7 +467,7 @@ public class LoanChargeService {
|
||||
break;
|
||||
case PERCENT_OF_DISBURSEMENT_AMOUNT:
|
||||
LoanTrancheDisbursementCharge loanTrancheDisbursementCharge = loanCharge.getLoanTrancheDisbursementCharge();
|
||||
amountPercentageAppliedTo = loanTrancheDisbursementCharge.getloanDisbursementDetails().principal();
|
||||
amountPercentageAppliedTo = loanTrancheDisbursementCharge.getloanDisbursementDetails().getPrincipal();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -850,14 +852,23 @@ public class LoanChargeService {
|
||||
}
|
||||
}
|
||||
|
||||
private Money getTotalAllTrancheDisbursementAmount(final Loan loan) {
|
||||
Money amount = Money.zero(loan.getCurrency());
|
||||
private Money sumMultiDisbursementAmounts(final Loan loan, final boolean isTrancheDisbursement) {
|
||||
if (loan.isMultiDisburmentLoan()) {
|
||||
for (final LoanDisbursementDetails loanDisbursementDetail : loan.getDisbursementDetails()) {
|
||||
amount = amount.plus(loanDisbursementDetail.principal());
|
||||
final List<LoanDisbursementDetails> loanDisbursementDetails = loan.getDisbursementDetails();
|
||||
if (loan.isOpen() || !loanDisbursementDetails.isEmpty()) {
|
||||
if (isTrancheDisbursement) {
|
||||
return Money.of(loan.getCurrency(), loanDisbursementDetails.stream() //
|
||||
.map(LoanDisbursementDetails::getPrincipal) //
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add));
|
||||
}
|
||||
return Money.of(loan.getCurrency(), loanDisbursementDetails.get(0).getPrincipal());
|
||||
} else if (loan.isSubmittedAndPendingApproval()) {
|
||||
return Money.of(loan.getCurrency(), loan.getProposedPrincipal());
|
||||
} else if (loan.isApproved()) {
|
||||
return Money.of(loan.getCurrency(), loan.getApprovedPrincipal());
|
||||
}
|
||||
}
|
||||
return amount;
|
||||
return Money.zero(loan.getCurrency());
|
||||
}
|
||||
|
||||
private List<Long> fetchAllLoanChargeIds(final Loan loan) {
|
||||
@@ -884,15 +895,16 @@ public class LoanChargeService {
|
||||
|
||||
private BigDecimal getDerivedAmountForCharge(final Loan loan, final LoanCharge loanCharge) {
|
||||
BigDecimal amount = BigDecimal.ZERO;
|
||||
if (loan.isMultiDisburmentLoan() && loanCharge.getCharge().getChargeTimeType().equals(ChargeTimeType.DISBURSEMENT.getValue())) {
|
||||
amount = loan.getApprovedPrincipal();
|
||||
final ChargeTimeType chargeTimeType = ChargeTimeType.fromInt(loanCharge.getCharge().getChargeTimeType());
|
||||
if (loan.isMultiDisburmentLoan() && chargeTimeType.isDisbursementOrTrancheDisbursementCharge()) {
|
||||
return sumMultiDisbursementAmounts(loan, chargeTimeType.isTrancheDisbursement()).getAmount();
|
||||
} else {
|
||||
// If charge type is specified due date and loan is multi disburment loan.
|
||||
// Then we need to get as of this loan charge due date how much amount disbursed.
|
||||
if (loanCharge.isSpecifiedDueDate() && loan.isMultiDisburmentLoan()) {
|
||||
for (final LoanDisbursementDetails loanDisbursementDetails : loan.getDisbursementDetails()) {
|
||||
if (!DateUtils.isAfter(loanDisbursementDetails.expectedDisbursementDate(), loanCharge.getDueDate())) {
|
||||
amount = amount.add(loanDisbursementDetails.principal());
|
||||
amount = amount.add(loanDisbursementDetails.getPrincipal());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user