}
@Override
public LoanScheduleData extractData(final ResultSet rs) throws SQLException, DataAccessException {
final LoanSchedulePeriodData disbursementPeriod = LoanSchedulePeriodData.disbursementOnlyPeriod(
this.disbursement.disbursementDate(), this.disbursement.amount(), this.totalFeeChargesDueAtDisbursement,
this.disbursement.isDisbursed());
final Collection<LoanSchedulePeriodData> periods = new ArrayList<>();
final MonetaryCurrency monCurrency = new MonetaryCurrency(this.currency.code(), this.currency.decimalPlaces(),
this.currency.currencyInMultiplesOf());
BigDecimal totalPrincipalDisbursed = BigDecimal.ZERO;
if (disbursementData == null || disbursementData.isEmpty()) {
periods.add(disbursementPeriod);
totalPrincipalDisbursed = Money.of(monCurrency, this.disbursement.amount()).getAmount();
} else {
if (!this.disbursement.isDisbursed()) {
excludePastUndisbursed = false;
}
this.outstandingLoanPrincipalBalance = BigDecimal.ZERO;
}
Money totalPrincipalExpected = Money.zero(monCurrency);
Money totalPrincipalPaid = Money.zero(monCurrency);
Money totalInterestCharged = Money.zero(monCurrency);
Money totalFeeChargesCharged = Money.zero(monCurrency);
Money totalPenaltyChargesCharged = Money.zero(monCurrency);
Money totalWaived = Money.zero(monCurrency);
Money totalWrittenOff = Money.zero(monCurrency);
Money totalRepaymentExpected = Money.zero(monCurrency);
Money totalRepayment = Money.zero(monCurrency);
Money totalPaidInAdvance = Money.zero(monCurrency);
Money totalPaidLate = Money.zero(monCurrency);
Money totalOutstanding = Money.zero(monCurrency);
// update totals with details of fees charged during disbursement
totalFeeChargesCharged = totalFeeChargesCharged.plus(disbursementPeriod.feeChargesDue());
totalRepaymentExpected = totalRepaymentExpected.plus(disbursementPeriod.feeChargesDue());
totalRepayment = totalRepayment.plus(disbursementPeriod.feeChargesPaid());
totalOutstanding = totalOutstanding.plus(disbursementPeriod.feeChargesDue()).minus(disbursementPeriod.feeChargesPaid());
Integer loanTermInDays = Integer.valueOf(0);
while (rs.next()) {
final Long loanId = rs.getLong("loanId");
final Integer period = JdbcSupport.getInteger(rs, "period");
LocalDate fromDate = JdbcSupport.getLocalDate(rs, "fromDate");
final LocalDate dueDate = JdbcSupport.getLocalDate(rs, "dueDate");
final LocalDate obligationsMetOnDate = JdbcSupport.getLocalDate(rs, "obligationsMetOnDate");
final boolean complete = rs.getBoolean("complete");
if (disbursementData != null) {
BigDecimal principal = BigDecimal.ZERO;
for (DisbursementData data : disbursementData) {
if (fromDate.equals(this.disbursement.disbursementDate()) && data.disbursementDate().equals(fromDate)) {
principal = principal.add(data.amount());
final LoanSchedulePeriodData periodData = LoanSchedulePeriodData.disbursementOnlyPeriod(
data.disbursementDate(), data.amount(), this.totalFeeChargesDueAtDisbursement, data.isDisbursed());
periods.add(periodData);
this.outstandingLoanPrincipalBalance = this.outstandingLoanPrincipalBalance.add(data.amount());
} else if (data.isDueForDisbursement(fromDate, dueDate)
&& this.outstandingLoanPrincipalBalance.compareTo(BigDecimal.ZERO) == 1) {
if (!excludePastUndisbursed
|| (excludePastUndisbursed && (data.isDisbursed() || !data.disbursementDate().isBefore(LocalDate.now())))) {
principal = principal.add(data.amount());
final LoanSchedulePeriodData periodData = LoanSchedulePeriodData.disbursementOnlyPeriod(
data.disbursementDate(), data.amount(), BigDecimal.ZERO, data.isDisbursed());
periods.add(periodData);
this.outstandingLoanPrincipalBalance = this.outstandingLoanPrincipalBalance.add(data.amount());
}
}
}
totalPrincipalDisbursed = totalPrincipalDisbursed.add(principal);
}
Integer daysInPeriod = Integer.valueOf(0);
if (fromDate != null) {
daysInPeriod = Days.daysBetween(fromDate, dueDate).getDays();
loanTermInDays = Integer.valueOf(loanTermInDays.intValue() + daysInPeriod.intValue());
}
final BigDecimal principalDue = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalDue");
totalPrincipalExpected = totalPrincipalExpected.plus(principalDue);
final BigDecimal principalPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalPaid");
totalPrincipalPaid = totalPrincipalPaid.plus(principalPaid);
final BigDecimal principalWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "principalWrittenOff");
final BigDecimal principalOutstanding = principalDue.subtract(principalPaid).subtract(principalWrittenOff);
final BigDecimal interestExpectedDue = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "interestDue");
totalInterestCharged = totalInterestCharged.plus(interestExpectedDue);
final BigDecimal interestPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "interestPaid");
final BigDecimal interestWaived = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "interestWaived");
final BigDecimal interestWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "interestWrittenOff");
final BigDecimal interestActualDue = interestExpectedDue.subtract(interestWaived).subtract(interestWrittenOff);
final BigDecimal interestOutstanding = interestActualDue.subtract(interestPaid);
final BigDecimal feeChargesExpectedDue = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "feeChargesDue");
totalFeeChargesCharged = totalFeeChargesCharged.plus(feeChargesExpectedDue);
final BigDecimal feeChargesPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "feeChargesPaid");
final BigDecimal feeChargesWaived = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "feeChargesWaived");
final BigDecimal feeChargesWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "feeChargesWrittenOff");
final BigDecimal feeChargesActualDue = feeChargesExpectedDue.subtract(feeChargesWaived).subtract(feeChargesWrittenOff);
final BigDecimal feeChargesOutstanding = feeChargesActualDue.subtract(feeChargesPaid);
final BigDecimal penaltyChargesExpectedDue = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penaltyChargesDue");
totalPenaltyChargesCharged = totalPenaltyChargesCharged.plus(penaltyChargesExpectedDue);
final BigDecimal penaltyChargesPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penaltyChargesPaid");
final BigDecimal penaltyChargesWaived = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penaltyChargesWaived");
final BigDecimal penaltyChargesWrittenOff = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "penaltyChargesWrittenOff");
final BigDecimal totalPaidInAdvanceForPeriod = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs,
"totalPaidInAdvanceForPeriod");
final BigDecimal totalPaidLateForPeriod = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "totalPaidLateForPeriod");
final BigDecimal penaltyChargesActualDue = penaltyChargesExpectedDue.subtract(penaltyChargesWaived).subtract(
penaltyChargesWrittenOff);
final BigDecimal penaltyChargesOutstanding = penaltyChargesActualDue.subtract(penaltyChargesPaid);
final BigDecimal totalExpectedCostOfLoanForPeriod = interestExpectedDue.add(feeChargesExpectedDue).add(
penaltyChargesExpectedDue);
final BigDecimal totalDueForPeriod = principalDue.add(totalExpectedCostOfLoanForPeriod);
final BigDecimal totalPaidForPeriod = principalPaid.add(interestPaid).add(feeChargesPaid).add(penaltyChargesPaid);
final BigDecimal totalWaivedForPeriod = interestWaived.add(feeChargesWaived).add(penaltyChargesWaived);
totalWaived = totalWaived.plus(totalWaivedForPeriod);
final BigDecimal totalWrittenOffForPeriod = principalWrittenOff.add(interestWrittenOff).add(feeChargesWrittenOff)
.add(penaltyChargesWrittenOff);
totalWrittenOff = totalWrittenOff.plus(totalWrittenOffForPeriod);
final BigDecimal totalOutstandingForPeriod = principalOutstanding.add(interestOutstanding).add(feeChargesOutstanding)
.add(penaltyChargesOutstanding);
final BigDecimal totalActualCostOfLoanForPeriod = interestActualDue.add(feeChargesActualDue).add(penaltyChargesActualDue);
totalRepaymentExpected = totalRepaymentExpected.plus(totalDueForPeriod);
totalRepayment = totalRepayment.plus(totalPaidForPeriod);
totalPaidInAdvance = totalPaidInAdvance.plus(totalPaidInAdvanceForPeriod);
totalPaidLate = totalPaidLate.plus(totalPaidLateForPeriod);
totalOutstanding = totalOutstanding.plus(totalOutstandingForPeriod);
if (fromDate == null) {
fromDate = this.lastDueDate;
}
final BigDecimal outstandingPrincipalBalanceOfLoan = this.outstandingLoanPrincipalBalance.subtract(principalDue);
// update based on current period values
this.lastDueDate = dueDate;
this.outstandingLoanPrincipalBalance = this.outstandingLoanPrincipalBalance.subtract(principalDue);
final LoanSchedulePeriodData periodData = LoanSchedulePeriodData.repaymentPeriodWithPayments(loanId, period, fromDate,
dueDate, obligationsMetOnDate, complete, principalDue, principalPaid, principalWrittenOff, principalOutstanding,
outstandingPrincipalBalanceOfLoan, interestExpectedDue, interestPaid, interestWaived, interestWrittenOff,
interestOutstanding, feeChargesExpectedDue, feeChargesPaid, feeChargesWaived, feeChargesWrittenOff,
feeChargesOutstanding, penaltyChargesExpectedDue, penaltyChargesPaid, penaltyChargesWaived,
penaltyChargesWrittenOff, penaltyChargesOutstanding, totalDueForPeriod, totalPaidForPeriod,