From e4f8eb6b12ebc1d065be516c57252b7f2266c449 Mon Sep 17 00:00:00 2001 From: Keith Woodlock Date: Fri, 14 Sep 2012 16:10:16 +0100 Subject: [PATCH] mifosx-58: restructure loan schedule to contain summary plus detail of schedule. As part of this work I removed the use of MoneyData in data objects and instead return currency and decimal for each monetary amount aligning with rest of application. --- .../platform/api/LoansApiResource.java | 25 +- .../platform/api/data/LoanAccountData.java | 219 +----------------- .../api/data/LoanAccountSummaryData.java | 164 +++---------- .../api/data/LoanRepaymentPeriodData.java | 136 +++-------- .../platform/api/data/LoanScheduleData.java | 94 ++++++++ .../GoogleGsonApiJsonSerializerService.java | 2 +- .../loan/service/LoanReadPlatformService.java | 9 +- .../service/LoanReadPlatformServiceImpl.java | 124 ++-------- 8 files changed, 209 insertions(+), 564 deletions(-) create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanScheduleData.java 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 f37cbcd60..5483af5e9 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 @@ -32,14 +32,14 @@ import org.mifosng.platform.api.data.EntityIdentifier; import org.mifosng.platform.api.data.EnumOptionData; import org.mifosng.platform.api.data.FundData; 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.LoanProductLookup; -import org.mifosng.platform.api.data.LoanRepaymentPeriodData; import org.mifosng.platform.api.data.LoanRepaymentTransactionData; import org.mifosng.platform.api.data.LoanSchedule; +import org.mifosng.platform.api.data.LoanScheduleData; import org.mifosng.platform.api.data.LoanTransactionData; +import org.mifosng.platform.api.data.MoneyData; import org.mifosng.platform.api.data.StaffData; import org.mifosng.platform.api.data.TransactionProcessingStrategyData; import org.mifosng.platform.api.infrastructure.ApiDataConversionService; @@ -159,7 +159,7 @@ public class LoansApiResource { // populate loan officers if query param is passed in Collection allowedLoanOfficers = this.staffReadPlatformService.retrieveAllLoanOfficersByOffice(loanBasicDetails.getClientOfficeId()); - final LoanAccountData newLoanAccount = new LoanAccountData(loanBasicDetails, convenienceDataRequired, null, null, null, null, charges, + final LoanAccountData newLoanAccount = new LoanAccountData(loanBasicDetails, convenienceDataRequired, null, null, null, charges, productOptions, loanTermFrequencyTypeOptions, repaymentFrequencyTypeOptions, repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, allowedLoanOfficers); @@ -196,16 +196,15 @@ public class LoansApiResource { int loanRepaymentsCount = 0; Collection loanRepayments = null; - Collection repaymentSchedule = null; - LoanAccountSummaryData summary = null; + LoanScheduleData repaymentSchedule = null; LoanPermissionData permissions = null; Collection charges = null; boolean convenienceDataRequired = false; - Set associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters()); + final Set associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters()); if (!associationParameters.isEmpty()) { if (associationParameters.contains("all")) { - responseParameters.addAll(Arrays.asList("summary", "repaymentSchedule", "loanRepayments", "permissions", "convenienceData", "charges")); + responseParameters.addAll(Arrays.asList("repaymentSchedule", "loanRepayments", "permissions", "convenienceData", "charges")); } else { responseParameters.addAll(associationParameters); } @@ -215,11 +214,12 @@ public class LoansApiResource { loanRepayments = currentLoanRepayments; loanRepaymentsCount = loanRepayments.size(); } - repaymentSchedule = this.loanReadPlatformService.retrieveRepaymentSchedule(loanId); + repaymentSchedule = this.loanReadPlatformService.retrieveRepaymentSchedule(loanId, loanBasicDetails.getCurrency(), loanRepayments); - summary = this.loanReadPlatformService.retrieveSummary(loanBasicDetails.getCurrency(), repaymentSchedule, loanRepayments); - - boolean isWaiveAllowed = summary.isWaiveAllowed(loanBasicDetails.getCurrency(), 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; @@ -270,7 +270,8 @@ public class LoansApiResource { chargeTemplate = this.chargeReadPlatformService.retrieveLoanChargeTemplate(); } - final LoanAccountData loanAccount = new LoanAccountData(loanBasicDetails, convenienceDataRequired, summary, repaymentSchedule, loanRepayments, permissions, charges, + final LoanAccountData loanAccount = new LoanAccountData(loanBasicDetails, convenienceDataRequired, + repaymentSchedule, loanRepayments, permissions, charges, productOptions, loanTermFrequencyTypeOptions, repaymentFrequencyTypeOptions, repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, allowedLoanOfficers); 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 464beafd2..108a3d8d7 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 @@ -8,8 +8,10 @@ import org.joda.time.LocalDate; /** * Immutable data object representing loan account data. */ +@SuppressWarnings("unused") public class LoanAccountData { + // basic loan details private final Long id; private final String externalId; private final Long clientId; @@ -50,15 +52,13 @@ public class LoanAccountData { private final LocalDate lifeCycleStatusDate; // associations - private final LoanAccountSummaryData summary; - private final Collection repaymentSchedule; + private final LoanScheduleData repaymentSchedule; private final Collection loanRepayments; private final Collection charges; private final LoanPermissionData permissions; private final LoanConvenienceData convenienceData; // template - @SuppressWarnings("unused") private final Collection loanOfficerOptions; private final Collection productOptions; private final Collection termFrequencyTypeOptions; @@ -70,14 +70,12 @@ public class LoanAccountData { private final Collection interestCalculationPeriodTypeOptions; private final Collection fundOptions; private final Collection chargeOptions; - @SuppressWarnings("unused") private final ChargeData chargeTemplate; public LoanAccountData( final LoanBasicDetailsData basicDetails, final boolean convenienceDataRequired, - final LoanAccountSummaryData summary, - final Collection repaymentSchedule, + final LoanScheduleData repaymentSchedule, final Collection loanRepayments, final LoanPermissionData permissions, final Collection charges, @@ -93,7 +91,6 @@ public class LoanAccountData { final Collection chargeOptions, final ChargeData chargeTemplate, final Collection loanOfficerOptions) { - this.summary = summary; this.repaymentSchedule = repaymentSchedule; this.loanRepayments = loanRepayments; this.permissions = permissions; @@ -177,212 +174,4 @@ public class LoanAccountData { this.status = basicDetails.getStatus(); this.lifeCycleStatusDate = basicDetails.getLifeCycleStatusDate(); } - - public Long getId() { - return id; - } - - public String getExternalId() { - return externalId; - } - - public Long getClientId() { - return clientId; - } - - public String getClientName() { - return clientName; - } - - public Long getLoanProductId() { - return loanProductId; - } - - public String getLoanProductName() { - return loanProductName; - } - - public String getLoanProductDescription() { - return loanProductDescription; - } - - public EnumOptionData getStatus() { - return status; - } - - public Long getFundId() { - return fundId; - } - - public String getFundName() { - return fundName; - } - - public LocalDate getSubmittedOnDate() { - return submittedOnDate; - } - - public LocalDate getApprovedOnDate() { - return approvedOnDate; - } - - public LocalDate getExpectedDisbursementDate() { - return expectedDisbursementDate; - } - - public LocalDate getActualDisbursementDate() { - return actualDisbursementDate; - } - - public LocalDate getRepaymentsStartingFromDate() { - return repaymentsStartingFromDate; - } - - public LocalDate getInterestChargedFromDate() { - return interestChargedFromDate; - } - - public LocalDate getClosedOnDate() { - return closedOnDate; - } - - public LocalDate getExpectedMaturityDate() { - return expectedMaturityDate; - } - - public CurrencyData getCurrency() { - return currency; - } - - public BigDecimal getPrincipal() { - return this.principal; - } - - public BigDecimal getInArrearsTolerance() { - return this.inArrearsTolerance; - } - - public Integer getTermFrequency() { - return termFrequency; - } - - public EnumOptionData getTermPeriodFrequencyType() { - return termPeriodFrequencyType; - } - - public Integer getNumberOfRepayments() { - return numberOfRepayments; - } - - public Integer getRepaymentEvery() { - return repaymentEvery; - } - - public Integer getTransactionStrategyId() { - return transactionStrategyId; - } - - public BigDecimal getInterestRatePerPeriod() { - return interestRatePerPeriod; - } - - public BigDecimal getAnnualInterestRate() { - return annualInterestRate; - } - - public EnumOptionData getRepaymentFrequencyType() { - return repaymentFrequencyType; - } - - public EnumOptionData getInterestRateFrequencyType() { - return interestRateFrequencyType; - } - - public EnumOptionData getAmortizationType() { - return amortizationType; - } - - public EnumOptionData getInterestType() { - return interestType; - } - - public EnumOptionData getInterestCalculationPeriodType() { - return interestCalculationPeriodType; - } - - public LocalDate getLifeCycleStatusDate() { - return lifeCycleStatusDate; - } - - public LoanAccountSummaryData getSummary() { - return summary; - } - - public Collection getRepaymentSchedule() { - return repaymentSchedule; - } - - public Collection getLoanRepayments() { - return loanRepayments; - } - - public LoanPermissionData getPermissions() { - return permissions; - } - - public LoanConvenienceData getConvenienceData() { - return convenienceData; - } - - public Collection getCharges() { - return this.charges; - } - - public Collection getProductOptions() { - return productOptions; - } - - public Collection getTermFrequencyTypeOptions() { - return termFrequencyTypeOptions; - } - - public Collection getRepaymentFrequencyTypeOptions() { - return repaymentFrequencyTypeOptions; - } - - public Collection getRepaymentStrategyOptions() { - return repaymentStrategyOptions; - } - - public Collection getInterestRateFrequencyTypeOptions() { - return interestRateFrequencyTypeOptions; - } - - public Collection getAmortizationTypeOptions() { - return amortizationTypeOptions; - } - - public Collection getInterestTypeOptions() { - return interestTypeOptions; - } - - public Collection getInterestCalculationPeriodTypeOptions() { - return interestCalculationPeriodTypeOptions; - } - - public Collection getFundOptions() { - return fundOptions; - } - - public Collection getChargeOptions() { - return chargeOptions; - } - - public Long getLoanOfficerId() { - return loanOfficerId; - } - - public String getLoanOfficerName() { - return loanOfficerName; - } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanAccountSummaryData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanAccountSummaryData.java index bc15d6e59..4ece0c3f4 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanAccountSummaryData.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanAccountSummaryData.java @@ -2,38 +2,45 @@ package org.mifosng.platform.api.data; import java.math.BigDecimal; +/** + * Immutable data object representing summary information of loan. + * + * currency is provided in summary even though its also passed with basic loan information so its possible to just request summary only. + * + * Note: getter/setter not added on purpose - google-gson only requires fields to generate json. + */ +@SuppressWarnings("unused") public class LoanAccountSummaryData { - private MoneyData originalPrincipal; - private MoneyData originalInterest; - private MoneyData originalTotal; - private MoneyData principalPaid; - private MoneyData principalOutstanding; - private MoneyData interestPaid; - private MoneyData interestWaived; - private MoneyData interestOutstanding; - private MoneyData totalPaid; - private MoneyData totalWaived; - private MoneyData totalOutstanding; - private MoneyData totalInArrears; - - protected LoanAccountSummaryData() { - // - } + private final CurrencyData currency; + private final BigDecimal originalPrincipal; + private final BigDecimal originalInterest; + private final BigDecimal originalTotal; + private final BigDecimal principalPaid; + private final BigDecimal principalOutstanding; + private final BigDecimal interestPaid; + private final BigDecimal interestWaived; + private final BigDecimal interestOutstanding; + private final BigDecimal totalPaid; + private final BigDecimal totalWaived; + private final BigDecimal totalOutstanding; + private final BigDecimal totalInArrears; public LoanAccountSummaryData( - MoneyData originalPrincipal, - MoneyData principalPaid, - MoneyData principalOutstanding, - MoneyData originalInterest, - MoneyData interestPaid, - MoneyData interestWaived, - MoneyData interestOutstanding, - MoneyData originalTotal, - MoneyData totalPaid, - MoneyData totalWaived, - MoneyData totalOutstanding, - MoneyData totalInArrears) { + final CurrencyData currency, + final BigDecimal originalPrincipal, + final BigDecimal principalPaid, + final BigDecimal principalOutstanding, + final BigDecimal originalInterest, + final BigDecimal interestPaid, + final BigDecimal interestWaived, + final BigDecimal interestOutstanding, + final BigDecimal originalTotal, + final BigDecimal totalPaid, + final BigDecimal totalWaived, + final BigDecimal totalOutstanding, + final BigDecimal totalInArrears) { + this.currency = currency; this.originalPrincipal = originalPrincipal; this.principalPaid = principalPaid; this.principalOutstanding = principalOutstanding; @@ -48,104 +55,7 @@ public class LoanAccountSummaryData { this.totalInArrears = totalInArrears; } - public boolean isWaiveAllowed(final CurrencyData currency, final BigDecimal toleranceAmount) { - MoneyData tolerance = MoneyData.of(currency, toleranceAmount); - return this.totalOutstanding.isGreaterThanZero() && (tolerance.isGreaterThan(this.totalOutstanding) || tolerance.isEqualTo(this.totalOutstanding)); - } - - public MoneyData getOriginalPrincipal() { - return originalPrincipal; - } - - public void setOriginalPrincipal(MoneyData originalPrincipal) { - this.originalPrincipal = originalPrincipal; - } - - public MoneyData getOriginalInterest() { - return originalInterest; - } - - public void setOriginalInterest(MoneyData originalInterest) { - this.originalInterest = originalInterest; - } - - public MoneyData getOriginalTotal() { - return originalTotal; - } - - public void setOriginalTotal(MoneyData originalTotal) { - this.originalTotal = originalTotal; - } - - 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 getInterestPaid() { - return interestPaid; - } - - public void setInterestPaid(MoneyData interestPaid) { - this.interestPaid = interestPaid; - } - - public MoneyData getInterestWaived() { - return interestWaived; - } - - public void setInterestWaived(MoneyData interestWaived) { - this.interestWaived = interestWaived; - } - - public MoneyData getInterestOutstanding() { - return interestOutstanding; - } - - public void setInterestOutstanding(MoneyData interestOutstanding) { - this.interestOutstanding = interestOutstanding; - } - - public MoneyData getTotalPaid() { - return totalPaid; - } - - public void setTotalPaid(MoneyData totalPaid) { - this.totalPaid = totalPaid; - } - - public MoneyData getTotalWaived() { - return totalWaived; - } - - public void setTotalWaived(MoneyData totalWaived) { - this.totalWaived = totalWaived; - } - - public MoneyData getTotalOutstanding() { - return totalOutstanding; - } - - public void setTotalOutstanding(MoneyData totalOutstanding) { - this.totalOutstanding = totalOutstanding; - } - - public MoneyData getTotalInArrears() { - return totalInArrears; - } - - public void setTotalInArrears(MoneyData totalInArrears) { - this.totalInArrears = totalInArrears; + public BigDecimal totalOutstanding() { + return this.totalOutstanding; } } \ No newline at end of file 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 24d5fdd27..637176333 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 @@ -1,33 +1,36 @@ package org.mifosng.platform.api.data; +import java.math.BigDecimal; + import org.joda.time.LocalDate; +/** + * Immutable data object representing a repayment period of a loan schedule. + */ public class LoanRepaymentPeriodData { - 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 interestWaived; - private MoneyData interestOutstanding; - private MoneyData total; - private MoneyData totalPaid; - private MoneyData totalWaived; - private MoneyData totalOutstanding; + @SuppressWarnings("unused") + private final Long loanId; + @SuppressWarnings("unused") + private final Integer period; + private final LocalDate date; + private final BigDecimal principal; + private final BigDecimal principalPaid; + private final BigDecimal principalOutstanding; + private final BigDecimal interest; + private final BigDecimal interestPaid; + private final BigDecimal interestWaived; + private final BigDecimal interestOutstanding; + private final BigDecimal total; + private final BigDecimal totalPaid; + private final BigDecimal totalWaived; + private final BigDecimal totalOutstanding; - public LoanRepaymentPeriodData() { - // - } - - public LoanRepaymentPeriodData(Long loanId, Integer period, - LocalDate date, MoneyData principal, MoneyData principalPaid, - MoneyData principalOutstanding, MoneyData interest, - MoneyData interestPaid, MoneyData interestWaived, MoneyData interestOutstanding, - MoneyData total, MoneyData totalPaid, MoneyData totalWaived, MoneyData totalOutstanding) { + public LoanRepaymentPeriodData(final Long loanId, final Integer period, + final LocalDate date, final BigDecimal principal, final BigDecimal principalPaid, + final BigDecimal principalOutstanding, final BigDecimal interest, + final BigDecimal interestPaid, final BigDecimal interestWaived, final BigDecimal interestOutstanding, + final BigDecimal total, final BigDecimal totalPaid, final BigDecimal totalWaived, final BigDecimal totalOutstanding) { this.loanId = loanId; this.period = period; this.date = date; @@ -44,116 +47,51 @@ public class LoanRepaymentPeriodData { 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() { + public BigDecimal getPrincipal() { return principal; } - public void setPrincipal(MoneyData principal) { - this.principal = principal; - } - - public MoneyData getPrincipalPaid() { + public BigDecimal getPrincipalPaid() { return principalPaid; } - public void setPrincipalPaid(MoneyData principalPaid) { - this.principalPaid = principalPaid; - } - - public MoneyData getPrincipalOutstanding() { + public BigDecimal getPrincipalOutstanding() { return principalOutstanding; } - public void setPrincipalOutstanding(MoneyData principalOutstanding) { - this.principalOutstanding = principalOutstanding; - } - - public MoneyData getInterest() { + public BigDecimal getInterest() { return interest; } - public void setInterest(MoneyData interest) { - this.interest = interest; - } - - public MoneyData getInterestPaid() { + public BigDecimal getInterestPaid() { return interestPaid; } - public void setInterestPaid(MoneyData interestPaid) { - this.interestPaid = interestPaid; - } - - public MoneyData getInterestWaived() { + public BigDecimal getInterestWaived() { return interestWaived; } - public void setInterestWaived(MoneyData interestWaived) { - this.interestWaived = interestWaived; - } - - public MoneyData getInterestOutstanding() { + public BigDecimal getInterestOutstanding() { return interestOutstanding; } - public void setInterestOutstanding(MoneyData interestOutstanding) { - this.interestOutstanding = interestOutstanding; - } - - public MoneyData getTotal() { + public BigDecimal getTotal() { return total; } - public void setTotal(MoneyData total) { - this.total = total; - } - - public MoneyData getTotalPaid() { + public BigDecimal getTotalPaid() { return totalPaid; } - public void setTotalPaid(MoneyData totalPaid) { - this.totalPaid = totalPaid; - } - - public MoneyData getTotalWaived() { + public BigDecimal getTotalWaived() { return totalWaived; } - public void setTotalWaived(MoneyData totalWaived) { - this.totalWaived = totalWaived; - } - - public MoneyData getTotalOutstanding() { + public BigDecimal 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/LoanScheduleData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanScheduleData.java new file mode 100644 index 000000000..766471f39 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/LoanScheduleData.java @@ -0,0 +1,94 @@ +package org.mifosng.platform.api.data; + +import java.math.BigDecimal; +import java.util.Collection; + +import org.joda.time.LocalDate; + +/** + * Immutable data object representing the expected disbursement and repayment schedule for the loan. + */ +public class LoanScheduleData { + + private final LoanAccountSummaryData summary; + @SuppressWarnings("unused") + private final CurrencyData currency; + @SuppressWarnings("unused") + private final Collection repaymentPeriods; + + public LoanScheduleData(final CurrencyData currency, final Collection repaymentPeriods, final Collection loanRepayments) { + this.summary = derivedSummaryFrom(currency, repaymentPeriods, loanRepayments); + this.currency = currency; + this.repaymentPeriods = repaymentPeriods; + } + + private LoanAccountSummaryData derivedSummaryFrom( + final CurrencyData currency, + final Collection repaymentSchedule, + final Collection loanRepayments) { + + BigDecimal originalPrincipal = BigDecimal.ZERO; + BigDecimal principalPaid = BigDecimal.ZERO; + BigDecimal principalOutstanding = BigDecimal.ZERO; + BigDecimal originalInterest = BigDecimal.ZERO; + BigDecimal interestPaid = BigDecimal.ZERO; + BigDecimal interestWaived = BigDecimal.ZERO; + BigDecimal interestOutstanding = BigDecimal.ZERO; + BigDecimal originalTotal = BigDecimal.ZERO; + BigDecimal totalPaid = BigDecimal.ZERO; + BigDecimal totalWaived = BigDecimal.ZERO; + BigDecimal totalOutstanding = BigDecimal.ZERO; + + BigDecimal totalInArrears = BigDecimal.ZERO; + + for (LoanRepaymentPeriodData installment : repaymentSchedule) { + originalPrincipal = originalPrincipal.add(installment.getPrincipal()); + principalPaid = principalPaid.add(installment.getPrincipalPaid()); + principalOutstanding = principalOutstanding.add(installment.getPrincipalOutstanding()); + + originalInterest = originalInterest.add(installment.getInterest()); + interestPaid = interestPaid.add(installment.getInterestPaid()); + interestWaived = interestWaived.add(installment.getInterestWaived()); + interestOutstanding = interestOutstanding.add(installment.getInterestOutstanding()); + + originalTotal = originalTotal.add(installment.getTotal()); + totalPaid = totalPaid.add(installment.getTotalPaid()); + totalWaived = totalWaived.add(installment.getTotalWaived()); + totalOutstanding = totalOutstanding.add(installment.getTotalOutstanding()); + + if (installment.getDate().isBefore(new LocalDate())) { + totalInArrears = totalInArrears.add(installment.getTotalOutstanding()); + } + } + + // sum up all repayment transactions + Long waiverType = (long) 4; + MoneyData totalRepaymentAmount = MoneyData.of(currency,BigDecimal.ZERO); + if (loanRepayments != null) { + for (LoanRepaymentTransactionData loanRepayment : loanRepayments) { + Long transactionType = loanRepayment.getTransactionType().getId(); + if (transactionType.equals(waiverType)) { + // skip + } else { + totalRepaymentAmount = totalRepaymentAmount.plus(loanRepayment.getTotal()); + } + } + } + + // detect if loan is in overpaid state + if (totalRepaymentAmount.isGreaterThan(MoneyData.of(currency, totalPaid))) { + BigDecimal difference = totalRepaymentAmount.getAmount().subtract(totalPaid); + totalOutstanding = totalOutstanding.subtract(difference); + } + + return new LoanAccountSummaryData(currency, originalPrincipal, + principalPaid, principalOutstanding, originalInterest, + interestPaid, interestWaived, interestOutstanding, + originalTotal, totalPaid, totalWaived, totalOutstanding, + totalInArrears); + } + + public BigDecimal totalOutstanding() { + return this.summary.totalOutstanding(); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonApiJsonSerializerService.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonApiJsonSerializerService.java index eb5de371a..b4331461d 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonApiJsonSerializerService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonApiJsonSerializerService.java @@ -147,7 +147,7 @@ public class GoogleGsonApiJsonSerializerService implements ApiJsonSerializerServ "expectedFirstRepaymentOnDate", "interestChargedFromDate", "closedOnDate", "expectedMaturityDate", "status", - "lifeCycleStatusDate", "summary", "repaymentSchedule", + "lifeCycleStatusDate", "repaymentSchedule", "loanRepayments", "permissions", "convenienceData", "charges", "productOptions", "amortizationTypeOptions", "interestTypeOptions", "interestCalculationPeriodTypeOptions", "repaymentFrequencyTypeOptions", "interestRateFrequencyTypeOptions", "fundOptions", "repaymentStrategyOptions", "chargeOptions", 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 db2f0dd13..2aa6bfd54 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 @@ -3,25 +3,20 @@ package org.mifosng.platform.loan.service; import java.util.Collection; import org.mifosng.platform.api.data.CurrencyData; -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.LoanRepaymentPeriodData; import org.mifosng.platform.api.data.LoanRepaymentTransactionData; +import org.mifosng.platform.api.data.LoanScheduleData; import org.mifosng.platform.api.data.LoanTransactionData; public interface LoanReadPlatformService { LoanBasicDetailsData retrieveLoanAccountDetails(Long loanId); - Collection retrieveRepaymentSchedule(Long loanId); + LoanScheduleData retrieveRepaymentSchedule(Long loanId, CurrencyData currencyData, Collection loanRepayments); Collection retrieveLoanPayments(Long loanId); - LoanAccountSummaryData retrieveSummary(CurrencyData currency, - Collection repaymentSchedule, - Collection loanRepayments); - LoanPermissionData retrieveLoanPermissions( LoanBasicDetailsData loanBasicDetails, boolean isWaiverAllowed, int repaymentAndWaiveCount); 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 19e529403..8519b256a 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 @@ -10,12 +10,12 @@ import org.mifosng.platform.api.data.ChargeData; import org.mifosng.platform.api.data.ClientData; import org.mifosng.platform.api.data.CurrencyData; import org.mifosng.platform.api.data.EnumOptionData; -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.LoanProductData; import org.mifosng.platform.api.data.LoanRepaymentPeriodData; import org.mifosng.platform.api.data.LoanRepaymentTransactionData; +import org.mifosng.platform.api.data.LoanScheduleData; import org.mifosng.platform.api.data.LoanTransactionData; import org.mifosng.platform.api.data.MoneyData; import org.mifosng.platform.client.service.ClientReadPlatformService; @@ -89,8 +89,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { } @Override - public Collection retrieveRepaymentSchedule( - Long loanId) { + public LoanScheduleData retrieveRepaymentSchedule(final Long loanId, final CurrencyData currency, final Collection loanRepayments) { try { context.authenticatedUser(); @@ -98,88 +97,14 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { LoanScheduleMapper rm = new LoanScheduleMapper(); String sql = "select " + rm.loanScheduleSchema() + " where l.id = ? order by ls.loan_id, ls.installment"; - return this.jdbcTemplate.query(sql, rm, new Object[] { loanId }); - + Collection repaymentSchedulePeriods = this.jdbcTemplate.query(sql, rm, new Object[] { loanId }); + + return new LoanScheduleData(currency, repaymentSchedulePeriods, loanRepayments); } catch (EmptyResultDataAccessException e) { throw new LoanNotFoundException(loanId); } } - @Override - public LoanAccountSummaryData retrieveSummary( - final CurrencyData currencyData, - final Collection repaymentSchedule, - final Collection loanRepayments) { - - BigDecimal originalPrincipal = BigDecimal.ZERO; - BigDecimal principalPaid = BigDecimal.ZERO; - BigDecimal principalOutstanding = BigDecimal.ZERO; - BigDecimal originalInterest = BigDecimal.ZERO; - BigDecimal interestPaid = BigDecimal.ZERO; - BigDecimal interestWaived = BigDecimal.ZERO; - BigDecimal interestOutstanding = BigDecimal.ZERO; - BigDecimal originalTotal = BigDecimal.ZERO; - BigDecimal totalPaid = BigDecimal.ZERO; - BigDecimal totalWaived = BigDecimal.ZERO; - BigDecimal totalOutstanding = BigDecimal.ZERO; - - BigDecimal totalInArrears = BigDecimal.ZERO; - - for (LoanRepaymentPeriodData installment : repaymentSchedule) { - originalPrincipal = originalPrincipal.add(installment.getPrincipal().getAmount()); - principalPaid = principalPaid.add(installment.getPrincipalPaid().getAmount()); - principalOutstanding = principalOutstanding.add(installment.getPrincipalOutstanding().getAmount()); - - originalInterest = originalInterest.add(installment.getInterest().getAmount()); - interestPaid = interestPaid.add(installment.getInterestPaid().getAmount()); - interestWaived = interestWaived.add(installment.getInterestWaived().getAmount()); - interestOutstanding = interestOutstanding.add(installment.getInterestOutstanding().getAmount()); - - originalTotal = originalTotal.add(installment.getTotal().getAmount()); - totalPaid = totalPaid.add(installment.getTotalPaid().getAmount()); - totalWaived = totalWaived.add(installment.getTotalWaived().getAmount()); - totalOutstanding = totalOutstanding.add(installment.getTotalOutstanding().getAmount()); - - if (installment.getDate().isBefore(new LocalDate())) { - totalInArrears = totalInArrears.add(installment.getTotalOutstanding().getAmount()); - } - } - - // sum up all repayment transactions - Long waiverType = (long) 4; - MoneyData totalRepaymentAmount = MoneyData.of(currencyData, BigDecimal.ZERO); - if (loanRepayments != null) { - for (LoanRepaymentTransactionData loanRepayment : loanRepayments) { - Long transactionType = loanRepayment.getTransactionType().getId(); - if (transactionType.equals(waiverType)) { - // skip - } else { - totalRepaymentAmount = totalRepaymentAmount.plus(loanRepayment.getTotal()); - } - } - } - - // detect if loan is in overpaid state - if (totalRepaymentAmount.isGreaterThan(MoneyData.of(currencyData, totalPaid))) { - BigDecimal difference = totalRepaymentAmount.getAmount().subtract(totalPaid); - totalOutstanding = totalOutstanding.subtract(difference); - } - - return new LoanAccountSummaryData( - MoneyData.of(currencyData,originalPrincipal), - MoneyData.of(currencyData, principalPaid), - MoneyData.of(currencyData, principalOutstanding), - MoneyData.of(currencyData, originalInterest), - MoneyData.of(currencyData, interestPaid), - MoneyData.of(currencyData, interestWaived), - MoneyData.of(currencyData, interestOutstanding), - MoneyData.of(currencyData, originalTotal), - MoneyData.of(currencyData, totalPaid), - MoneyData.of(currencyData, totalWaived), - MoneyData.of(currencyData, totalOutstanding), - MoneyData.of(currencyData, totalInArrears)); - } - @Override public Collection retrieveLoanPayments(Long loanId) { try { @@ -516,13 +441,12 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { public LoanRepaymentPeriodData mapRow(final ResultSet rs, final int rowNum) throws SQLException { + // FIXME - kw - currency not need per installment period any longer, just at loan schedule level. String currencyCode = rs.getString("currencyCode"); String currencyName = rs.getString("currencyName"); String currencyNameCode = rs.getString("currencyNameCode"); - String currencyDisplaySymbol = rs - .getString("currencyDisplaySymbol"); - Integer currencyDigits = JdbcSupport.getInteger(rs, - "currencyDigits"); + String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol"); + Integer currencyDigits = JdbcSupport.getInteger(rs,"currencyDigits"); CurrencyData currencyData = new CurrencyData(currencyCode, currencyName, currencyDigits, currencyDisplaySymbol, currencyNameCode); @@ -531,28 +455,22 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { Integer period = JdbcSupport.getInteger(rs, "period"); LocalDate date = JdbcSupport.getLocalDate(rs, "date"); - BigDecimal principalBD = rs.getBigDecimal("principal"); - MoneyData principal = MoneyData.of(currencyData, principalBD); - BigDecimal principalPaidBD = rs.getBigDecimal("principalPaid"); - MoneyData principalPaid = MoneyData.of(currencyData, principalPaidBD); - MoneyData principalOutstanding = MoneyData.of(currencyData,principalBD.subtract(principalPaidBD)); + BigDecimal principal = rs.getBigDecimal("principal"); + BigDecimal principalPaid = rs.getBigDecimal("principalPaid"); + BigDecimal principalOutstanding = principal.subtract(principalPaid); - BigDecimal interestBD = rs.getBigDecimal("interest"); - MoneyData interest = MoneyData.of(currencyData, interestBD); - BigDecimal interestPaidBD = rs.getBigDecimal("interestPaid"); - MoneyData interestPaid = MoneyData.of(currencyData, interestPaidBD); - - BigDecimal interestWaivedBD = rs.getBigDecimal("interestWaived"); - if (interestWaivedBD == null) { - interestWaivedBD = BigDecimal.ZERO; + BigDecimal interest = rs.getBigDecimal("interest"); + BigDecimal interestPaid = rs.getBigDecimal("interestPaid"); + BigDecimal interestWaived = rs.getBigDecimal("interestWaived"); + if (interestWaived == null) { + interestWaived = BigDecimal.ZERO; } - MoneyData interestWaived = MoneyData.of(currencyData, interestWaivedBD); - MoneyData interestOutstanding = MoneyData.of(currencyData, interestBD.subtract(interestPaidBD).subtract(interestWaivedBD)); + BigDecimal interestOutstanding = interest.subtract(interestPaid).subtract(interestWaived); - MoneyData total = MoneyData.of(currencyData,principalBD.add(interestBD)); - MoneyData totalPaid = principalPaid.plus(interestPaid); - MoneyData totalWaived = interestWaived; - MoneyData totalOutstanding = principalOutstanding.plus(interestOutstanding); + BigDecimal total = principal.add(interest); + BigDecimal totalPaid = principalPaid.add(interestPaid); + BigDecimal totalWaived = interestWaived; + BigDecimal totalOutstanding = principalOutstanding.add(interestOutstanding); return new LoanRepaymentPeriodData(loanId, period, date, principal, principalPaid, principalOutstanding, interest,