From bc747a91ed8d17e8c5543e7040f0063a53975c1e Mon Sep 17 00:00:00 2001 From: Keith Woodlock Date: Wed, 1 Aug 2012 23:11:53 +0100 Subject: [PATCH] add mifos style repayment processor that pays off interest, then principal from most overdue installments first. --- ...RepaymentScheduleTransactionProcessor.java | 3 +- ...ntScheduleTransactionProcessorFactory.java | 7 +- ...RepaymentScheduleTransactionProcessor.java | 96 +++++++++++++++++++ 3 files changed, 101 insertions(+), 5 deletions(-) create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/MifosStyleLoanRepaymentScheduleTransactionProcessor.java diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/CreocoreLoanRepaymentScheduleTransactionProcessor.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/CreocoreLoanRepaymentScheduleTransactionProcessor.java index 8930e0da4..71a4b9b24 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/CreocoreLoanRepaymentScheduleTransactionProcessor.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/CreocoreLoanRepaymentScheduleTransactionProcessor.java @@ -37,7 +37,8 @@ public class CreocoreLoanRepaymentScheduleTransactionProcessor extends } /** - * For early/'in advance' repayments, pays off principal component only. + * For early/'in advance' repayments, pay off in the same way as on-time payments, + * interest first then principal. */ @Override protected Money handleTransactionThatIsPaymentInAdvanceOfInstallment( diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanRepaymentScheduleTransactionProcessorFactory.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanRepaymentScheduleTransactionProcessorFactory.java index 8c13e3fa6..b9000f34e 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanRepaymentScheduleTransactionProcessorFactory.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/LoanRepaymentScheduleTransactionProcessorFactory.java @@ -8,12 +8,12 @@ public class LoanRepaymentScheduleTransactionProcessorFactory { public LoanRepaymentScheduleTransactionProcessor determineProcessor(final LoanTransactionProcessingStrategy transactionProcessingStrategy) { - LoanRepaymentScheduleTransactionProcessor processor = new HeavensFamilyLoanRepaymentScheduleTransactionProcessor(); + LoanRepaymentScheduleTransactionProcessor processor = new MifosStyleLoanRepaymentScheduleTransactionProcessor(); if (transactionProcessingStrategy != null) { if (transactionProcessingStrategy.isStandardMifosStrategy()) { - processor = new HeavensFamilyLoanRepaymentScheduleTransactionProcessor(); + processor = new MifosStyleLoanRepaymentScheduleTransactionProcessor(); } if (transactionProcessingStrategy.isHeavensfamilyStrategy()) { @@ -31,5 +31,4 @@ public class LoanRepaymentScheduleTransactionProcessorFactory { return processor; } - -} +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/MifosStyleLoanRepaymentScheduleTransactionProcessor.java b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/MifosStyleLoanRepaymentScheduleTransactionProcessor.java new file mode 100644 index 000000000..3363cd786 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/loan/domain/MifosStyleLoanRepaymentScheduleTransactionProcessor.java @@ -0,0 +1,96 @@ +package org.mifosng.platform.loan.domain; + +import java.util.List; + +import org.joda.time.LocalDate; +import org.mifosng.platform.currency.domain.Money; + +/** + * Old Mifos style {@link LoanRepaymentScheduleTransactionProcessor}. + * + * For ALL types of transactions, pays off components in order of interest, then + * principal. + * + * Other formulas exist on mifos where you can choose 'Declining-Balance Interest Recalculation' which simply + * means, recalculate the interest component based on the how much principal is outstanding at a point in time; + * but this isnt trying to model that option only the basic one for now. + */ +public class MifosStyleLoanRepaymentScheduleTransactionProcessor extends + AbstractLoanRepaymentScheduleTransactionProcessor { + + @Override + protected boolean isTransactionInAdvanceOfInstallment( + final int currentInstallmentIndex, + final List installments, + final LocalDate transactionDate, final Money transactionAmount) { + + LoanRepaymentScheduleInstallment currentInstallment = installments.get(currentInstallmentIndex); + + return transactionDate.isBefore(currentInstallment.getDueDate()); + } + + /** + * For early/'in advance' repayments, pay off in the same way as on-time payments, + * interest first then principal. + */ + @Override + protected Money handleTransactionThatIsPaymentInAdvanceOfInstallment( + final LoanRepaymentScheduleInstallment currentInstallment, + final List installments, + final LoanTransaction loanTransaction, + final LocalDate transactionDate, final Money paymentInAdvance) { + + return handleTransactionThatIsOnTimePaymentOfInstallment(currentInstallment, loanTransaction, paymentInAdvance); + } + + /** + * For late repayments, pay off in the same way as on-time payments, + * interest first then principal. + */ + @Override + protected Money handleTransactionThatIsALateRepaymentOfInstallment( + final LoanRepaymentScheduleInstallment currentInstallment, + final List installments, + final LoanTransaction loanTransaction, + final Money transactionAmountUnprocessed) { + + return handleTransactionThatIsOnTimePaymentOfInstallment( + currentInstallment, loanTransaction, + transactionAmountUnprocessed); + } + + /** + * For normal on-time repayments, pays off interest first, then principal. + */ + @Override + protected Money handleTransactionThatIsOnTimePaymentOfInstallment( + final LoanRepaymentScheduleInstallment currentInstallment, + final LoanTransaction loanTransaction, + final Money transactionAmountUnprocessed) { + + Money transactionAmountRemaining = transactionAmountUnprocessed; + + Money interestPortion = currentInstallment + .payInterestComponent(transactionAmountRemaining); + transactionAmountRemaining = transactionAmountRemaining + .minus(interestPortion); + + Money principalPortion = currentInstallment + .payPrincipalComponent(transactionAmountRemaining); + transactionAmountRemaining = transactionAmountRemaining + .minus(principalPortion); + + Money interestWaivedPortion = Money.zero(transactionAmountRemaining + .getCurrency()); + loanTransaction.updateComponents(principalPortion, interestPortion, + interestWaivedPortion); + + return transactionAmountRemaining; + } + + @Override + protected void onLoanOverpayment(final LoanTransaction loanTransaction, + final Money loanOverPaymentAmount) { + // dont do anything for with loan over-payment + } +} \ No newline at end of file