diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/LoansApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/LoansApiResource.java index 7595be782..fe73046f2 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/LoansApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/LoansApiResource.java @@ -27,10 +27,10 @@ import org.mifosng.platform.api.data.LoanAccountData; import org.mifosng.platform.api.data.LoanAccountSummaryData; import org.mifosng.platform.api.data.LoanBasicDetailsData; import org.mifosng.platform.api.data.LoanPermissionData; -import org.mifosng.platform.api.data.LoanRepaymentPeriodDatajpw; +import org.mifosng.platform.api.data.LoanRepaymentPeriodData; import org.mifosng.platform.api.data.LoanSchedule; import org.mifosng.platform.api.data.LoanTransactionData; -import org.mifosng.platform.api.data.LoanTransactionDatajpw; +import org.mifosng.platform.api.data.LoanTransactionDataDTO; import org.mifosng.platform.api.data.NewLoanData; import org.mifosng.platform.api.infrastructure.ApiDataConversionService; import org.mifosng.platform.api.infrastructure.ApiJSONFormattingService; @@ -99,9 +99,9 @@ public class LoansApiResource { LoanBasicDetailsData loanBasicDetails = this.loanReadPlatformService .retrieveLoanAccountDetails(loanId); - Collection loanRepayments = this.loanReadPlatformService + Collection loanRepayments = this.loanReadPlatformService .retrieveLoanPayments(loanId); - Collection repaymentSchedule = this.loanReadPlatformService + Collection repaymentSchedule = this.loanReadPlatformService .retrieveRepaymentSchedule(loanId); LoanAccountSummaryData summary = this.loanReadPlatformService diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/DerivedLoanData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/DerivedLoanData.java deleted file mode 100644 index 353b859ea..000000000 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/DerivedLoanData.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.mifosng.platform.api.data; - -import java.util.List; - -public class DerivedLoanData { - - private LoanRepaymentScheduleData repaymentSchedule; - private LoanAccountSummaryData summary; - private List loanRepayments; - - public DerivedLoanData() { - // - } - - public DerivedLoanData(LoanRepaymentScheduleData repaymentScheduleData, LoanAccountSummaryData summaryData, List loanRepayments) { - this.repaymentSchedule = repaymentScheduleData; - this.summary = summaryData; - this.loanRepayments = loanRepayments; - } - - public LoanRepaymentScheduleData getRepaymentSchedule() { - return repaymentSchedule; - } - - public void setRepaymentSchedule(LoanRepaymentScheduleData repaymentSchedule) { - this.repaymentSchedule = repaymentSchedule; - } - - public LoanAccountSummaryData getSummary() { - return summary; - } - - public void setSummary(LoanAccountSummaryData summary) { - this.summary = summary; - } - - public List getLoanRepayments() { - return loanRepayments; - } - - public void setLoanRepayments(List loanRepayments) { - this.loanRepayments = loanRepayments; - } -} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanAccountData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanAccountData.java index e2f0c898c..292d5d9af 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanAccountData.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanAccountData.java @@ -44,8 +44,8 @@ public class LoanAccountData { private LocalDate lifeCycleStatusDate; private LoanAccountSummaryData summary; - private Collection repaymentSchedule; - private Collection loanRepayments; + private Collection repaymentSchedule; + private Collection loanRepayments; private LoanPermissionData permissions; @@ -57,8 +57,8 @@ public class LoanAccountData { public LoanAccountData(LoanBasicDetailsData basicDetails, LoanAccountSummaryData summary, - Collection repaymentSchedule, - Collection loanRepayments, + Collection repaymentSchedule, + Collection loanRepayments, LoanPermissionData permissions) { this.summary = summary; this.repaymentSchedule = repaymentSchedule; @@ -141,21 +141,21 @@ public class LoanAccountData { this.summary = summary; } - public Collection getRepaymentSchedule() { + public Collection getRepaymentSchedule() { return repaymentSchedule; } public void setRepaymentSchedule( - Collection repaymentSchedule) { + Collection repaymentSchedule) { this.repaymentSchedule = repaymentSchedule; } - public Collection getLoanRepayments() { + public Collection getLoanRepayments() { return loanRepayments; } public void setLoanRepayments( - Collection loanRepayments) { + Collection loanRepayments) { this.loanRepayments = loanRepayments; } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanRepaymentPeriodData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanRepaymentPeriodData.java index ffaf8c34a..bfa982b00 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanRepaymentPeriodData.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanRepaymentPeriodData.java @@ -4,9 +4,9 @@ import org.joda.time.LocalDate; public class LoanRepaymentPeriodData { + private Long loanId; private Integer period; private LocalDate date; - private MoneyData disbursed; private MoneyData principal; private MoneyData principalPaid; private MoneyData principalOutstanding; @@ -16,70 +16,36 @@ public class LoanRepaymentPeriodData { private MoneyData total; private MoneyData totalPaid; private MoneyData totalOutstanding; - private MoneyData totalWaived; - private MoneyData totalArrears; - private LocalDate arrearsFrom; - private LocalDate arrearsTo; - private LocalDate paidInFullOn; - private LocalDate lastAffectingPaymentOn; - - private static CurrencyData currencyData(MoneyData moneyData) { - String code = moneyData.getCurrencyCode(); - String name = moneyData.getDefaultName(); - int decimalPlaces = moneyData.getDigitsAfterDecimal(); - String displaySymbol = moneyData.getDisplaySymbol(); - String nameCode = moneyData.getNameCode(); - return new CurrencyData(code, name, decimalPlaces, displaySymbol, nameCode); - } public LoanRepaymentPeriodData() { // } - - public LoanRepaymentPeriodData(Integer period, LocalDate date, - MoneyData disbursed, MoneyData total) { - this.period = period; - this.date = date; - this.disbursed = disbursed; - this.principal = null; - this.principalPaid = null; - this.principalOutstanding = null; - this.interest = null; - this.interestPaid = null; - this.interestOutstanding = null; - this.total = total; - this.totalPaid = null; - this.totalOutstanding = total; - } - public LoanRepaymentPeriodData(Integer period, LocalDate date, - MoneyData disbursed, MoneyData principal, - MoneyData interest, MoneyData total, - MoneyData totalOutstanding) { + public LoanRepaymentPeriodData(Long loanId, Integer period, + LocalDate date, MoneyData principal, MoneyData principalPaid, + MoneyData principalOutstanding, MoneyData interest, + MoneyData interestPaid, MoneyData interestOutstanding, + MoneyData total, MoneyData totalPaid, MoneyData totalOutstanding) { + this.loanId = loanId; this.period = period; this.date = date; - this.disbursed = disbursed; this.principal = principal; - this.principalPaid = MoneyData.zero(currencyData(principal)); - this.principalOutstanding = principal; + this.principalPaid = principalPaid; + this.principalOutstanding = principalOutstanding; this.interest = interest; - this.interestPaid = MoneyData.zero(currencyData(principal)); - this.interestOutstanding = interest; + this.interestPaid = interestPaid; + this.interestOutstanding = interestOutstanding; this.total = total; - this.totalPaid = MoneyData.zero(currencyData(principal)); + this.totalPaid = totalPaid; this.totalOutstanding = totalOutstanding; } - - public boolean isInArrearsWithToleranceOf(MoneyData arrearsTolerance, LocalDate asOf) { - - boolean inArrears = false; - if (arrearsTolerance.isGreaterThanZero()) { - inArrears = this.totalOutstanding.isGreaterThan(arrearsTolerance); - } else { - inArrears = this.totalOutstanding.isGreaterThanZero(); - } - - return inArrears && this.date.isBefore(asOf); + + public Long getLoanId() { + return loanId; + } + + public void setLoanId(Long loanId) { + this.loanId = loanId; } public Integer getPeriod() { @@ -98,14 +64,6 @@ public class LoanRepaymentPeriodData { this.date = date; } - public MoneyData getDisbursed() { - return disbursed; - } - - public void setDisbursed(MoneyData disbursed) { - this.disbursed = disbursed; - } - public MoneyData getPrincipal() { return principal; } @@ -114,22 +72,6 @@ public class LoanRepaymentPeriodData { this.principal = principal; } - public MoneyData getInterest() { - return interest; - } - - public void setInterest(MoneyData interest) { - this.interest = interest; - } - - public MoneyData getTotal() { - return total; - } - - public void setTotal(MoneyData total) { - this.total = total; - } - public MoneyData getPrincipalPaid() { return principalPaid; } @@ -146,6 +88,14 @@ public class LoanRepaymentPeriodData { this.principalOutstanding = principalOutstanding; } + public MoneyData getInterest() { + return interest; + } + + public void setInterest(MoneyData interest) { + this.interest = interest; + } + public MoneyData getInterestPaid() { return interestPaid; } @@ -162,6 +112,14 @@ public class LoanRepaymentPeriodData { this.interestOutstanding = interestOutstanding; } + public MoneyData getTotal() { + return total; + } + + public void setTotal(MoneyData total) { + this.total = total; + } + public MoneyData getTotalPaid() { return totalPaid; } @@ -178,55 +136,4 @@ public class LoanRepaymentPeriodData { this.totalOutstanding = totalOutstanding; } - public boolean isFullyPaid() { - return this.totalOutstanding.isZero(); - } - - public MoneyData getTotalArrears() { - return totalArrears; - } - - public void setTotalArrears(MoneyData totalArrears) { - this.totalArrears = totalArrears; - } - - public LocalDate getArrearsFrom() { - return arrearsFrom; - } - - public void setArrearsFrom(LocalDate arrearsFrom) { - this.arrearsFrom = arrearsFrom; - } - - public LocalDate getArrearsTo() { - return arrearsTo; - } - - public void setArrearsTo(LocalDate arrearsTo) { - this.arrearsTo = arrearsTo; - } - - public LocalDate getPaidInFullOn() { - return paidInFullOn; - } - - public void setPaidInFullOn(LocalDate paidInFullOn) { - this.paidInFullOn = paidInFullOn; - } - - public LocalDate getLastAffectingPaymentOn() { - return lastAffectingPaymentOn; - } - - public void setLastAffectingPaymentOn(LocalDate lastAffectingPaymentOn) { - this.lastAffectingPaymentOn = lastAffectingPaymentOn; - } - - public MoneyData getTotalWaived() { - return totalWaived; - } - - public void setTotalWaived(MoneyData totalWaived) { - this.totalWaived = totalWaived; - } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanRepaymentPeriodDatajpw.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanRepaymentPeriodDatajpw.java deleted file mode 100644 index 06cba188c..000000000 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanRepaymentPeriodDatajpw.java +++ /dev/null @@ -1,139 +0,0 @@ -package org.mifosng.platform.api.data; - -import org.joda.time.LocalDate; - -public class LoanRepaymentPeriodDatajpw { - - private Long loanId; - private Integer period; - private LocalDate date; - private MoneyData principal; - private MoneyData principalPaid; - private MoneyData principalOutstanding; - private MoneyData interest; - private MoneyData interestPaid; - private MoneyData interestOutstanding; - private MoneyData total; - private MoneyData totalPaid; - private MoneyData totalOutstanding; - - public LoanRepaymentPeriodDatajpw() { - // - } - - public LoanRepaymentPeriodDatajpw(Long loanId, Integer period, - LocalDate date, MoneyData principal, MoneyData principalPaid, - MoneyData principalOutstanding, MoneyData interest, - MoneyData interestPaid, MoneyData interestOutstanding, - MoneyData total, MoneyData totalPaid, MoneyData totalOutstanding) { - this.loanId = loanId; - this.period = period; - this.date = date; - this.principal = principal; - this.principalPaid = principalPaid; - this.principalOutstanding = principalOutstanding; - this.interest = interest; - this.interestPaid = interestPaid; - this.interestOutstanding = interestOutstanding; - this.total = total; - this.totalPaid = totalPaid; - this.totalOutstanding = totalOutstanding; - } - - public Long getLoanId() { - return loanId; - } - - public void setLoanId(Long loanId) { - this.loanId = loanId; - } - - public Integer getPeriod() { - return period; - } - - public void setPeriod(Integer period) { - this.period = period; - } - - public LocalDate getDate() { - return date; - } - - public void setDate(LocalDate date) { - this.date = date; - } - - public MoneyData getPrincipal() { - return principal; - } - - public void setPrincipal(MoneyData principal) { - this.principal = principal; - } - - public MoneyData getPrincipalPaid() { - return principalPaid; - } - - public void setPrincipalPaid(MoneyData principalPaid) { - this.principalPaid = principalPaid; - } - - public MoneyData getPrincipalOutstanding() { - return principalOutstanding; - } - - public void setPrincipalOutstanding(MoneyData principalOutstanding) { - this.principalOutstanding = principalOutstanding; - } - - public MoneyData getInterest() { - return interest; - } - - public void setInterest(MoneyData interest) { - this.interest = interest; - } - - public MoneyData getInterestPaid() { - return interestPaid; - } - - public void setInterestPaid(MoneyData interestPaid) { - this.interestPaid = interestPaid; - } - - public MoneyData getInterestOutstanding() { - return interestOutstanding; - } - - public void setInterestOutstanding(MoneyData interestOutstanding) { - this.interestOutstanding = interestOutstanding; - } - - public MoneyData getTotal() { - return total; - } - - public void setTotal(MoneyData total) { - this.total = total; - } - - public MoneyData getTotalPaid() { - return totalPaid; - } - - public void setTotalPaid(MoneyData totalPaid) { - this.totalPaid = totalPaid; - } - - public MoneyData getTotalOutstanding() { - return totalOutstanding; - } - - public void setTotalOutstanding(MoneyData totalOutstanding) { - this.totalOutstanding = totalOutstanding; - } - -} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanRepaymentScheduleData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanRepaymentScheduleData.java deleted file mode 100644 index 0e5eba9b5..000000000 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanRepaymentScheduleData.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.mifosng.platform.api.data; - -import java.util.ArrayList; -import java.util.List; - -public class LoanRepaymentScheduleData { - - private List periods = new ArrayList(); - - public LoanRepaymentScheduleData() { - // - } - - public LoanRepaymentScheduleData( - final List periods) { - this.periods = periods; - } - - public List getPeriods() { - return periods; - } - - public void setPeriods(List periods) { - this.periods = periods; - } -} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanTransactionDatajpw.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanTransactionDataDTO.java similarity index 86% rename from mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanTransactionDatajpw.java rename to mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanTransactionDataDTO.java index 155d5e9a2..91548d9a5 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanTransactionDatajpw.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanTransactionDataDTO.java @@ -2,18 +2,18 @@ package org.mifosng.platform.api.data; import org.joda.time.LocalDate; -public class LoanTransactionDatajpw { +public class LoanTransactionDataDTO { private Long id; private EnumOptionData transactionType; private LocalDate date; private MoneyData total; - public LoanTransactionDatajpw() { + public LoanTransactionDataDTO() { // } - public LoanTransactionDatajpw(Long id, EnumOptionData transactionType, + public LoanTransactionDataDTO(Long id, EnumOptionData transactionType, final LocalDate date, final MoneyData total) { this.id = id; this.transactionType = transactionType; diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/DerivedLoanDataProcessor.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/DerivedLoanDataProcessor.java deleted file mode 100644 index 9c8d0ece7..000000000 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/DerivedLoanDataProcessor.java +++ /dev/null @@ -1,491 +0,0 @@ -package org.mifosng.platform.loan.domain; - -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.joda.time.LocalDate; -import org.mifosng.platform.api.data.CurrencyData; -import org.mifosng.platform.api.data.DerivedLoanData; -import org.mifosng.platform.api.data.EnumOptionData; -import org.mifosng.platform.api.data.LoanAccountSummaryData; -import org.mifosng.platform.api.data.LoanTransactionData; -import org.mifosng.platform.api.data.LoanRepaymentPeriodData; -import org.mifosng.platform.api.data.LoanRepaymentScheduleData; -import org.mifosng.platform.api.data.MoneyData; -import org.mifosng.platform.currency.domain.MonetaryCurrency; -import org.mifosng.platform.currency.domain.Money; -import org.mifosng.platform.loanproduct.service.LoanEnumerations; - -// FIXME - The derived details of the loan schedule are now updated on the fly when someone does a transaction against a loan. So this is not fully needed. -// - we still use this to figure out how much of a given transactions amount was principal versus interest but might not need this and we should probably -// - derive and update that on the database on the fly -// FIXME - JPW - the above fixme was done and I can't see anything else using this method or whole class -public class DerivedLoanDataProcessor { - - public DerivedLoanData process(List repaymentSchedulePeriods, List loanTransactions, - CurrencyData currencyDetail, BigDecimal arrearsTolerance) { - - // 1. derive repayment schedule - LoanRepaymentScheduleData repaymentScheduleDetails = generateRepaymentScheduleData(repaymentSchedulePeriods, currencyDetail); - List loanRepaymentPeriods = repaymentScheduleDetails.getPeriods(); - - // break up payments based on principal and interest - List loanRepayments = new ArrayList(); - int repaymentScheduleIndex = 0; - for (LoanTransaction transaction : loanTransactions) { - if (transaction.isRepayment() || transaction.isWaiver()) { - - MonetaryCurrency currency = new MonetaryCurrency(currencyDetail.getCode(), currencyDetail.getDecimalPlaces()); - - if (transaction.getAmount(currency).isGreaterThanZero()) { - LoanRepaymentPeriodData scheduledRepaymentPeriod = loanRepaymentPeriods - .get(repaymentScheduleIndex); - - if (transaction.isRepayment()) { - LoanTransactionData repaymentData = processLoanRepayment( - transaction, scheduledRepaymentPeriod, - repaymentScheduleIndex, loanRepaymentPeriods, - arrearsTolerance, currencyDetail); - loanRepayments.add(repaymentData); - } - - if (transaction.isWaiver()) { - LoanTransactionData repaymentData = processWaiver(transaction, scheduledRepaymentPeriod, currencyDetail); - loanRepayments.add(repaymentData); - } - - if (scheduledRepaymentPeriod.isFullyPaid()) { - repaymentScheduleIndex++; - } - } - } - } - - loanRepaymentPeriods = calculateArrears(loanRepaymentPeriods, arrearsTolerance, currencyDetail); - - LoanRepaymentScheduleData processRepaymentScheduleData = new LoanRepaymentScheduleData(loanRepaymentPeriods); - LoanAccountSummaryData summaryData = calculateTotalsFromRepaymentScheduleData(loanRepaymentPeriods, currencyDetail); - - Collections.sort(loanRepayments, new LoanRepaymentDataComparator()); - - if (loanRepayments.isEmpty()) { - loanRepayments = null; - } - - return new DerivedLoanData(processRepaymentScheduleData, summaryData, loanRepayments); - } - - private LoanTransactionData processWaiver(LoanTransaction transaction, - LoanRepaymentPeriodData scheduledRepaymentPeriod, CurrencyData currencyData) { - - MonetaryCurrency currency = new MonetaryCurrency(currencyData.getCode(), currencyData.getDecimalPlaces()); - Money totalToWaive = transaction.getAmount(currency); - - Money interestToWaive = moneyFrom(scheduledRepaymentPeriod.getInterestOutstanding()); - Money principalToWaive = moneyFrom(scheduledRepaymentPeriod.getPrincipalOutstanding()); - - Money interestWaived = Money.zero(currency); - - if (totalToWaive.isGreaterThanOrEqualTo(interestToWaive)) { - totalToWaive = totalToWaive.minus(interestToWaive); - interestWaived = interestToWaive; - } else { - interestWaived = totalToWaive; - totalToWaive = Money.zero(currency); - } - - Money principalWaived = Money.zero(currency); - if (totalToWaive.isGreaterThanOrEqualTo(principalToWaive)) { - totalToWaive = totalToWaive.minus(principalToWaive); - principalWaived = principalToWaive; - } else { - principalWaived = totalToWaive; - totalToWaive = Money.zero(currency); - } - - MoneyData zero = moneyDataFrom(currencyData, Money.zero(currency)); - - Money totalWaivedInPeriodToDate = Money.zero(currency); - if (scheduledRepaymentPeriod.getTotalWaived() != null) { - totalWaivedInPeriodToDate = moneyFrom(scheduledRepaymentPeriod.getTotalWaived()); - } - Money totalWaivedInTransaction = interestWaived.plus(principalWaived); - totalWaivedInPeriodToDate = totalWaivedInPeriodToDate.plus(totalWaivedInTransaction); - scheduledRepaymentPeriod.setTotalWaived(moneyDataFrom(currencyData, totalWaivedInPeriodToDate)); - - MoneyData totalWaived = moneyDataFrom(currencyData, totalWaivedInTransaction); - - Money principalOutstanding = moneyFrom(scheduledRepaymentPeriod.getPrincipalOutstanding()); - Money remainingPrincipalOutstanding = principalOutstanding.minus(principalWaived); - scheduledRepaymentPeriod.setPrincipalOutstanding(moneyDataFrom(currencyData, remainingPrincipalOutstanding)); - - Money interestOutstanding = moneyFrom(scheduledRepaymentPeriod.getInterestOutstanding()); - Money remainingInterestOutstanding = interestOutstanding.minus(interestWaived); - scheduledRepaymentPeriod.setInterestOutstanding(moneyDataFrom(currencyData, remainingInterestOutstanding)); - - Money totalOutstanding = moneyFrom(scheduledRepaymentPeriod.getTotalOutstanding()); - Money remainingOutstanding = totalOutstanding.minus(moneyFrom(totalWaived)); - scheduledRepaymentPeriod.setTotalOutstanding(moneyDataFrom(currencyData, remainingOutstanding)); - - EnumOptionData transactionType = LoanEnumerations.transactionType(LoanTransactionType.WAIVED); - LoanTransactionData loanRepaymentData = new LoanTransactionData(transaction.getId(), transactionType, transaction.getTransactionDate(), moneyDataFrom(currencyData, principalWaived), - moneyDataFrom(currencyData, interestWaived), totalWaived, zero); - loanRepaymentData.setTotalWaived(totalWaived); - return loanRepaymentData; - } - - private List calculateArrears( - List loanRepaymentPeriods, - BigDecimal arrearsTolerance, CurrencyData currencyData) { - - LocalDate today = new LocalDate(); - int repaymentIndex = 0; - for (LoanRepaymentPeriodData currentRepaymentSchedule : loanRepaymentPeriods) { - if (currentRepaymentSchedule.isInArrearsWithToleranceOf( - MoneyData.of(currencyData, arrearsTolerance), today)) { - currentRepaymentSchedule - .setTotalArrears(currentRepaymentSchedule - .getTotalOutstanding()); - - LocalDate arrearsFrom = determineInArrearsFrom(currentRepaymentSchedule, loanRepaymentPeriods, repaymentIndex); - - LocalDate arrearsTo = determineInArrearsTo(loanRepaymentPeriods, repaymentIndex); - - currentRepaymentSchedule.setArrearsFrom(arrearsFrom); - currentRepaymentSchedule.setArrearsTo(arrearsTo); - } - - repaymentIndex++; - } - - return loanRepaymentPeriods; - } - - private LocalDate determineInArrearsTo( - List loanRepaymentPeriods, - int repaymentIndex) { - - LocalDate today = new LocalDate(); - LocalDate arrearsDate = null; - - if (loanRepaymentPeriods.size() - 1 > repaymentIndex) { - LoanRepaymentPeriodData nextRepaymentSchedule = loanRepaymentPeriods - .get(repaymentIndex); - - arrearsDate = nextRepaymentSchedule.getDate().minusDays(1); - } - - if (loanRepaymentPeriods.size() - 1 == repaymentIndex) { - arrearsDate = today; - } - - return arrearsDate; - } - - private LocalDate determineInArrearsFrom( - LoanRepaymentPeriodData currentRepaymentSchedule, - List loanRepaymentPeriods, - int repaymentIndex) { - - - int previousScheduleIndex = repaymentIndex - 1; - LocalDate arrearsDate = null; - if (currentRepaymentSchedule.getLastAffectingPaymentOn() != null) { - - if (currentRepaymentSchedule.getLastAffectingPaymentOn().isAfter( - currentRepaymentSchedule.getDate())) { - - if (loanRepaymentPeriods.size() - 1 > previousScheduleIndex && previousScheduleIndex > -1) { - LoanRepaymentPeriodData lastRepaymentSchedule = loanRepaymentPeriods - .get(previousScheduleIndex); - arrearsDate = lastRepaymentSchedule.getDate().plusDays(1); - } else { - arrearsDate = currentRepaymentSchedule.getDate().minusMonths(1); - } - - } else { - arrearsDate = currentRepaymentSchedule.getLastAffectingPaymentOn(); - } - } else { - if (loanRepaymentPeriods.size() - 1 > previousScheduleIndex && previousScheduleIndex > -1) { - LoanRepaymentPeriodData lastRepaymentSchedule = loanRepaymentPeriods - .get(previousScheduleIndex); - arrearsDate = lastRepaymentSchedule.getDate().plusDays(1); - } else { - arrearsDate = currentRepaymentSchedule.getDate().minusMonths(1); - } - } - - return arrearsDate; - } - - private LoanAccountSummaryData calculateTotalsFromRepaymentScheduleData( - List loanRepaymentPeriods, CurrencyData currencyData) { - - MonetaryCurrency monetaryCurrency = new MonetaryCurrency(currencyData.getCode(), currencyData.getDecimalPlaces()); - - Money principalExpected = Money.zero(monetaryCurrency); - Money principalPaid = Money.zero(monetaryCurrency); - Money principalOutstanding = Money.zero(monetaryCurrency); - - Money interestExpected = Money.zero(monetaryCurrency); - Money interestPaid = Money.zero(monetaryCurrency); - Money interestOutstanding = Money.zero(monetaryCurrency); - - Money totalExpected = Money.zero(monetaryCurrency); - Money totalPaid = Money.zero(monetaryCurrency); - Money totalOutstanding = Money.zero(monetaryCurrency); - - Money totalInArrears = Money.zero(monetaryCurrency); - Money totalWaived = Money.zero(monetaryCurrency); - - - for (LoanRepaymentPeriodData period : loanRepaymentPeriods) { - - principalExpected = principalExpected.plus(moneyFrom(period.getPrincipal())); - principalPaid = principalPaid.plus(moneyFrom(period.getPrincipalPaid())); - principalOutstanding = principalOutstanding.plus(moneyFrom(period.getPrincipalOutstanding())); - - interestExpected = interestExpected.plus(moneyFrom(period.getInterest())); - interestPaid = interestPaid.plus(moneyFrom(period.getInterestPaid())); - interestOutstanding = interestOutstanding.plus(moneyFrom(period.getInterestOutstanding())); - - totalExpected = totalExpected.plus(moneyFrom(period.getTotal())); - totalPaid = totalPaid.plus(moneyFrom(period.getTotalPaid())); - totalOutstanding = totalOutstanding.plus(moneyFrom(period.getTotalOutstanding())); - - if (period.getTotalWaived() != null) { - totalWaived = totalWaived.plus(moneyFrom(period.getTotalWaived())); - } - - if (period.getTotalArrears() != null) { - totalInArrears = totalInArrears.plus(moneyFrom(period.getTotalArrears())); - } - } - - return new LoanAccountSummaryData(moneyDataFrom(currencyData, principalExpected), moneyDataFrom(currencyData, principalPaid), - moneyDataFrom(currencyData, principalOutstanding), moneyDataFrom(currencyData, interestExpected), - moneyDataFrom(currencyData, interestPaid), moneyDataFrom(currencyData, interestOutstanding), - moneyDataFrom(currencyData, totalExpected), moneyDataFrom(currencyData, totalPaid), moneyDataFrom(currencyData, totalOutstanding), - moneyDataFrom(currencyData, totalInArrears), moneyDataFrom(currencyData, totalWaived)); - } - - /** - * TODO - pays off interest first then principal so should make this configurable when generating 'derived view of loan account' - */ - private LoanTransactionData processLoanRepayment(LoanTransaction repayment, - LoanRepaymentPeriodData scheduledRepayment, - int repaymentScheduleIndex, - List repaymentSchedulePeriods, - BigDecimal arrearsTolerance, CurrencyData currencyDetail) { - - MoneyData zero = MoneyData.zero(currencyDetail); - MoneyData cumulativeInterestPaid = MoneyData.zero(currencyDetail); - MoneyData cumulativePrincipalPaid = MoneyData.zero(currencyDetail); - - LoanRepaymentPeriodData currentRepaymentSchedule = scheduledRepayment; - int currentRepaymentScheduleIndex = repaymentScheduleIndex; - MoneyData overpaid = null; - - MonetaryCurrency currency = new MonetaryCurrency(currencyDetail.getCode(), currencyDetail.getDecimalPlaces()); - - Money remaining = repayment.getAmount(currency); - while (remaining.isGreaterThanZero()) { - - Money interestOutstanding = moneyFrom(currentRepaymentSchedule.getInterestOutstanding()); - Money principalOutstanding = moneyFrom(currentRepaymentSchedule.getPrincipalOutstanding()); - - // pay off interest component - if (remaining.isGreaterThanOrEqualTo(interestOutstanding)) { - Money previousInterestPaid = moneyFrom(cumulativeInterestPaid); - cumulativeInterestPaid = moneyDataFrom(currencyDetail, previousInterestPaid.plus(interestOutstanding)); - - MoneyData interestPaid = moneyDataFrom(currencyDetail, interestOutstanding); - - Money paidToDate = moneyFrom(currentRepaymentSchedule.getInterestPaid()); - Money amountPaid = moneyFrom(interestPaid); - - paidToDate = paidToDate.plus(amountPaid); - - MoneyData totalInterest = moneyDataFrom(currencyDetail, paidToDate); - currentRepaymentSchedule.setInterestPaid(totalInterest); - - currentRepaymentSchedule.setInterestOutstanding(zero); - - Money totalPaidToDate = moneyFrom(currentRepaymentSchedule.getTotalPaid()); - totalPaidToDate = totalPaidToDate.plus(interestOutstanding); - - currentRepaymentSchedule.setTotalPaid(moneyDataFrom(currencyDetail, totalPaidToDate)); - - Money outstanding = moneyFrom(currentRepaymentSchedule.getTotal()).minus(moneyFrom(currentRepaymentSchedule.getTotalPaid())); - currentRepaymentSchedule.setTotalOutstanding(moneyDataFrom(currencyDetail, outstanding)); - - if (interestOutstanding.isGreaterThanZero()) { - currentRepaymentSchedule.setLastAffectingPaymentOn(repayment.getTransactionDate()); - } - - remaining = remaining.minus(interestOutstanding); - } else { - // partial payment of principal - Money previousInterestPaid = moneyFrom(cumulativeInterestPaid); - cumulativeInterestPaid = moneyDataFrom(currencyDetail, previousInterestPaid.plus(remaining)); - - MoneyData interestPaid = moneyDataFrom(currencyDetail, remaining); - - Money paidToDate = moneyFrom(currentRepaymentSchedule.getInterestPaid()); - Money amountPaid = moneyFrom(interestPaid); - - paidToDate = paidToDate.plus(amountPaid); - - MoneyData totalInterest = moneyDataFrom(currencyDetail, paidToDate); - currentRepaymentSchedule.setInterestPaid(totalInterest); - - interestOutstanding = interestOutstanding.minus(amountPaid); - - currentRepaymentSchedule.setInterestOutstanding(moneyDataFrom(currencyDetail, interestOutstanding)); - - Money totalPaidToDate = moneyFrom(currentRepaymentSchedule.getTotalPaid()); - totalPaidToDate = totalPaidToDate.plus(amountPaid); - - currentRepaymentSchedule.setTotalPaid(moneyDataFrom(currencyDetail, totalPaidToDate)); - - Money outstanding = moneyFrom(currentRepaymentSchedule.getTotal()).minus(moneyFrom(currentRepaymentSchedule.getTotalPaid())); - currentRepaymentSchedule.setTotalOutstanding(moneyDataFrom(currencyDetail, outstanding)); - - if (interestPaid.isGreaterThanZero()) { - currentRepaymentSchedule.setLastAffectingPaymentOn(repayment.getTransactionDate()); - } - - remaining = remaining.minus(amountPaid); - } - - // pay off principal component - if (remaining.isGreaterThanOrEqualTo(principalOutstanding)) { - Money previousPrincipalPaid = moneyFrom(cumulativePrincipalPaid); - cumulativePrincipalPaid = moneyDataFrom(currencyDetail, previousPrincipalPaid.plus(principalOutstanding)); - - MoneyData principalPaid = moneyDataFrom(currencyDetail, principalOutstanding); - - Money paidToDate = moneyFrom(currentRepaymentSchedule.getPrincipalPaid()); - Money amountPaid = moneyFrom(principalPaid); - - paidToDate = paidToDate.plus(amountPaid); - - MoneyData totalPrincipal = moneyDataFrom(currencyDetail, paidToDate); - currentRepaymentSchedule.setPrincipalPaid(totalPrincipal); - currentRepaymentSchedule.setPrincipalOutstanding(zero); - - Money totalPaidToDate = moneyFrom(currentRepaymentSchedule.getTotalPaid()); - totalPaidToDate = totalPaidToDate.plus(principalOutstanding); - - currentRepaymentSchedule.setTotalPaid(moneyDataFrom(currencyDetail, totalPaidToDate)); - - Money outstanding = moneyFrom(currentRepaymentSchedule.getTotal()).minus(moneyFrom(currentRepaymentSchedule.getTotalPaid())); - currentRepaymentSchedule.setTotalOutstanding(moneyDataFrom(currencyDetail, outstanding)); - - remaining = remaining.minus(principalOutstanding); - } else { - // partial payment of principal - Money previousPrincipalPaid = moneyFrom(cumulativePrincipalPaid); - cumulativePrincipalPaid = moneyDataFrom(currencyDetail, previousPrincipalPaid.plus(remaining)); - - MoneyData principalPaid = moneyDataFrom(currencyDetail, remaining); - - Money paidToDate = moneyFrom(currentRepaymentSchedule.getPrincipalPaid()); - Money amountPaid = moneyFrom(principalPaid); - - paidToDate = paidToDate.plus(amountPaid); - - MoneyData totalPrincipal = moneyDataFrom(currencyDetail, paidToDate); - currentRepaymentSchedule.setPrincipalPaid(totalPrincipal); - - principalOutstanding = principalOutstanding.minus(amountPaid); - currentRepaymentSchedule.setPrincipalOutstanding(moneyDataFrom(currencyDetail, principalOutstanding)); - - Money totalPaidToDate = moneyFrom(currentRepaymentSchedule.getTotalPaid()); - totalPaidToDate = totalPaidToDate.plus(amountPaid); - - currentRepaymentSchedule.setTotalPaid(moneyDataFrom(currencyDetail, totalPaidToDate)); - Money outstanding = moneyFrom(currentRepaymentSchedule.getTotal()).minus(moneyFrom(currentRepaymentSchedule.getTotalPaid())); - currentRepaymentSchedule.setTotalOutstanding(moneyDataFrom(currencyDetail, outstanding)); - - if (principalPaid.isGreaterThanZero()) { - currentRepaymentSchedule.setLastAffectingPaymentOn(repayment.getTransactionDate()); - } - - remaining = remaining.minus(amountPaid); - } - - // mark schedule as paid in full - if (currentRepaymentSchedule.isFullyPaid()) { - currentRepaymentSchedule.setPaidInFullOn(repayment.getTransactionDate()); - } - - // check if this installment has - if (currentRepaymentSchedule.isInArrearsWithToleranceOf(MoneyData.of(currencyDetail, arrearsTolerance), repayment.getTransactionDate())) { - currentRepaymentSchedule.setTotalArrears(currentRepaymentSchedule.getTotalOutstanding()); - } else { - currentRepaymentSchedule.setTotalArrears(MoneyData.zero(currencyDetail)); - } - - if (remaining.isGreaterThanZero()) { - currentRepaymentScheduleIndex++; - if (repaymentSchedulePeriods.size() > currentRepaymentScheduleIndex) { - currentRepaymentSchedule = repaymentSchedulePeriods.get(currentRepaymentScheduleIndex); - } else { - // loan has been overpaid by an amount so - overpaid = moneyDataFrom(currencyDetail, remaining); - // note - maybe should set the overpayment 'amount' against repayment period. - remaining = Money.zero(remaining.getCurrency()); - } - } - } - - Money totalInterestComponent = moneyFrom(cumulativeInterestPaid); - Money totalPrincipalComponent= moneyFrom(cumulativePrincipalPaid); - - MoneyData totalPaid = moneyDataFrom(currencyDetail, totalPrincipalComponent.plus(totalInterestComponent)); - - EnumOptionData transactionType = LoanEnumerations.transactionType(LoanTransactionType.REPAYMENT); - LoanTransactionData loanRepaymentData = new LoanTransactionData(repayment.getId(), transactionType, repayment.getTransactionDate(), cumulativePrincipalPaid, cumulativeInterestPaid, totalPaid, overpaid); - return loanRepaymentData; - } - - private LoanRepaymentScheduleData generateRepaymentScheduleData( - List repaymentSchedulePeriods, - CurrencyData currencyData) { - - MoneyData zero = MoneyData.zero(currencyData); - - MonetaryCurrency currency = new MonetaryCurrency(currencyData.getCode(), currencyData.getDecimalPlaces()); - - List loanScheduleDetails = new ArrayList(); - - for (LoanRepaymentScheduleInstallment scheduledRepayment : repaymentSchedulePeriods) { - - MoneyData principal = MoneyData.of(currencyData, scheduledRepayment.getPrincipal(currency).getAmount()); - MoneyData interest = MoneyData.of(currencyData, scheduledRepayment.getInterest(currency).getAmount()); - MoneyData total = MoneyData.of(currencyData, scheduledRepayment.getTotal(currency).getAmount()); - - LoanRepaymentPeriodData periodData = new LoanRepaymentPeriodData( - scheduledRepayment.getInstallmentNumber(), - scheduledRepayment.getDueDate(), zero, principal, interest, - total, total); - - loanScheduleDetails.add(periodData); - } - - return new LoanRepaymentScheduleData(loanScheduleDetails); - } - - private Money moneyFrom(MoneyData money) { - MonetaryCurrency monetaryCurrency = new MonetaryCurrency(money.getCurrencyCode(), money.getDigitsAfterDecimal()); - return Money.of(monetaryCurrency, money.getAmount()); - } - - private MoneyData moneyDataFrom(CurrencyData currencyData, Money money) { - return MoneyData.of(currencyData, money.getAmount()); - } -} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformService.java index 7b638e9de..26bce13b4 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformService.java @@ -5,9 +5,9 @@ import java.util.Collection; import org.mifosng.platform.api.data.LoanAccountSummaryData; import org.mifosng.platform.api.data.LoanBasicDetailsData; import org.mifosng.platform.api.data.LoanPermissionData; -import org.mifosng.platform.api.data.LoanRepaymentPeriodDatajpw; +import org.mifosng.platform.api.data.LoanRepaymentPeriodData; import org.mifosng.platform.api.data.LoanTransactionData; -import org.mifosng.platform.api.data.LoanTransactionDatajpw; +import org.mifosng.platform.api.data.LoanTransactionDataDTO; import org.mifosng.platform.api.data.MoneyData; import org.mifosng.platform.api.data.NewLoanData; @@ -15,13 +15,13 @@ public interface LoanReadPlatformService { LoanBasicDetailsData retrieveLoanAccountDetails(Long loanId); - Collection retrieveRepaymentSchedule(Long loanId); + Collection retrieveRepaymentSchedule(Long loanId); - Collection retrieveLoanPayments(Long loanId); + Collection retrieveLoanPayments(Long loanId); LoanAccountSummaryData retrieveSummary(MoneyData principal, - Collection repaymentSchedule, - Collection loanRepayments); + Collection repaymentSchedule, + Collection loanRepayments); LoanPermissionData retrieveLoanPermissions( LoanBasicDetailsData loanBasicDetails, boolean isWaiverAllowed, diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java index 129e5b967..4a9ff0724 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/service/LoanReadPlatformServiceImpl.java @@ -15,9 +15,9 @@ import org.mifosng.platform.api.data.LoanBasicDetailsData; import org.mifosng.platform.api.data.LoanPermissionData; import org.mifosng.platform.api.data.LoanProductData; import org.mifosng.platform.api.data.LoanProductLookup; -import org.mifosng.platform.api.data.LoanRepaymentPeriodDatajpw; +import org.mifosng.platform.api.data.LoanRepaymentPeriodData; import org.mifosng.platform.api.data.LoanTransactionData; -import org.mifosng.platform.api.data.LoanTransactionDatajpw; +import org.mifosng.platform.api.data.LoanTransactionDataDTO; import org.mifosng.platform.api.data.MoneyData; import org.mifosng.platform.api.data.NewLoanData; import org.mifosng.platform.client.service.ClientReadPlatformService; @@ -90,7 +90,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { } @Override - public Collection retrieveRepaymentSchedule( + public Collection retrieveRepaymentSchedule( Long loanId) { try { @@ -108,8 +108,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { @Override public LoanAccountSummaryData retrieveSummary(MoneyData principal, - Collection repaymentSchedule, - Collection loanRepayments) { + Collection repaymentSchedule, + Collection loanRepayments) { CurrencyData currencyData = new CurrencyData( principal.getCurrencyCode(), principal.getDefaultName(), @@ -128,7 +128,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { BigDecimal totalInArrears = BigDecimal.ZERO; BigDecimal totalWaived = BigDecimal.ZERO; - for (LoanRepaymentPeriodDatajpw installment : repaymentSchedule) { + for (LoanRepaymentPeriodData installment : repaymentSchedule) { originalPrincipal = originalPrincipal.add(installment .getPrincipal().getAmount()); principalPaid = principalPaid.add(installment.getPrincipalPaid() @@ -149,12 +149,14 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { totalOutstanding = totalOutstanding.add(installment .getTotalOutstanding().getAmount()); + if (installment.getDate().isBefore(new LocalDate())) { + totalInArrears = totalInArrears.add(installment + .getTotalOutstanding().getAmount()); + } } - totalInArrears = BigDecimal.TEN; - Long waiverType = (long) 4; - for (LoanTransactionDatajpw loanRepayment : loanRepayments) { + for (LoanTransactionDataDTO loanRepayment : loanRepayments) { Long transactionType = loanRepayment.getTransactionType().getId(); if (transactionType.equals(waiverType)) { totalWaived = totalWaived.add(loanRepayment.getTotal() @@ -176,7 +178,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { } @Override - public Collection retrieveLoanPayments(Long loanId) { + public Collection retrieveLoanPayments(Long loanId) { try { context.authenticatedUser(); @@ -214,7 +216,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { boolean undoApprovalAllowed = waitingForDisbursal; - boolean undoDisbursalAllowed = isActive && (repaymentAndWaiveCount == 0); + boolean undoDisbursalAllowed = isActive + && (repaymentAndWaiveCount == 0); boolean disbursalAllowed = waitingForDisbursal; @@ -524,7 +527,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { } private static final class LoanScheduleMapper implements - RowMapper { + RowMapper { public String loanScheduleSchema() { @@ -538,7 +541,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { } @Override - public LoanRepaymentPeriodDatajpw mapRow(final ResultSet rs, + public LoanRepaymentPeriodData mapRow(final ResultSet rs, final int rowNum) throws SQLException { String currencyCode = rs.getString("currencyCode"); @@ -579,7 +582,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { principalBD.add(interestBD).subtract(principalPaidBD) .subtract(interestPaidBD)); - return new LoanRepaymentPeriodDatajpw(loanId, period, date, + return new LoanRepaymentPeriodData(loanId, period, date, principal, principalPaid, principalOutstanding, interest, interestPaid, interestOutstanding, total, totalPaid, totalOutstanding); @@ -587,7 +590,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { } private static final class LoanPaymentsMapper implements - RowMapper { + RowMapper { public String LoanPaymentsSchema() { @@ -599,7 +602,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { } @Override - public LoanTransactionDatajpw mapRow(final ResultSet rs, + public LoanTransactionDataDTO mapRow(final ResultSet rs, final int rowNum) throws SQLException { String currencyCode = rs.getString("currencyCode"); @@ -622,7 +625,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { BigDecimal totalBD = rs.getBigDecimal("total"); MoneyData total = MoneyData.of(currencyData, totalBD); - return new LoanTransactionDatajpw(id, transactionType, date, total); + return new LoanTransactionDataDTO(id, transactionType, date, total); } } diff --git a/mifosng-provider/src/test/java/org/mifosng/platform/loan/domain/DerivedLoanDataProcessorTest.java b/mifosng-provider/src/test/java/org/mifosng/platform/loan/domain/DerivedLoanDataProcessorTest.java deleted file mode 100644 index 2d721a4b8..000000000 --- a/mifosng-provider/src/test/java/org/mifosng/platform/loan/domain/DerivedLoanDataProcessorTest.java +++ /dev/null @@ -1,376 +0,0 @@ -package org.mifosng.platform.loan.domain; - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.junit.Assert.assertThat; - -import java.util.ArrayList; -import java.util.List; - -import org.joda.time.LocalDate; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mifosng.platform.api.data.CurrencyData; -import org.mifosng.platform.api.data.DerivedLoanData; -import org.mifosng.platform.api.data.LoanTransactionData; -import org.mifosng.platform.api.data.LoanRepaymentPeriodData; -import org.mifosng.platform.api.data.LoanRepaymentScheduleData; -import org.mifosng.platform.api.data.MoneyData; -import org.mifosng.platform.currency.domain.MonetaryCurrency; -import org.mifosng.platform.currency.domain.Money; -import org.mockito.runners.MockitoJUnitRunner; - -@RunWith(MockitoJUnitRunner.class) -public class DerivedLoanDataProcessorTest { - - private DerivedLoanDataProcessor loanDataProcessor = new DerivedLoanDataProcessor(); - private MonetaryCurrency cfaCurrency = new MonetaryCurrencyBuilder().withCode("XOF").withDigitsAfterDecimal(0).build(); - private Money arrearsTolerance = new MoneyBuilder().with(cfaCurrency).with("0.0").build(); - - @Test - public void shouldDeriveLoanRepaymentScheduleWithSingleRepaymentPeriodAndRepaymentInFull() { - - - - List repaymentScheduleWithSinglePeriod = new ArrayList(); - - LoanRepaymentScheduleInstallment firstRepaymentPeriod = new LoanRepaymentScheduleInstallmentBuilder(cfaCurrency) - .withPrincipal("1000") - .withInterest("10") - .withDueDate(LocalDate.now()) - .build(); - repaymentScheduleWithSinglePeriod.add(firstRepaymentPeriod); - - List singleRepaymentInFull = new ArrayList(); - - Money fullAmount = new MoneyBuilder().with(cfaCurrency).with("1010").build(); - - LoanTransaction fullRepayment = new LoanTransactionBuilder().with(fullAmount).build(); - singleRepaymentInFull.add(fullRepayment); - - // exercise test - DerivedLoanData derivedData = loanDataProcessor.process(repaymentScheduleWithSinglePeriod, singleRepaymentInFull, asCurrencyData(cfaCurrency), arrearsTolerance); - - // verification - assertThat(derivedData, is(notNullValue())); - - LoanRepaymentScheduleData repaymentSchedule = derivedData.getRepaymentSchedule(); - assertThat(repaymentSchedule, is(notNullValue())); - - List periods = repaymentSchedule.getPeriods(); - assertThat(periods, is(notNullValue())); - assertThat(periods.size(), is(1)); - - LoanRepaymentPeriodData periodData = periods.get(0); - - MoneyData expectedPrincipal = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("1000").build()); - MoneyData expectedPrincipalPaid = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("1000").build()); - MoneyData expectedPrincipalOutstanding = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("0").build()); - MoneyData expectedInterest = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("10").build()); - MoneyData expectedInterestPaid = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("10").build()); - MoneyData expectedInterestOutstanding = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("0").build()); - - MoneyData expectedTotal = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("1010").build()); - - assertThat(periodData.getPrincipal(), is(expectedPrincipal)); - assertThat(periodData.getPrincipalPaid(), is(expectedPrincipalPaid)); - assertThat(periodData.getPrincipalOutstanding(), is(expectedPrincipalOutstanding)); - - assertThat(periodData.getInterest(), is(expectedInterest)); - assertThat(periodData.getInterestPaid(), is(expectedInterestPaid)); - assertThat(periodData.getInterestOutstanding(), is(expectedInterestOutstanding)); - - // assert repayments are ok - List loanRepayments = derivedData.getLoanRepayments(); - assertThat(loanRepayments, is(notNullValue())); - assertThat(loanRepayments.size(), is(1)); - - LoanTransactionData firstRepayment = loanRepayments.get(0); - assertThat(firstRepayment.getPrincipal(), is(expectedPrincipalPaid)); - assertThat(firstRepayment.getInterest(), is(expectedInterestPaid)); - assertThat(firstRepayment.getTotal(), is(expectedTotal)); - } - - private CurrencyData asCurrencyData(MonetaryCurrency currency) { - return new CurrencyData(currency.getCode(), "", currency.getDigitsAfterDecimal(), "CFA", ""); - } - - @Test - public void shouldDeriveLoanRepaymentScheduleWithSingleRepaymentPeriodAndPartialRepayment() { - - List repaymentScheduleWithSinglePeriod = new ArrayList(); - - LoanRepaymentScheduleInstallment firstRepaymentPeriod = new LoanRepaymentScheduleInstallmentBuilder(cfaCurrency) - .withPrincipal("1000") - .withInterest("10") - .withDueDate(LocalDate.now()) - .build(); - repaymentScheduleWithSinglePeriod.add(firstRepaymentPeriod); - - List singlePartialRepayment = new ArrayList(); - - Money partialAmount = new MoneyBuilder().with(cfaCurrency).with("510").build(); - - LoanTransaction partialRepayment = new LoanTransactionBuilder().with(partialAmount).build(); - singlePartialRepayment.add(partialRepayment); - - // exercise test - DerivedLoanData derivedData = loanDataProcessor.process(repaymentScheduleWithSinglePeriod, singlePartialRepayment, asCurrencyData(cfaCurrency), arrearsTolerance); - - // verification - assertThat(derivedData, is(notNullValue())); - - LoanRepaymentScheduleData repaymentSchedule = derivedData.getRepaymentSchedule(); - assertThat(repaymentSchedule, is(notNullValue())); - - List periods = repaymentSchedule.getPeriods(); - assertThat(periods, is(notNullValue())); - assertThat(periods.size(), is(1)); - - LoanRepaymentPeriodData periodData = periods.get(0); - - MoneyData expectedPrincipal = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("1000").build()); - MoneyData expectedPrincipalPaid = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("500").build()); - MoneyData expectedPrincipalOutstanding = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("500").build()); - MoneyData expectedInterest = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("10").build()); - MoneyData expectedInterestPaid = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("10").build()); - MoneyData expectedInterestOutstanding = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("0").build()); - - MoneyData expectedTotal = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("510").build()); - - assertThat(periodData.getPrincipal(), is(expectedPrincipal)); - assertThat(periodData.getPrincipalPaid(), is(expectedPrincipalPaid)); - assertThat(periodData.getPrincipalOutstanding(), is(expectedPrincipalOutstanding)); - - assertThat(periodData.getInterest(), is(expectedInterest)); - assertThat(periodData.getInterestPaid(), is(expectedInterestPaid)); - assertThat(periodData.getInterestOutstanding(), is(expectedInterestOutstanding)); - - // assert repayments are ok - List loanRepayments = derivedData.getLoanRepayments(); - assertThat(loanRepayments, is(notNullValue())); - assertThat(loanRepayments.size(), is(1)); - - LoanTransactionData firstRepayment = loanRepayments.get(0); - assertThat(firstRepayment.getPrincipal(), is(expectedPrincipalPaid)); - assertThat(firstRepayment.getInterest(), is(expectedInterestPaid)); - assertThat(firstRepayment.getTotal(), is(expectedTotal)); - } - - - @Test - public void shouldDeriveLoanRepaymentScheduleWithSingleRepaymentPeriodAndPartialRepaymentLessThanInterestComponent() { - - List repaymentScheduleWithSinglePeriod = new ArrayList(); - - LoanRepaymentScheduleInstallment firstRepaymentPeriod = new LoanRepaymentScheduleInstallmentBuilder(cfaCurrency) - .withPrincipal("1000") - .withInterest("10") - .withDueDate(LocalDate.now()) - .build(); - repaymentScheduleWithSinglePeriod.add(firstRepaymentPeriod); - - List singlePartialRepayment = new ArrayList(); - - Money partialAmount = new MoneyBuilder().with(cfaCurrency).with("5").build(); - - LoanTransaction partialRepayment = new LoanTransactionBuilder().with(partialAmount).build(); - singlePartialRepayment.add(partialRepayment); - - // exercise test - DerivedLoanData derivedData = loanDataProcessor.process(repaymentScheduleWithSinglePeriod, singlePartialRepayment, asCurrencyData(cfaCurrency), arrearsTolerance); - - // verification - assertThat(derivedData, is(notNullValue())); - - LoanRepaymentScheduleData repaymentSchedule = derivedData.getRepaymentSchedule(); - assertThat(repaymentSchedule, is(notNullValue())); - - List periods = repaymentSchedule.getPeriods(); - assertThat(periods, is(notNullValue())); - assertThat(periods.size(), is(1)); - - LoanRepaymentPeriodData periodData = periods.get(0); - - MoneyData expectedPrincipal = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("1000").build()); - MoneyData expectedPrincipalPaid = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("0").build()); - MoneyData expectedPrincipalOutstanding = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("1000").build()); - MoneyData expectedInterest = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("10").build()); - MoneyData expectedInterestPaid = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("5").build()); - MoneyData expectedInterestOutstanding = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("5").build()); - - MoneyData expectedTotal = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("5").build()); - - assertThat(periodData.getPrincipal(), is(expectedPrincipal)); - assertThat(periodData.getPrincipalPaid(), is(expectedPrincipalPaid)); - assertThat(periodData.getPrincipalOutstanding(), is(expectedPrincipalOutstanding)); - - assertThat(periodData.getInterest(), is(expectedInterest)); - assertThat(periodData.getInterestPaid(), is(expectedInterestPaid)); - assertThat(periodData.getInterestOutstanding(), is(expectedInterestOutstanding)); - - // assert repayments are ok - List loanRepayments = derivedData.getLoanRepayments(); - assertThat(loanRepayments, is(notNullValue())); - assertThat(loanRepayments.size(), is(1)); - - LoanTransactionData firstRepayment = loanRepayments.get(0); - assertThat(firstRepayment.getPrincipal(), is(expectedPrincipalPaid)); - assertThat(firstRepayment.getInterest(), is(expectedInterestPaid)); - assertThat(firstRepayment.getTotal(), is(expectedTotal)); - } - - @Test - public void shouldDeriveLoanRepaymentScheduleWithSingleRepaymentPeriodAndOverPayment() { - - List repaymentScheduleWithSinglePeriod = new ArrayList(); - - LoanRepaymentScheduleInstallment firstRepaymentPeriod = new LoanRepaymentScheduleInstallmentBuilder(cfaCurrency) - .withPrincipal("1000") - .withInterest("10") - .withDueDate(LocalDate.now()) - .build(); - repaymentScheduleWithSinglePeriod.add(firstRepaymentPeriod); - - List singleOverRepayment = new ArrayList(); - - Money partialAmount = new MoneyBuilder().with(cfaCurrency).with("1200").build(); - - LoanTransaction overRepayment = new LoanTransactionBuilder().with(partialAmount).build(); - singleOverRepayment.add(overRepayment); - - // exercise test - DerivedLoanData derivedData = loanDataProcessor.process(repaymentScheduleWithSinglePeriod, singleOverRepayment, asCurrencyData(cfaCurrency), arrearsTolerance); - - // verification - assertThat(derivedData, is(notNullValue())); - - LoanRepaymentScheduleData repaymentSchedule = derivedData.getRepaymentSchedule(); - assertThat(repaymentSchedule, is(notNullValue())); - - List periods = repaymentSchedule.getPeriods(); - assertThat(periods, is(notNullValue())); - assertThat(periods.size(), is(1)); - - LoanRepaymentPeriodData periodData = periods.get(0); - - MoneyData expectedPrincipal = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("1000").build()); - MoneyData expectedPrincipalPaid = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("1000").build()); - MoneyData expectedPrincipalOutstanding = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("0").build()); - MoneyData expectedInterest = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("10").build()); - MoneyData expectedInterestPaid = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("10").build()); - MoneyData expectedInterestOutstanding = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("0").build()); - - MoneyData expectedTotal = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("1010").build()); - MoneyData expectedOverpayment = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("190").build()); - - assertThat(periodData.getPrincipal(), is(expectedPrincipal)); - assertThat(periodData.getPrincipalPaid(), is(expectedPrincipalPaid)); - assertThat(periodData.getPrincipalOutstanding(), is(expectedPrincipalOutstanding)); - - assertThat(periodData.getInterest(), is(expectedInterest)); - assertThat(periodData.getInterestPaid(), is(expectedInterestPaid)); - assertThat(periodData.getInterestOutstanding(), is(expectedInterestOutstanding)); - - // assert repayments are ok - List loanRepayments = derivedData.getLoanRepayments(); - assertThat(loanRepayments, is(notNullValue())); - assertThat(loanRepayments.size(), is(1)); - - LoanTransactionData firstRepayment = loanRepayments.get(0); - assertThat(firstRepayment.getPrincipal(), is(expectedPrincipalPaid)); - assertThat(firstRepayment.getInterest(), is(expectedInterestPaid)); - assertThat(firstRepayment.getTotal(), is(expectedTotal)); - assertThat(firstRepayment.getOverpaid(), is(expectedOverpayment)); - } - - @Test - public void shouldDeriveLoanRepaymentScheduleWithTwoRepaymentPeriodAndOneSinglePayment() { - - List repaymentScheduleWithSinglePeriod = new ArrayList(); - - LoanRepaymentScheduleInstallment firstRepaymentPeriod = new LoanRepaymentScheduleInstallmentBuilder(cfaCurrency) - .withPrincipal("1000") - .withInterest("10") - .withDueDate(LocalDate.now()) - .build(); - - LoanRepaymentScheduleInstallment secondRepaymentPeriod = new LoanRepaymentScheduleInstallmentBuilder(cfaCurrency) - .withPrincipal("1000") - .withInterest("10") - .withDueDate(LocalDate.now().plusWeeks(1)) - .build(); - - repaymentScheduleWithSinglePeriod.add(firstRepaymentPeriod); - repaymentScheduleWithSinglePeriod.add(secondRepaymentPeriod); - - List singleRepayment = new ArrayList(); - - Money partialAmount = new MoneyBuilder().with(cfaCurrency).with("1200").build(); - - LoanTransaction overRepaymentForFirstPeriod = new LoanTransactionBuilder().with(partialAmount).build(); - singleRepayment.add(overRepaymentForFirstPeriod); - - // exercise test - DerivedLoanData derivedData = loanDataProcessor.process(repaymentScheduleWithSinglePeriod, singleRepayment, asCurrencyData(cfaCurrency), arrearsTolerance); - - // verification - assertThat(derivedData, is(notNullValue())); - - LoanRepaymentScheduleData repaymentSchedule = derivedData.getRepaymentSchedule(); - assertThat(repaymentSchedule, is(notNullValue())); - - List periods = repaymentSchedule.getPeriods(); - assertThat(periods, is(notNullValue())); - assertThat(periods.size(), is(2)); - - LoanRepaymentPeriodData firstPeriod = periods.get(0); - - MoneyData expectedPrincipal = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("1000").build()); - MoneyData expectedPrincipalPaid = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("1000").build()); - MoneyData expectedPrincipalOutstanding = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("0").build()); - MoneyData expectedInterest = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("10").build()); - MoneyData expectedInterestPaid = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("10").build()); - MoneyData expectedInterestOutstanding = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("0").build()); - - assertThat(firstPeriod.getPrincipal(), is(expectedPrincipal)); - assertThat(firstPeriod.getPrincipalPaid(), is(expectedPrincipalPaid)); - assertThat(firstPeriod.getPrincipalOutstanding(), is(expectedPrincipalOutstanding)); - - assertThat(firstPeriod.getInterest(), is(expectedInterest)); - assertThat(firstPeriod.getInterestPaid(), is(expectedInterestPaid)); - assertThat(firstPeriod.getInterestOutstanding(), is(expectedInterestOutstanding)); - - LoanRepaymentPeriodData secondPeriod = periods.get(1); - - expectedPrincipal = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("1000").build()); - expectedPrincipalPaid = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("180").build()); - expectedPrincipalOutstanding = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("820").build()); - expectedInterest = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("10").build()); - expectedInterestPaid = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("10").build()); - expectedInterestOutstanding = moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("0").build()); - - assertThat(secondPeriod.getPrincipal(), is(expectedPrincipal)); - assertThat(secondPeriod.getPrincipalPaid(), is(expectedPrincipalPaid)); - assertThat(secondPeriod.getPrincipalOutstanding(), is(expectedPrincipalOutstanding)); - - assertThat(secondPeriod.getInterest(), is(expectedInterest)); - assertThat(secondPeriod.getInterestPaid(), is(expectedInterestPaid)); - assertThat(secondPeriod.getInterestOutstanding(), is(expectedInterestOutstanding)); - - // assert repayments are ok - List loanRepayments = derivedData.getLoanRepayments(); - assertThat(loanRepayments, is(notNullValue())); - assertThat(loanRepayments.size(), is(1)); - - LoanTransactionData firstRepayment = loanRepayments.get(0); - assertThat(firstRepayment.getPrincipal(), is(moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("1180").build()))); - assertThat(firstRepayment.getInterest(), is(moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("20").build()))); - assertThat(firstRepayment.getTotal(), is(moneyDataFrom(new MoneyBuilder().with(cfaCurrency).with("1200").build()))); - } - - private MoneyData moneyDataFrom(Money money) { - CurrencyData currency = new CurrencyData(money.getCurrencyCode(), "", money.getCurrencyDigitsAfterDecimal(), "CFA", ""); - return MoneyData.of(currency, money.getAmount()); - } -} \ No newline at end of file