keep running tab on overdue amount for each period of repayment schedule, determine arrears from this based on loans arrears tolerance setting, ensure repaymentSchedule from retrieve loan has charges correctly included for disbursement period.
This commit is contained in:
+3
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE `m_loan`
|
||||
DROP COLUMN `total_charges_due_at_disbursement_derived`,
|
||||
ADD COLUMN `total_charges_due_at_disbursement_derived` decimal(19,6) DEFAULT NULL AFTER `interest_rebate_amount`;
|
||||
@@ -199,13 +199,15 @@ public class LoansApiResource {
|
||||
loanRepayments = currentLoanRepayments;
|
||||
loanRepaymentsCount = loanRepayments.size();
|
||||
}
|
||||
|
||||
DisbursementData singleDisbursement = loanBasicDetails.toDisburementData();
|
||||
repaymentSchedule = this.loanReadPlatformService.retrieveRepaymentSchedule(loanId, loanBasicDetails.getCurrency(), singleDisbursement);
|
||||
repaymentSchedule = this.loanReadPlatformService.retrieveRepaymentSchedule(loanId, loanBasicDetails.getCurrency(),
|
||||
singleDisbursement, loanBasicDetails.getTotalDisbursementCharges(), loanBasicDetails.getInArrearsTolerance());
|
||||
|
||||
MoneyData tolerance = MoneyData.of(loanBasicDetails.getCurrency(), loanBasicDetails.getInArrearsTolerance());
|
||||
MoneyData totalOutstandingMoney = MoneyData.of(loanBasicDetails.getCurrency(), repaymentSchedule.totalOutstanding());
|
||||
boolean isWaiveAllowed = totalOutstandingMoney.isGreaterThanZero() && (tolerance.isGreaterThan(totalOutstandingMoney) || tolerance.isEqualTo(totalOutstandingMoney));
|
||||
|
||||
|
||||
permissions = this.loanReadPlatformService.retrieveLoanPermissions(loanBasicDetails, isWaiveAllowed, loanRepaymentsCount);
|
||||
convenienceDataRequired = true;
|
||||
|
||||
|
||||
+10
-1
@@ -54,6 +54,7 @@ public class LoanBasicDetailsData {
|
||||
private final LocalDate expectedMaturityDate;
|
||||
private final LocalDate lifeCycleStatusDate;
|
||||
|
||||
private final BigDecimal totalDisbursementCharges;
|
||||
private final Collection<LoanChargeData> charges;
|
||||
|
||||
public static LoanBasicDetailsData populateForNewLoanCreation(final Long clientId, final String clientName, final LocalDate expectedDisbursementDate,
|
||||
@@ -146,6 +147,7 @@ public class LoanBasicDetailsData {
|
||||
this.lifeCycleStatusDate = null;
|
||||
|
||||
this.charges = charges;
|
||||
this.totalDisbursementCharges = BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
private LoanBasicDetailsData(final Long clientId, final String clientName, final LocalDate expectedDisbursementDate, final Long clientOfficeId) {
|
||||
@@ -191,6 +193,7 @@ public class LoanBasicDetailsData {
|
||||
this.interestChargedFromDate = null;
|
||||
|
||||
this.charges = null;
|
||||
this.totalDisbursementCharges = BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
public LoanBasicDetailsData(
|
||||
@@ -227,7 +230,8 @@ public class LoanBasicDetailsData {
|
||||
final EnumOptionData termPeriodFrequencyType,
|
||||
final Integer transactionStrategyId,
|
||||
final Collection<LoanChargeData> charges,
|
||||
final Long loanOfficerId, String loanOfficerName) {
|
||||
final Long loanOfficerId, String loanOfficerName,
|
||||
final BigDecimal totalDisbursementCharges) {
|
||||
this.id = id;
|
||||
this.externalId = externalId;
|
||||
this.clientId = clientId;
|
||||
@@ -266,6 +270,7 @@ public class LoanBasicDetailsData {
|
||||
this.termPeriodFrequencyType = termPeriodFrequencyType;
|
||||
this.transactionStrategyId = transactionStrategyId;
|
||||
this.charges = charges;
|
||||
this.totalDisbursementCharges = totalDisbursementCharges;
|
||||
}
|
||||
|
||||
public int getMaxSubmittedOnOffsetFromToday() {
|
||||
@@ -509,6 +514,10 @@ public class LoanBasicDetailsData {
|
||||
return loanOfficerName;
|
||||
}
|
||||
|
||||
public BigDecimal getTotalDisbursementCharges() {
|
||||
return totalDisbursementCharges;
|
||||
}
|
||||
|
||||
public DisbursementData toDisburementData() {
|
||||
return new DisbursementData(this.expectedDisbursementDate, this.actualDisbursementDate, this.principal);
|
||||
}
|
||||
|
||||
+26
-1
@@ -38,6 +38,7 @@ public class LoanSchedulePeriodData {
|
||||
private final BigDecimal totalPaidForPeriod;
|
||||
private final BigDecimal totalWaivedForPeriod;
|
||||
private final BigDecimal totalOutstandingForPeriod;
|
||||
private final BigDecimal totalOverdue;
|
||||
|
||||
public static LoanSchedulePeriodData disbursementOnlyPeriod(
|
||||
final LocalDate disbursementDate,
|
||||
@@ -118,7 +119,12 @@ public class LoanSchedulePeriodData {
|
||||
this.totalDueForPeriod = chargesDueAtTimeOfDisbursement;
|
||||
this.totalPaidForPeriod = BigDecimal.ZERO;
|
||||
this.totalWaivedForPeriod = null;
|
||||
this.totalOutstandingForPeriod = null;
|
||||
this.totalOutstandingForPeriod = chargesDueAtTimeOfDisbursement;
|
||||
if (dueDate.isBefore(new LocalDate())) {
|
||||
this.totalOverdue = this.totalOutstandingForPeriod;
|
||||
} else {
|
||||
this.totalOverdue = null;
|
||||
}
|
||||
}
|
||||
|
||||
private LoanSchedulePeriodData(
|
||||
@@ -159,6 +165,11 @@ public class LoanSchedulePeriodData {
|
||||
this.totalPaidForPeriod = BigDecimal.ZERO;
|
||||
this.totalWaivedForPeriod = null;
|
||||
this.totalOutstandingForPeriod = totalDueForPeriod;
|
||||
if (dueDate.isBefore(new LocalDate())) {
|
||||
this.totalOverdue = this.totalOutstandingForPeriod;
|
||||
} else {
|
||||
this.totalOverdue = null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -204,6 +215,12 @@ public class LoanSchedulePeriodData {
|
||||
this.totalPaidForPeriod = BigDecimal.ZERO;
|
||||
this.totalWaivedForPeriod = BigDecimal.ZERO;
|
||||
this.totalOutstandingForPeriod = totalDueForPeriod;
|
||||
|
||||
if (dueDate.isBefore(new LocalDate())) {
|
||||
this.totalOverdue = this.totalOutstandingForPeriod;
|
||||
} else {
|
||||
this.totalOverdue = null;
|
||||
}
|
||||
}
|
||||
|
||||
private BigDecimal defaultToZeroIfNull(final BigDecimal possibleNullValue) {
|
||||
@@ -230,6 +247,10 @@ public class LoanSchedulePeriodData {
|
||||
return this.dueDate;
|
||||
}
|
||||
|
||||
public Integer daysInPeriod() {
|
||||
return this.daysInPeriod;
|
||||
}
|
||||
|
||||
public BigDecimal principalDisbursed() {
|
||||
return defaultToZeroIfNull(this.principalDisbursed);
|
||||
}
|
||||
@@ -273,4 +294,8 @@ public class LoanSchedulePeriodData {
|
||||
public BigDecimal chargesOutstanding() {
|
||||
return defaultToZeroIfNull(this.chargesOutstanding);
|
||||
}
|
||||
|
||||
public BigDecimal totalOverdue() {
|
||||
return defaultToZeroIfNull(this.totalOverdue);
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
package org.mifosng.platform.loan.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.mifosng.platform.api.LoanScheduleNewData;
|
||||
@@ -14,7 +15,7 @@ public interface LoanReadPlatformService {
|
||||
|
||||
LoanBasicDetailsData retrieveLoanAccountDetails(Long loanId);
|
||||
|
||||
LoanScheduleNewData retrieveRepaymentSchedule(Long loanId, CurrencyData currency, DisbursementData disbursement);
|
||||
LoanScheduleNewData retrieveRepaymentSchedule(Long loanId, CurrencyData currency, DisbursementData disbursement, BigDecimal totalChargesAtDisbursement, BigDecimal inArrearsTolerance);
|
||||
|
||||
Collection<LoanRepaymentTransactionData> retrieveLoanPayments(Long loanId);
|
||||
|
||||
|
||||
+21
-6
@@ -91,7 +91,11 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoanScheduleNewData retrieveRepaymentSchedule(final Long loanId, final CurrencyData currency, final DisbursementData disbursement) {
|
||||
public LoanScheduleNewData retrieveRepaymentSchedule(final Long loanId,
|
||||
final CurrencyData currency,
|
||||
final DisbursementData disbursement,
|
||||
final BigDecimal totalChargesAtDisbursement,
|
||||
final BigDecimal inArrearsTolerance) {
|
||||
|
||||
try {
|
||||
context.authenticatedUser();
|
||||
@@ -99,8 +103,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
final LoanScheduleMapper rm = new LoanScheduleMapper(disbursement);
|
||||
final String sql = "select " + rm.loanScheduleSchema() + " where l.id = ? order by ls.loan_id, ls.installment";
|
||||
|
||||
// FIXME - KW - pass through total chargesDueAtTimeOfDisbursementFigure
|
||||
final LoanSchedulePeriodData disbursementPeriod = LoanSchedulePeriodData.disbursementOnlyPeriod(disbursement.disbursementDate(), disbursement.amount(), BigDecimal.ZERO);
|
||||
final LoanSchedulePeriodData disbursementPeriod = LoanSchedulePeriodData.disbursementOnlyPeriod(disbursement.disbursementDate(), disbursement.amount(), totalChargesAtDisbursement);
|
||||
|
||||
final Collection<LoanSchedulePeriodData> repaymentSchedulePeriods = this.jdbcTemplate.query(sql, rm, new Object[] { loanId });
|
||||
|
||||
@@ -110,7 +113,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
|
||||
LoanSchedulePeriodDataWrapper wrapper = new LoanSchedulePeriodDataWrapper(periods);
|
||||
|
||||
final Integer loanTermInDays = null;
|
||||
final Integer loanTermInDays = wrapper.deriveCumulativeLoanTermInDays();
|
||||
final BigDecimal cumulativePrincipalDisbursed = wrapper.deriveCumulativePrincipalDisbursed();
|
||||
final BigDecimal cumulativePrincipalDue = wrapper.deriveCumulativePrincipalDue();
|
||||
final BigDecimal cumulativePrincipalPaid = wrapper.deriveCumulativePrincipalPaid();
|
||||
@@ -128,7 +131,17 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
final BigDecimal totalPaidToDate = cumulativePrincipalPaid.add(cumulativeInterestPaid).add(cumulativeChargesPaid);
|
||||
final BigDecimal totalWaivedToDate = cumulativeInterestWaived;
|
||||
final BigDecimal totalOutstanding = cumulativePrincipalOutstanding.add(cumulativeInterestOutstanding).add(cumulativeChargesOutstanding);
|
||||
final BigDecimal totalInArrears = null;
|
||||
|
||||
final BigDecimal totalOverdue = wrapper.deriveCumulativeTotalOverdue();
|
||||
|
||||
MoneyData tolerance = MoneyData.of(currency, inArrearsTolerance);
|
||||
MoneyData totalOverdueMoney = MoneyData.of(currency, totalOverdue);
|
||||
boolean isWaiveAllowed = totalOverdueMoney.isGreaterThanZero() && (tolerance.isGreaterThan(totalOverdueMoney) || tolerance.isEqualTo(totalOverdueMoney));
|
||||
|
||||
BigDecimal totalInArrears = null;
|
||||
if (!isWaiveAllowed) {
|
||||
totalInArrears = totalOverdueMoney.getAmount();
|
||||
}
|
||||
|
||||
return new LoanScheduleNewData(currency, periods, loanTermInDays,
|
||||
cumulativePrincipalDisbursed, cumulativePrincipalDue, cumulativePrincipalPaid, cumulativePrincipalOutstanding,
|
||||
@@ -335,6 +348,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
return "l.id as id, l.external_id as externalId, l.fund_id as fundId, f.name as fundName, "
|
||||
+ " lp.id as loanProductId, lp.name as loanProductName, lp.description as loanProductDescription, c.id as clientId, c.display_name as clientName, "
|
||||
+ " c.office_id as clientOfficeId,l.submittedon_date as submittedOnDate,"
|
||||
+ " l.total_charges_due_at_disbursement_derived as totalDisbursementCharges,"
|
||||
+ " l.approvedon_date as approvedOnDate, l.expected_disbursedon_date as expectedDisbursementDate, l.disbursedon_date as actualDisbursementDate, l.expected_firstrepaymenton_date as expectedFirstRepaymentOnDate,"
|
||||
+ " l.interest_calculated_from_date as interestChargedFromDate, l.closedon_date as closedOnDate, l.expected_maturedon_date as expectedMaturityDate, "
|
||||
+ " l.principal_amount as principal, l.arrearstolerance_amount as inArrearsTolerance, l.number_of_repayments as numberOfRepayments, l.repay_every as repaymentEvery,"
|
||||
@@ -398,6 +412,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
|
||||
BigDecimal principal = rs.getBigDecimal("principal");
|
||||
BigDecimal inArrearsTolerance = rs.getBigDecimal("inArrearsTolerance");
|
||||
BigDecimal totalDisbursementCharges = rs.getBigDecimal("totalDisbursementCharges");
|
||||
|
||||
Integer numberOfRepayments = JdbcSupport.getInteger(rs,"numberOfRepayments");
|
||||
Integer repaymentEvery = JdbcSupport.getInteger(rs,"repaymentEvery");
|
||||
@@ -454,7 +469,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
interestCalculationPeriodType,
|
||||
status,
|
||||
lifeCycleStatusDate, termFrequency, termPeriodFrequencyType, transactionStrategyId, charges,
|
||||
loanOfficerId, loanOfficerName);
|
||||
loanOfficerId, loanOfficerName, totalDisbursementCharges);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+18
@@ -100,4 +100,22 @@ public class LoanSchedulePeriodDataWrapper {
|
||||
}
|
||||
return cumulativeValue;
|
||||
}
|
||||
|
||||
public Integer deriveCumulativeLoanTermInDays() {
|
||||
Integer cumulativeValue = Integer.valueOf(0);
|
||||
for (LoanSchedulePeriodData period : this.periods) {
|
||||
if (period.daysInPeriod() != null) {
|
||||
cumulativeValue += period.daysInPeriod();
|
||||
}
|
||||
}
|
||||
return cumulativeValue;
|
||||
}
|
||||
|
||||
public BigDecimal deriveCumulativeTotalOverdue() {
|
||||
BigDecimal cumulativeValue = BigDecimal.ZERO;
|
||||
for (LoanSchedulePeriodData period : this.periods) {
|
||||
cumulativeValue = cumulativeValue.add(period.totalOverdue());
|
||||
}
|
||||
return cumulativeValue;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user