fix some issues with late payments and checks for isFullyRepaid or overpaid.

This commit is contained in:
Keith Woodlock
2012-07-28 01:47:58 +01:00
parent 89230969ea
commit 58b3a2cc3e
4 changed files with 19 additions and 12 deletions
@@ -47,7 +47,7 @@ public class LoanAccountSummaryData {
} }
public boolean isWaiveAllowed(MoneyData tolerance) { public boolean isWaiveAllowed(MoneyData tolerance) {
return tolerance.isGreaterThan(this.totalOutstanding) || tolerance.isEqualTo(this.totalOutstanding); return this.totalOutstanding.isGreaterThanZero() && (tolerance.isGreaterThan(this.totalOutstanding) || tolerance.isEqualTo(this.totalOutstanding));
} }
public MoneyData getOriginalPrincipal() { public MoneyData getOriginalPrincipal() {
@@ -54,7 +54,7 @@ public class DefaultLoanLifecycleStateMachine implements
} }
break; break;
case LOAN_REPAYMENT: case LOAN_REPAYMENT:
if (this.anyOfAllowedWhenComingFrom(from, LoanStatus.ACTIVE, LoanStatus.OVERPAID)) { if (this.anyOfAllowedWhenComingFrom(from, LoanStatus.ACTIVE, LoanStatus.CLOSED, LoanStatus.OVERPAID)) {
newState = stateOf(LoanStatus.ACTIVE, allowedLoanStatuses); newState = stateOf(LoanStatus.ACTIVE, allowedLoanStatuses);
} else { } else {
newState = from; newState = from;
@@ -46,7 +46,7 @@ public class DefaultLoanRepaymentScheduleTransactionProcessor implements LoanRep
transactionProcessed = true; transactionProcessed = true;
} else if (isTransactionLate(installmentIndex, installments, loanTransaction.getTransactionDate())) { } else if (isTransactionLate(installmentIndex, installments, loanTransaction.getTransactionDate())) {
// does this result in a late payment of existing installment? // does this result in a late payment of existing installment?
handleLateTransaction(installments, loanTransaction, currency); handleLateTransaction(currentInstallment, installments, loanTransaction, currency);
transactionProcessed = true; transactionProcessed = true;
} else { } else {
// standard transaction // standard transaction
@@ -65,14 +65,16 @@ public class DefaultLoanRepaymentScheduleTransactionProcessor implements LoanRep
/** /**
* Dont do anything special for late payments e.g. no fees, charges or penalties are applied * Dont do anything special for late payments e.g. no fees, charges or penalties are applied
* @param currentInstallment2
*/ */
protected void handleLateTransaction( protected void handleLateTransaction(
final LoanRepaymentScheduleInstallment currentInstallment,
final List<LoanRepaymentScheduleInstallment> installments, final List<LoanRepaymentScheduleInstallment> installments,
final LoanTransaction loanTransaction, final LoanTransaction loanTransaction,
final MonetaryCurrency currency) { final MonetaryCurrency currency) {
final Money lateRepayment = loanTransaction.getAmount(currency); Money installmentOverPaymentAmount = handleOnTimeTransaction(currentInstallment, loanTransaction, currency);
Money loanOverPaymentAmount = handleOverpaymentTransaction(installments, loanTransaction, currency, lateRepayment); Money loanOverPaymentAmount = handleOverpaymentTransaction(installments, loanTransaction, currency, installmentOverPaymentAmount);
if (loanOverPaymentAmount.isGreaterThanZero()) { if (loanOverPaymentAmount.isGreaterThanZero()) {
onLoanOverpayment(loanTransaction, currency, loanOverPaymentAmount); onLoanOverpayment(loanTransaction, currency, loanOverPaymentAmount);
} }
@@ -455,9 +455,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
if (this.isOverPaid()) { if (this.isOverPaid()) {
handleLoanOverpayment(loanTransaction, loanLifecycleStateMachine); handleLoanOverpayment(loanTransaction, loanLifecycleStateMachine);
} } else if (this.isRepaidInFull()) {
if (this.isRepaidInFull()) {
handleLoanRepaymentInFull(loanTransaction, loanLifecycleStateMachine); handleLoanRepaymentInFull(loanTransaction, loanLifecycleStateMachine);
} }
} }
@@ -567,18 +565,25 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
private boolean isRepaidInFull() { private boolean isRepaidInFull() {
MonetaryCurrency currency = loanCurrency(); MonetaryCurrency currency = loanCurrency();
Money cumulativeOriginalExpectedTotal = Money.zero(currency); Money cumulativeOriginalPrincipalExpected = Money.zero(currency);
Money cumulativeOriginalInterestExpected = Money.zero(currency);
Money cumulativeOriginalTotalExpected = Money.zero(currency);
Money cumulativeTotalPaid = Money.zero(currency); Money cumulativeTotalPaid = Money.zero(currency);
Money cumulativeTotalWaived = Money.zero(currency); Money cumulativeTotalWaived = Money.zero(currency);
for (LoanRepaymentScheduleInstallment scheduledRepayment : this.repaymentScheduleInstallments) { for (LoanRepaymentScheduleInstallment scheduledRepayment : this.repaymentScheduleInstallments) {
cumulativeOriginalExpectedTotal = cumulativeOriginalExpectedTotal.plus(scheduledRepayment.getPrincipal(currency)); cumulativeOriginalPrincipalExpected = cumulativeOriginalPrincipalExpected.plus(scheduledRepayment.getPrincipal(currency));
cumulativeOriginalInterestExpected = cumulativeOriginalInterestExpected.plus(scheduledRepayment.getInterest(currency));
cumulativeTotalPaid = cumulativeTotalPaid.plus(scheduledRepayment.getPrincipalCompleted(currency).plus(scheduledRepayment.getInterestCompleted(currency))); cumulativeTotalPaid = cumulativeTotalPaid.plus(scheduledRepayment.getPrincipalCompleted(currency).plus(scheduledRepayment.getInterestCompleted(currency)));
cumulativeTotalWaived = cumulativeTotalWaived.plus(scheduledRepayment.getInterestWaived(currency)); cumulativeTotalWaived = cumulativeTotalWaived.plus(scheduledRepayment.getInterestWaived(currency));
} }
Money totalOutstanding = cumulativeOriginalExpectedTotal.minus(cumulativeTotalPaid.plus(cumulativeTotalWaived)); cumulativeOriginalTotalExpected = cumulativeOriginalPrincipalExpected.plus(cumulativeOriginalInterestExpected);
Money totalOutstanding = cumulativeOriginalTotalExpected.minus(cumulativeTotalPaid.plus(cumulativeTotalWaived));
boolean isRepaidInFull = totalOutstanding.isZero(); boolean isRepaidInFull = totalOutstanding.isZero();
return isRepaidInFull; return isRepaidInFull;