some fixes around transactions returned for loan account screens.

This commit is contained in:
Keith Woodlock
2012-07-20 23:59:29 +01:00
parent 3951fdc383
commit 676cb33d37
8 changed files with 68 additions and 36 deletions
@@ -30,7 +30,7 @@ import org.mifosng.platform.api.data.LoanPermissionData;
import org.mifosng.platform.api.data.LoanRepaymentPeriodData; import org.mifosng.platform.api.data.LoanRepaymentPeriodData;
import org.mifosng.platform.api.data.LoanSchedule; import org.mifosng.platform.api.data.LoanSchedule;
import org.mifosng.platform.api.data.LoanTransactionData; import org.mifosng.platform.api.data.LoanTransactionData;
import org.mifosng.platform.api.data.LoanTransactionDataDTO; import org.mifosng.platform.api.data.LoanRepaymentTransactionData;
import org.mifosng.platform.api.data.NewLoanData; import org.mifosng.platform.api.data.NewLoanData;
import org.mifosng.platform.api.infrastructure.ApiDataConversionService; import org.mifosng.platform.api.infrastructure.ApiDataConversionService;
import org.mifosng.platform.api.infrastructure.ApiJSONFormattingService; import org.mifosng.platform.api.infrastructure.ApiJSONFormattingService;
@@ -99,7 +99,7 @@ public class LoansApiResource {
LoanBasicDetailsData loanBasicDetails = this.loanReadPlatformService LoanBasicDetailsData loanBasicDetails = this.loanReadPlatformService
.retrieveLoanAccountDetails(loanId); .retrieveLoanAccountDetails(loanId);
Collection<LoanTransactionDataDTO> loanRepayments = this.loanReadPlatformService Collection<LoanRepaymentTransactionData> loanRepayments = this.loanReadPlatformService
.retrieveLoanPayments(loanId); .retrieveLoanPayments(loanId);
Collection<LoanRepaymentPeriodData> repaymentSchedule = this.loanReadPlatformService Collection<LoanRepaymentPeriodData> repaymentSchedule = this.loanReadPlatformService
.retrieveRepaymentSchedule(loanId); .retrieveRepaymentSchedule(loanId);
@@ -45,7 +45,7 @@ public class LoanAccountData {
private LoanAccountSummaryData summary; private LoanAccountSummaryData summary;
private Collection<LoanRepaymentPeriodData> repaymentSchedule; private Collection<LoanRepaymentPeriodData> repaymentSchedule;
private Collection<LoanTransactionDataDTO> loanRepayments; private Collection<LoanRepaymentTransactionData> loanRepayments;
private LoanPermissionData permissions; private LoanPermissionData permissions;
@@ -58,7 +58,7 @@ public class LoanAccountData {
public LoanAccountData(LoanBasicDetailsData basicDetails, public LoanAccountData(LoanBasicDetailsData basicDetails,
LoanAccountSummaryData summary, LoanAccountSummaryData summary,
Collection<LoanRepaymentPeriodData> repaymentSchedule, Collection<LoanRepaymentPeriodData> repaymentSchedule,
Collection<LoanTransactionDataDTO> loanRepayments, Collection<LoanRepaymentTransactionData> loanRepayments,
LoanPermissionData permissions) { LoanPermissionData permissions) {
this.summary = summary; this.summary = summary;
this.repaymentSchedule = repaymentSchedule; this.repaymentSchedule = repaymentSchedule;
@@ -150,12 +150,12 @@ public class LoanAccountData {
this.repaymentSchedule = repaymentSchedule; this.repaymentSchedule = repaymentSchedule;
} }
public Collection<LoanTransactionDataDTO> getLoanRepayments() { public Collection<LoanRepaymentTransactionData> getLoanRepayments() {
return loanRepayments; return loanRepayments;
} }
public void setLoanRepayments( public void setLoanRepayments(
Collection<LoanTransactionDataDTO> loanRepayments) { Collection<LoanRepaymentTransactionData> loanRepayments) {
this.loanRepayments = loanRepayments; this.loanRepayments = loanRepayments;
} }
@@ -2,18 +2,21 @@ package org.mifosng.platform.api.data;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
public class LoanTransactionDataDTO { /**
* This data object replaces {@link LoanTransactionData}.
*/
public class LoanRepaymentTransactionData {
private Long id; private Long id;
private EnumOptionData transactionType; private EnumOptionData transactionType;
private LocalDate date; private LocalDate date;
private MoneyData total; private MoneyData total;
public LoanTransactionDataDTO() { public LoanRepaymentTransactionData() {
// //
} }
public LoanTransactionDataDTO(Long id, EnumOptionData transactionType, public LoanRepaymentTransactionData(Long id, EnumOptionData transactionType,
final LocalDate date, final MoneyData total) { final LocalDate date, final MoneyData total) {
this.id = id; this.id = id;
this.transactionType = transactionType; this.transactionType = transactionType;
@@ -3,6 +3,10 @@ package org.mifosng.platform.api.data;
import org.codehaus.jackson.map.annotate.JsonFilter; import org.codehaus.jackson.map.annotate.JsonFilter;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
/**
* TODO - KW - Think this is deprecated now.
*/
@Deprecated
@JsonFilter("loanRepaymentFilter") @JsonFilter("loanRepaymentFilter")
public class LoanTransactionData { public class LoanTransactionData {
@@ -413,15 +413,31 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
} }
} }
public void makeRepayment(final LoanTransaction loanTransaction, public void makeRepayment(final LoanTransaction loanTransaction, final LoanLifecycleStateMachine loanLifecycleStateMachine) {
LoanLifecycleStateMachine loanLifecycleStateMachine) { this.loanStatus = loanLifecycleStateMachine.transition(LoanEvent.LOAN_REPAYMENT, this.loanStatus);
this.loanStatus = loanLifecycleStateMachine.transition(
LoanEvent.LOAN_REPAYMENT, this.loanStatus);
loanTransaction.updateLoan(this); loanTransaction.updateLoan(this);
this.loanTransactions.add(loanTransaction); this.loanTransactions.add(loanTransaction);
deriveLoanRepaymentScheduleCompletedData(); deriveLoanRepaymentScheduleCompletedData();
// Money totalRepaidOrWaived = Money.zero(this.loanRepaymentScheduleDetail.getPrincipal().getCurrency());
// MonetaryCurrency currency = totalRepaidOrWaived.getCurrency();
//
// int repaymentIndex = 0;
//
// for (LoanTransaction transaction : this.loanTransactions) {
// if (transaction.isRepayment() || transaction.isWaiver()) {
// totalRepaidOrWaived = totalRepaidOrWaived.plus(transaction.getAmount());
//
// LoanRepaymentScheduleInstallment currentInstallment = this.repaymentScheduleInstallments.get(repaymentIndex);
// if (currentInstallment.unpaid()) {
// currentInstallment.payOffWith(transaction, currency);
// } else {
// repaymentIndex++;
// }
// }
// }
if (loanTransaction.isNotRepayment()) { if (loanTransaction.isNotRepayment()) {
final String errorMessage = "A transaction of type repayment was expected but not received."; final String errorMessage = "A transaction of type repayment was expected but not received.";
throw new InvalidLoanTransactionTypeException("transaction", throw new InvalidLoanTransactionTypeException("transaction",
@@ -466,23 +482,18 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
Money totalRepaidOrWaivedAgainstLoan = calculateTotalPaidOrWaived(); Money totalRepaidOrWaivedAgainstLoan = calculateTotalPaidOrWaived();
Money remainingToPayoffAgainstLoanSchedule = totalRepaidOrWaivedAgainstLoan; Money remainingToPayoffAgainstLoanSchedule = totalRepaidOrWaivedAgainstLoan;
Money totalOverpaid = Money.zero(totalRepaidOrWaivedAgainstLoan Money totalOverpaid = Money.zero(totalRepaidOrWaivedAgainstLoan.getCurrency());
.getCurrency());
int repaymentInstallmentIndex = 0; int repaymentInstallmentIndex = 0;
while (remainingToPayoffAgainstLoanSchedule.isGreaterThanZero()) { while (remainingToPayoffAgainstLoanSchedule.isGreaterThanZero()) {
if (repaymentInstallmentIndex == this.repaymentScheduleInstallments if (repaymentInstallmentIndex == this.repaymentScheduleInstallments.size()) {
.size()) {
totalOverpaid = remainingToPayoffAgainstLoanSchedule; totalOverpaid = remainingToPayoffAgainstLoanSchedule;
// to exit while loop // to exit while loop
remainingToPayoffAgainstLoanSchedule = remainingToPayoffAgainstLoanSchedule remainingToPayoffAgainstLoanSchedule = remainingToPayoffAgainstLoanSchedule.minus(totalOverpaid);
.minus(totalOverpaid);
} else { } else {
LoanRepaymentScheduleInstallment scheduledRepaymentInstallment = this.repaymentScheduleInstallments LoanRepaymentScheduleInstallment scheduledRepaymentInstallment = this.repaymentScheduleInstallments.get(repaymentInstallmentIndex);
.get(repaymentInstallmentIndex); remainingToPayoffAgainstLoanSchedule = scheduledRepaymentInstallment.updateDerivedComponents(remainingToPayoffAgainstLoanSchedule);
remainingToPayoffAgainstLoanSchedule = scheduledRepaymentInstallment
.updateDerivedComponents(remainingToPayoffAgainstLoanSchedule);
repaymentInstallmentIndex++; repaymentInstallmentIndex++;
} }
} }
@@ -151,4 +151,18 @@ public class LoanRepaymentScheduleInstallment extends AbstractAuditableCustom<Ap
private Money getTotalCompleted(MonetaryCurrency currency) { private Money getTotalCompleted(MonetaryCurrency currency) {
return getPrincipalCompleted(currency).plus(getInterestCompleted(currency)); return getPrincipalCompleted(currency).plus(getInterestCompleted(currency));
} }
// public void payOffWith(final LoanTransaction transaction, final MonetaryCurrency currency) {
// Money transactionAmountRemaining = Money.of(currency, transaction.getAmount());
//
// Money interestDue = getInterest(currency);
// if (transactionAmountRemaining.isGreaterThanOrEqualTo(interestDue)) {
// this.interestCompleted = interestDue.getAmount();
// transactionAmountRemaining = transactionAmountRemaining.minus(interestDue);
// } else {
// this.interestCompleted = transactionAmountRemaining.getAmount();
// }
//
// Money principalDue = getPrincipal(currency);
// }
} }
@@ -7,7 +7,7 @@ import org.mifosng.platform.api.data.LoanBasicDetailsData;
import org.mifosng.platform.api.data.LoanPermissionData; import org.mifosng.platform.api.data.LoanPermissionData;
import org.mifosng.platform.api.data.LoanRepaymentPeriodData; import org.mifosng.platform.api.data.LoanRepaymentPeriodData;
import org.mifosng.platform.api.data.LoanTransactionData; import org.mifosng.platform.api.data.LoanTransactionData;
import org.mifosng.platform.api.data.LoanTransactionDataDTO; import org.mifosng.platform.api.data.LoanRepaymentTransactionData;
import org.mifosng.platform.api.data.MoneyData; import org.mifosng.platform.api.data.MoneyData;
import org.mifosng.platform.api.data.NewLoanData; import org.mifosng.platform.api.data.NewLoanData;
@@ -17,11 +17,11 @@ public interface LoanReadPlatformService {
Collection<LoanRepaymentPeriodData> retrieveRepaymentSchedule(Long loanId); Collection<LoanRepaymentPeriodData> retrieveRepaymentSchedule(Long loanId);
Collection<LoanTransactionDataDTO> retrieveLoanPayments(Long loanId); Collection<LoanRepaymentTransactionData> retrieveLoanPayments(Long loanId);
LoanAccountSummaryData retrieveSummary(MoneyData principal, LoanAccountSummaryData retrieveSummary(MoneyData principal,
Collection<LoanRepaymentPeriodData> repaymentSchedule, Collection<LoanRepaymentPeriodData> repaymentSchedule,
Collection<LoanTransactionDataDTO> loanRepayments); Collection<LoanRepaymentTransactionData> loanRepayments);
LoanPermissionData retrieveLoanPermissions( LoanPermissionData retrieveLoanPermissions(
LoanBasicDetailsData loanBasicDetails, boolean isWaiverAllowed, LoanBasicDetailsData loanBasicDetails, boolean isWaiverAllowed,
@@ -17,7 +17,7 @@ import org.mifosng.platform.api.data.LoanProductData;
import org.mifosng.platform.api.data.LoanProductLookup; import org.mifosng.platform.api.data.LoanProductLookup;
import org.mifosng.platform.api.data.LoanRepaymentPeriodData; import org.mifosng.platform.api.data.LoanRepaymentPeriodData;
import org.mifosng.platform.api.data.LoanTransactionData; import org.mifosng.platform.api.data.LoanTransactionData;
import org.mifosng.platform.api.data.LoanTransactionDataDTO; import org.mifosng.platform.api.data.LoanRepaymentTransactionData;
import org.mifosng.platform.api.data.MoneyData; import org.mifosng.platform.api.data.MoneyData;
import org.mifosng.platform.api.data.NewLoanData; import org.mifosng.platform.api.data.NewLoanData;
import org.mifosng.platform.client.service.ClientReadPlatformService; import org.mifosng.platform.client.service.ClientReadPlatformService;
@@ -110,7 +110,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
@Override @Override
public LoanAccountSummaryData retrieveSummary(MoneyData principal, public LoanAccountSummaryData retrieveSummary(MoneyData principal,
Collection<LoanRepaymentPeriodData> repaymentSchedule, Collection<LoanRepaymentPeriodData> repaymentSchedule,
Collection<LoanTransactionDataDTO> loanRepayments) { Collection<LoanRepaymentTransactionData> loanRepayments) {
CurrencyData currencyData = new CurrencyData( CurrencyData currencyData = new CurrencyData(
principal.getCurrencyCode(), principal.getDefaultName(), principal.getCurrencyCode(), principal.getDefaultName(),
@@ -157,7 +157,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
} }
Long waiverType = (long) 4; Long waiverType = (long) 4;
for (LoanTransactionDataDTO loanRepayment : loanRepayments) { for (LoanRepaymentTransactionData loanRepayment : loanRepayments) {
Long transactionType = loanRepayment.getTransactionType().getId(); Long transactionType = loanRepayment.getTransactionType().getId();
if (transactionType.equals(waiverType)) { if (transactionType.equals(waiverType)) {
totalWaived = totalWaived.add(loanRepayment.getTotal() totalWaived = totalWaived.add(loanRepayment.getTotal()
@@ -179,17 +179,17 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
} }
@Override @Override
public Collection<LoanTransactionDataDTO> retrieveLoanPayments(Long loanId) { public Collection<LoanRepaymentTransactionData> retrieveLoanPayments(Long loanId) {
try { try {
context.authenticatedUser(); context.authenticatedUser();
LoanPaymentsMapper rm = new LoanPaymentsMapper(); LoanPaymentsMapper rm = new LoanPaymentsMapper();
// retrieve all loan transactions that are not invalid (0) and not // retrieve all loan transactions that are not invalid (0) and not
// disbursements (1) // disbursements (1) and have not been 'contra'ed by another transaction
String sql = "select " String sql = "select "
+ rm.LoanPaymentsSchema() + rm.LoanPaymentsSchema()
+ " where tr.loan_id = ? and tr.transaction_type_enum not in (0, 1) order by tr.transaction_date"; + " where tr.loan_id = ? and tr.transaction_type_enum not in (0, 1) and tr.contra_id is null order by tr.transaction_date ASC";
return this.jdbcTemplate.query(sql, rm, new Object[] { loanId }); return this.jdbcTemplate.query(sql, rm, new Object[] { loanId });
} catch (EmptyResultDataAccessException e) { } catch (EmptyResultDataAccessException e) {
@@ -581,7 +581,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
} }
private static final class LoanPaymentsMapper implements private static final class LoanPaymentsMapper implements
RowMapper<LoanTransactionDataDTO> { RowMapper<LoanRepaymentTransactionData> {
public String LoanPaymentsSchema() { public String LoanPaymentsSchema() {
@@ -593,7 +593,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
} }
@Override @Override
public LoanTransactionDataDTO mapRow(final ResultSet rs, public LoanRepaymentTransactionData mapRow(final ResultSet rs,
final int rowNum) throws SQLException { final int rowNum) throws SQLException {
String currencyCode = rs.getString("currencyCode"); String currencyCode = rs.getString("currencyCode");
@@ -616,7 +616,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
BigDecimal totalBD = rs.getBigDecimal("total"); BigDecimal totalBD = rs.getBigDecimal("total");
MoneyData total = MoneyData.of(currencyData, totalBD); MoneyData total = MoneyData.of(currencyData, totalBD);
return new LoanTransactionDataDTO(id, transactionType, date, total); return new LoanRepaymentTransactionData(id, transactionType, date, total);
} }
} }