Skip to content

Commit 880a4c2

Browse files
committed
Refactor disbursement max calculation and use enum-based over-applied type handling
1 parent 870a781 commit 880a4c2

1 file changed

Lines changed: 24 additions & 37 deletions

File tree

fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanDisbursementValidator.java

Lines changed: 24 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.apache.fineract.infrastructure.core.service.DateUtils;
2525
import org.apache.fineract.infrastructure.core.service.MathUtil;
2626
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
27+
import org.apache.fineract.portfolio.loanaccount.domain.LoanOverAppliedCalculationType;
2728
import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
2829
import org.apache.fineract.portfolio.loanaccount.exception.InvalidLoanStateTransitionException;
2930
import org.apache.fineract.portfolio.loanaccount.exception.LoanDisbursalException;
@@ -40,26 +41,8 @@ public void compareDisbursedToApprovedOrProposedPrincipal(final Loan loan, final
4041
final BigDecimal totalCapitalizedIncomeAdjustment = MathUtil.nullToZero(loan.getSummary().getTotalCapitalizedIncomeAdjustment());
4142
final BigDecimal netCapitalizedIncome = totalCapitalizedIncome.subtract(totalCapitalizedIncomeAdjustment);
4243

43-
// Always use the same logic for over-applied config and fallback
44-
LoanProduct loanProduct = loan.getLoanProduct();
45-
BigDecimal approvedPrincipal = loan.getApprovedPrincipal();
46-
BigDecimal maxAllowed = approvedPrincipal;
47-
48-
if (loanProduct.getOverAppliedCalculationType() != null && loanProduct.getOverAppliedNumber() != null) {
49-
BigDecimal overAppliedNumber = BigDecimal.valueOf(loanProduct.getOverAppliedNumber());
50-
if ("percentage".equalsIgnoreCase(loanProduct.getOverAppliedCalculationType())) {
51-
BigDecimal extra = approvedPrincipal.multiply(overAppliedNumber).divide(BigDecimal.valueOf(100));
52-
maxAllowed = approvedPrincipal.add(extra);
53-
} else {
54-
// ABSOLUTE (flat)
55-
maxAllowed = approvedPrincipal.add(overAppliedNumber);
56-
}
57-
}
58-
44+
final BigDecimal maxAllowed = calculateMaxAllowedDisbursement(loan);
5945
BigDecimal total = totalDisbursed.add(netCapitalizedIncome);
60-
if (maxAllowed == null) {
61-
maxAllowed = approvedPrincipal;
62-
}
6346
if (total.compareTo(maxAllowed) > 0) {
6447
throw new LoanDisbursalException(
6548
"Disbursement exceeds allowed limit including over-applied threshold",
@@ -68,25 +51,8 @@ public void compareDisbursedToApprovedOrProposedPrincipal(final Loan loan, final
6851
}
6952

7053
public void validateOverMaximumAmount(final Loan loan, final BigDecimal totalDisbursed, final BigDecimal capitalizedIncome) {
71-
LoanProduct loanProduct = loan.getLoanProduct();
72-
BigDecimal approvedPrincipal = loan.getApprovedPrincipal();
73-
BigDecimal maxAllowed = approvedPrincipal;
74-
75-
if (loanProduct.getOverAppliedCalculationType() != null && loanProduct.getOverAppliedNumber() != null) {
76-
BigDecimal overAppliedNumber = BigDecimal.valueOf(loanProduct.getOverAppliedNumber());
77-
if ("percentage".equalsIgnoreCase(loanProduct.getOverAppliedCalculationType())) {
78-
BigDecimal extra = approvedPrincipal.multiply(overAppliedNumber).divide(BigDecimal.valueOf(100));
79-
maxAllowed = approvedPrincipal.add(extra);
80-
} else {
81-
// ABSOLUTE (flat)
82-
maxAllowed = approvedPrincipal.add(overAppliedNumber);
83-
}
84-
}
85-
54+
final BigDecimal maxAllowed = calculateMaxAllowedDisbursement(loan);
8655
BigDecimal total = totalDisbursed.add(capitalizedIncome);
87-
if (maxAllowed == null) {
88-
maxAllowed = approvedPrincipal;
89-
}
9056
if (total.compareTo(maxAllowed) > 0) {
9157
final String errorMessage = String.format(
9258
"Disbursement exceeds allowed limit including over-applied threshold. Total disbursed amount: %s Maximum allowed: %s",
@@ -96,6 +62,27 @@ public void validateOverMaximumAmount(final Loan loan, final BigDecimal totalDis
9662
}
9763
}
9864

65+
private BigDecimal calculateMaxAllowedDisbursement(final Loan loan) {
66+
final LoanProduct loanProduct = loan.getLoanProduct();
67+
final BigDecimal approvedPrincipal = loan.getApprovedPrincipal() != null ? loan.getApprovedPrincipal() : loan.getProposedPrincipal();
68+
BigDecimal maxAllowed = approvedPrincipal;
69+
70+
if (loanProduct.getOverAppliedCalculationType() != null && loanProduct.getOverAppliedNumber() != null) {
71+
final BigDecimal overAppliedMax = BigDecimal.valueOf(loanProduct.getOverAppliedNumber());
72+
final LoanOverAppliedCalculationType calculationType = LoanOverAppliedCalculationType
73+
.valueOf(loanProduct.getOverAppliedCalculationType().toUpperCase());
74+
75+
if (calculationType.isPercentage()) {
76+
final BigDecimal extra = approvedPrincipal.multiply(overAppliedMax).divide(BigDecimal.valueOf(100));
77+
maxAllowed = approvedPrincipal.add(extra);
78+
} else {
79+
maxAllowed = approvedPrincipal.add(overAppliedMax);
80+
}
81+
}
82+
83+
return maxAllowed;
84+
}
85+
9986
public void validateDisburseDate(final Loan loan, final LocalDate disbursedOn, final LocalDate expectedDate) {
10087
if (expectedDate != null
10188
&& (DateUtils.isAfter(disbursedOn, loan.fetchRepaymentScheduleInstallment(1).getDueDate())

0 commit comments

Comments
 (0)