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.

This commit is contained in:
Keith Woodlock
2012-09-14 16:10:16 +01:00
parent 4717393816
commit e4f8eb6b12
8 changed files with 209 additions and 564 deletions
@@ -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<StaffData> 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<LoanRepaymentTransactionData> loanRepayments = null;
Collection<LoanRepaymentPeriodData> repaymentSchedule = null;
LoanAccountSummaryData summary = null;
LoanScheduleData repaymentSchedule = null;
LoanPermissionData permissions = null;
Collection<ChargeData> charges = null;
boolean convenienceDataRequired = false;
Set<String> associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters());
final Set<String> 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);
@@ -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<LoanRepaymentPeriodData> repaymentSchedule;
private final LoanScheduleData repaymentSchedule;
private final Collection<LoanRepaymentTransactionData> loanRepayments;
private final Collection<ChargeData> charges;
private final LoanPermissionData permissions;
private final LoanConvenienceData convenienceData;
// template
@SuppressWarnings("unused")
private final Collection<StaffData> loanOfficerOptions;
private final Collection<LoanProductLookup> productOptions;
private final Collection<EnumOptionData> termFrequencyTypeOptions;
@@ -70,14 +70,12 @@ public class LoanAccountData {
private final Collection<EnumOptionData> interestCalculationPeriodTypeOptions;
private final Collection<FundData> fundOptions;
private final Collection<ChargeData> chargeOptions;
@SuppressWarnings("unused")
private final ChargeData chargeTemplate;
public LoanAccountData(
final LoanBasicDetailsData basicDetails,
final boolean convenienceDataRequired,
final LoanAccountSummaryData summary,
final Collection<LoanRepaymentPeriodData> repaymentSchedule,
final LoanScheduleData repaymentSchedule,
final Collection<LoanRepaymentTransactionData> loanRepayments,
final LoanPermissionData permissions,
final Collection<ChargeData> charges,
@@ -93,7 +91,6 @@ public class LoanAccountData {
final Collection<ChargeData> chargeOptions,
final ChargeData chargeTemplate,
final Collection<StaffData> 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<LoanRepaymentPeriodData> getRepaymentSchedule() {
return repaymentSchedule;
}
public Collection<LoanRepaymentTransactionData> getLoanRepayments() {
return loanRepayments;
}
public LoanPermissionData getPermissions() {
return permissions;
}
public LoanConvenienceData getConvenienceData() {
return convenienceData;
}
public Collection<ChargeData> getCharges() {
return this.charges;
}
public Collection<LoanProductLookup> getProductOptions() {
return productOptions;
}
public Collection<EnumOptionData> getTermFrequencyTypeOptions() {
return termFrequencyTypeOptions;
}
public Collection<EnumOptionData> getRepaymentFrequencyTypeOptions() {
return repaymentFrequencyTypeOptions;
}
public Collection<TransactionProcessingStrategyData> getRepaymentStrategyOptions() {
return repaymentStrategyOptions;
}
public Collection<EnumOptionData> getInterestRateFrequencyTypeOptions() {
return interestRateFrequencyTypeOptions;
}
public Collection<EnumOptionData> getAmortizationTypeOptions() {
return amortizationTypeOptions;
}
public Collection<EnumOptionData> getInterestTypeOptions() {
return interestTypeOptions;
}
public Collection<EnumOptionData> getInterestCalculationPeriodTypeOptions() {
return interestCalculationPeriodTypeOptions;
}
public Collection<FundData> getFundOptions() {
return fundOptions;
}
public Collection<ChargeData> getChargeOptions() {
return chargeOptions;
}
public Long getLoanOfficerId() {
return loanOfficerId;
}
public String getLoanOfficerName() {
return loanOfficerName;
}
}
@@ -2,38 +2,45 @@ package org.mifosng.platform.api.data;
import java.math.BigDecimal;
/**
* Immutable data object representing summary information of loan.
*
* <code>currency</code> 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;
}
}
@@ -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;
}
}
@@ -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<LoanRepaymentPeriodData> repaymentPeriods;
public LoanScheduleData(final CurrencyData currency, final Collection<LoanRepaymentPeriodData> repaymentPeriods, final Collection<LoanRepaymentTransactionData> loanRepayments) {
this.summary = derivedSummaryFrom(currency, repaymentPeriods, loanRepayments);
this.currency = currency;
this.repaymentPeriods = repaymentPeriods;
}
private LoanAccountSummaryData derivedSummaryFrom(
final CurrencyData currency,
final Collection<LoanRepaymentPeriodData> repaymentSchedule,
final Collection<LoanRepaymentTransactionData> 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();
}
}
@@ -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",
@@ -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<LoanRepaymentPeriodData> retrieveRepaymentSchedule(Long loanId);
LoanScheduleData retrieveRepaymentSchedule(Long loanId, CurrencyData currencyData, Collection<LoanRepaymentTransactionData> loanRepayments);
Collection<LoanRepaymentTransactionData> retrieveLoanPayments(Long loanId);
LoanAccountSummaryData retrieveSummary(CurrencyData currency,
Collection<LoanRepaymentPeriodData> repaymentSchedule,
Collection<LoanRepaymentTransactionData> loanRepayments);
LoanPermissionData retrieveLoanPermissions(
LoanBasicDetailsData loanBasicDetails, boolean isWaiverAllowed,
int repaymentAndWaiveCount);
@@ -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<LoanRepaymentPeriodData> retrieveRepaymentSchedule(
Long loanId) {
public LoanScheduleData retrieveRepaymentSchedule(final Long loanId, final CurrencyData currency, final Collection<LoanRepaymentTransactionData> 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<LoanRepaymentPeriodData> 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<LoanRepaymentPeriodData> repaymentSchedule,
final Collection<LoanRepaymentTransactionData> 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<LoanRepaymentTransactionData> 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,