add start of Adhikar example for processing loan transactions.
This commit is contained in:
+143
@@ -0,0 +1,143 @@
|
|||||||
|
package org.mifosng.platform.loan.domain;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.joda.time.LocalDate;
|
||||||
|
import org.mifosng.platform.currency.domain.MonetaryCurrency;
|
||||||
|
import org.mifosng.platform.currency.domain.Money;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adhikar style {@link LoanRepaymentScheduleTransactionProcessor}.
|
||||||
|
*
|
||||||
|
* From https://mifosforge.jira.com/browse/MIFOS-5636:
|
||||||
|
*
|
||||||
|
* Per RBI regulations, all interest must be paid (both current and overdue) before principal is paid.
|
||||||
|
*
|
||||||
|
* For example on a loan with two installments due (one current and one overdue) of 220 each (200 principal + 20 interest):
|
||||||
|
*
|
||||||
|
* Partial Payment of 40
|
||||||
|
* 20 Payment to interest on Installment #1 (200 principal remaining)
|
||||||
|
* 20 Payment to interest on Installment #2 (200 principal remaining)
|
||||||
|
*/
|
||||||
|
public class AdhikarLoanRepaymentScheduleTransactionProcessor extends AbstractLoanRepaymentScheduleTransactionProcessor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For creocore, early is defined as any date before the installment due
|
||||||
|
* date
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected boolean isTransactionInAdvanceOfInstallment(
|
||||||
|
final int currentInstallmentIndex,
|
||||||
|
final List<LoanRepaymentScheduleInstallment> installments,
|
||||||
|
final LocalDate transactionDate, final Money transactionAmount) {
|
||||||
|
|
||||||
|
LoanRepaymentScheduleInstallment currentInstallment = installments.get(currentInstallmentIndex);
|
||||||
|
|
||||||
|
return transactionDate.isBefore(currentInstallment.getDueDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For early/'in advance' repayments, pays off principal component only.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected Money handleTransactionThatIsPaymentInAdvanceOfInstallment(
|
||||||
|
final LoanRepaymentScheduleInstallment currentInstallment,
|
||||||
|
final List<LoanRepaymentScheduleInstallment> 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<LoanRepaymentScheduleInstallment> installments,
|
||||||
|
final LoanTransaction loanTransaction,
|
||||||
|
final Money transactionAmountUnprocessed) {
|
||||||
|
|
||||||
|
// pay of overdue and current interest due given transaction date
|
||||||
|
MonetaryCurrency currency = transactionAmountUnprocessed.getCurrency();
|
||||||
|
Money transactionAmountRemaining = transactionAmountUnprocessed;
|
||||||
|
|
||||||
|
LoanRepaymentScheduleInstallment currentInstallmentBasedOnTransactionDate = nearestInstallment(loanTransaction.getTransactionDate(), installments);
|
||||||
|
|
||||||
|
for (LoanRepaymentScheduleInstallment installment : installments) {
|
||||||
|
if (
|
||||||
|
installment.isInterestDue(currency) &&
|
||||||
|
(installment.isOverdueOn(loanTransaction.getTransactionDate()) || installment.getInstallmentNumber().equals(currentInstallmentBasedOnTransactionDate.getInstallmentNumber()))
|
||||||
|
) {
|
||||||
|
Money interestPortion = installment.payInterestComponent(transactionAmountRemaining);
|
||||||
|
transactionAmountRemaining = transactionAmountRemaining.minus(interestPortion);
|
||||||
|
|
||||||
|
Money principalPortion = Money.zero(currency);
|
||||||
|
Money interestWaivedPortion = Money.zero(currency);
|
||||||
|
loanTransaction.updateComponents(principalPortion, interestPortion, interestWaivedPortion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// With whatever is remaining, pay off principal components of installments
|
||||||
|
for (LoanRepaymentScheduleInstallment installment : installments) {
|
||||||
|
if (installment.isPrincipalNotCompleted(currency) && transactionAmountRemaining.isGreaterThanZero()) {
|
||||||
|
Money principalPortion = installment.payPrincipalComponent(transactionAmountRemaining);
|
||||||
|
transactionAmountRemaining = transactionAmountRemaining.minus(principalPortion);
|
||||||
|
|
||||||
|
Money interestPortion = Money.zero(currency);
|
||||||
|
Money interestWaivedPortion = Money.zero(currency);
|
||||||
|
loanTransaction.updateComponents(principalPortion, interestPortion, interestWaivedPortion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return transactionAmountRemaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LoanRepaymentScheduleInstallment nearestInstallment(final LocalDate transactionDate, List<LoanRepaymentScheduleInstallment> installments) {
|
||||||
|
|
||||||
|
LoanRepaymentScheduleInstallment nearest = installments.get(0);
|
||||||
|
|
||||||
|
for (LoanRepaymentScheduleInstallment installment : installments) {
|
||||||
|
if (installment.getDueDate().isAfter(transactionDate) || installment.getDueDate().isEqual(transactionDate)) {
|
||||||
|
nearest = installment;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nearest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
-5
@@ -85,26 +85,30 @@ public class LoanRepaymentScheduleInstallment extends AbstractAuditableCustom<Ap
|
|||||||
return new LocalDate(this.dueDate);
|
return new LocalDate(this.dueDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Money getPrincipal(MonetaryCurrency currency) {
|
public Money getPrincipal(final MonetaryCurrency currency) {
|
||||||
return Money.of(currency, this.principal);
|
return Money.of(currency, this.principal);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Money getPrincipalCompleted(MonetaryCurrency currency) {
|
public Money getPrincipalCompleted(final MonetaryCurrency currency) {
|
||||||
return Money.of(currency, this.principalCompleted);
|
return Money.of(currency, this.principalCompleted);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Money getInterest(MonetaryCurrency currency) {
|
public Money getInterest(final MonetaryCurrency currency) {
|
||||||
return Money.of(currency, this.interest);
|
return Money.of(currency, this.interest);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Money getInterestCompleted(MonetaryCurrency currency) {
|
public Money getInterestCompleted(final MonetaryCurrency currency) {
|
||||||
return Money.of(currency, this.interestCompleted);
|
return Money.of(currency, this.interestCompleted);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Money getInterestWaived(MonetaryCurrency currency) {
|
public Money getInterestWaived(final MonetaryCurrency currency) {
|
||||||
return Money.of(currency, this.interestWaived);
|
return Money.of(currency, this.interestWaived);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isInterestDue(final MonetaryCurrency currency) {
|
||||||
|
return getInterest(currency).minus(getInterestCompleted(currency).plus(getInterestWaived(currency))).isGreaterThanZero();
|
||||||
|
}
|
||||||
|
|
||||||
public Money getTotal(MonetaryCurrency currency) {
|
public Money getTotal(MonetaryCurrency currency) {
|
||||||
return getPrincipal(currency).plus(getInterest(currency));
|
return getPrincipal(currency).plus(getInterest(currency));
|
||||||
}
|
}
|
||||||
@@ -204,4 +208,8 @@ public class LoanRepaymentScheduleInstallment extends AbstractAuditableCustom<Ap
|
|||||||
|
|
||||||
return waivedInterestPortionOfTransaction;
|
return waivedInterestPortionOfTransaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isOverdueOn(final LocalDate transactionDate) {
|
||||||
|
return this.getDueDate().isBefore(transactionDate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+154
@@ -0,0 +1,154 @@
|
|||||||
|
package org.mifosng.platform.loan.domain;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.joda.time.LocalDate;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mifosng.platform.currency.domain.MonetaryCurrency;
|
||||||
|
import org.mifosng.platform.currency.domain.Money;
|
||||||
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class AdhikarLoanRepaymentScheduleTransactionProcessorTest {
|
||||||
|
|
||||||
|
// class under test
|
||||||
|
private AdhikarLoanRepaymentScheduleTransactionProcessor processor;
|
||||||
|
|
||||||
|
//
|
||||||
|
private LocalDate july2nd = new LocalDate(2012, 7, 2);
|
||||||
|
private MonetaryCurrency usDollars = new MonetaryCurrencyBuilder().withCode("USD").withDigitsAfterDecimal(2).build();
|
||||||
|
private List<LoanRepaymentScheduleInstallment> installments;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUpForEachTestCase() {
|
||||||
|
|
||||||
|
installments = LoanScheduleTestDataHelper.createSimpleLoanSchedule(july2nd, usDollars);
|
||||||
|
|
||||||
|
processor = new AdhikarLoanRepaymentScheduleTransactionProcessor();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scenario 1: Given no overdue installments, current interest due is paid before principal.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void givenNoOverdueInstallmentsOnTimeRepaymentPaysOffInterestDueFirst() {
|
||||||
|
|
||||||
|
// setup
|
||||||
|
Money repaymentAmount = new MoneyBuilder().with(usDollars).with("100.00").build();
|
||||||
|
LoanTransaction onTimePartialRepayment = new LoanTransactionBuilder().repayment().with(july2nd).with(repaymentAmount).build();
|
||||||
|
|
||||||
|
// execute test
|
||||||
|
processor.handleTransaction(onTimePartialRepayment, usDollars, installments);
|
||||||
|
|
||||||
|
// verification of derived fields on installments
|
||||||
|
LoanRepaymentScheduleInstallment firstInstallment = this.installments.get(0);
|
||||||
|
assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("0.00"), interestOf("100.00"), interestWaivedOf("0.00"), firstInstallment, usDollars);
|
||||||
|
|
||||||
|
assertThatLoanTransactionHasDerivedFieldsOf(principalOf("0.00"), interestOf("100.00"), interestWaivedOf("0.00"), onTimePartialRepayment, usDollars);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scenario 2: Given overdue interest exists on overdue installment, a late
|
||||||
|
* repayment results in overdue interest and current interest being paid
|
||||||
|
* before principal component for overdue or current installments.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void givenOverdueInterestOnOverdueInstallmentsLateRepaymentPaysOffOverdueInterestAndCurrentInterestDue() {
|
||||||
|
|
||||||
|
// setup
|
||||||
|
Money repaymentAmount = new MoneyBuilder().with(usDollars).with("300.00").build();
|
||||||
|
LoanTransaction lateRepayment = new LoanTransactionBuilder().repayment().with(july2nd.plusMonths(1)).with(repaymentAmount).build();
|
||||||
|
|
||||||
|
// execute test
|
||||||
|
processor.handleTransaction(lateRepayment, usDollars, installments);
|
||||||
|
|
||||||
|
// verification of derived fields on installments
|
||||||
|
LoanRepaymentScheduleInstallment firstInstallment = this.installments.get(0);
|
||||||
|
assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("0.00"), interestOf("200.00"), interestWaivedOf("0.00"), firstInstallment, usDollars);
|
||||||
|
|
||||||
|
LoanRepaymentScheduleInstallment secondInstallment = this.installments.get(1);
|
||||||
|
assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("0.00"), interestOf("100.00"), interestWaivedOf("0.00"), secondInstallment, usDollars);
|
||||||
|
|
||||||
|
LoanRepaymentScheduleInstallment thirdInstallment = this.installments.get(2);
|
||||||
|
assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("0.00"), interestOf("0.00"), interestWaivedOf("0.00"), thirdInstallment, usDollars);
|
||||||
|
|
||||||
|
assertThatLoanTransactionHasDerivedFieldsOf(principalOf("0.00"), interestOf("300.00"), interestWaivedOf("0.00"), lateRepayment, usDollars);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scenario 3: Given an overdue installment with overdue interest and principal, a late
|
||||||
|
* repayment results in overdue interest and current interest being paid
|
||||||
|
* before principal component for overdue or current installments.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void givenAFullyOverdueInstallmentALateRepaymentShouldPayOffOverdueInterestAndCurrentInterestDueFirstThenOverduePrincipal() {
|
||||||
|
|
||||||
|
// setup
|
||||||
|
Money repaymentAmount = new MoneyBuilder().with(usDollars).with("900.00").build();
|
||||||
|
LoanTransaction lateRepayment = new LoanTransactionBuilder().repayment().with(july2nd.plusMonths(1)).with(repaymentAmount).build();
|
||||||
|
|
||||||
|
// execute test
|
||||||
|
processor.handleTransaction(lateRepayment, usDollars, installments);
|
||||||
|
|
||||||
|
// verification of derived fields on installments
|
||||||
|
LoanRepaymentScheduleInstallment firstInstallment = this.installments.get(0);
|
||||||
|
assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("500.00"), interestOf("200.00"), interestWaivedOf("0.00"), firstInstallment, usDollars);
|
||||||
|
|
||||||
|
LoanRepaymentScheduleInstallment secondInstallment = this.installments.get(1);
|
||||||
|
assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("0.00"), interestOf("200.00"), interestWaivedOf("0.00"), secondInstallment, usDollars);
|
||||||
|
|
||||||
|
LoanRepaymentScheduleInstallment thirdInstallment = this.installments.get(2);
|
||||||
|
assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("0.00"), interestOf("0.00"), interestWaivedOf("0.00"), thirdInstallment, usDollars);
|
||||||
|
|
||||||
|
assertThatLoanTransactionHasDerivedFieldsOf(principalOf("500.00"), interestOf("400.00"), interestWaivedOf("0.00"), lateRepayment, usDollars);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertThatLoanTransactionHasDerivedFieldsOf(
|
||||||
|
final String principal,
|
||||||
|
final String interest,
|
||||||
|
final String interestWaived,
|
||||||
|
final LoanTransaction transaction, final MonetaryCurrency currency) {
|
||||||
|
|
||||||
|
Money expectedPrincipalPortion = new MoneyBuilder().with(currency).with(principal).build();
|
||||||
|
assertThat("Principal portion of transaction not as expected: ", transaction.getPrincipalPortion(currency).toString(), is(expectedPrincipalPortion.toString()));
|
||||||
|
|
||||||
|
Money expectedInterestPortion = new MoneyBuilder().with(currency).with(interest).build();
|
||||||
|
assertThat("Interest portion of transaction not as expected: ", transaction.getInterestPortion(currency).toString(), is(expectedInterestPortion.toString()));
|
||||||
|
|
||||||
|
Money expectedInterestWaivedPortion = new MoneyBuilder().with(currency).with(interestWaived).build();
|
||||||
|
assertThat("Interest waived portion of transaction not as expected: ",transaction.getInterestWaivedPortion(currency).toString(), is(expectedInterestWaivedPortion.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertThatLoanInstallmentHasDerivedFieldsOf(
|
||||||
|
final String principal,
|
||||||
|
final String interest,
|
||||||
|
final String interestWaived,
|
||||||
|
final LoanRepaymentScheduleInstallment installment, final MonetaryCurrency currency) {
|
||||||
|
|
||||||
|
Money expectedPrincipalCompleted = new MoneyBuilder().with(currency).with(principal).build();
|
||||||
|
assertThat("principal not as expected", installment.getPrincipalCompleted(currency).toString(), is(expectedPrincipalCompleted.toString()));
|
||||||
|
|
||||||
|
Money expectedInterestCompleted = new MoneyBuilder().with(currency).with(interest).build();
|
||||||
|
assertThat("interest completed not as expected: ",installment.getInterestCompleted(currency).toString(), is(expectedInterestCompleted.toString()));
|
||||||
|
|
||||||
|
Money expectedInterestWaived = new MoneyBuilder().with(currency).with(interestWaived).build();
|
||||||
|
assertThat("interest waived not as expected: ", installment.getInterestWaived(currency).toString(), is(expectedInterestWaived.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String principalOf(final String value) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String interestOf(final String value) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String interestWaivedOf(final String value) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -48,4 +48,9 @@ public class LoanRepaymentScheduleInstallmentBuilder {
|
|||||||
this.completed = true;
|
this.completed = true;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LoanRepaymentScheduleInstallmentBuilder withInstallmentNumber(final int withInstallmentNumber) {
|
||||||
|
this.installmentNumber = withInstallmentNumber;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+35
-4
@@ -11,20 +11,35 @@ import org.mifosng.platform.currency.domain.MonetaryCurrency;
|
|||||||
*/
|
*/
|
||||||
public class LoanScheduleTestDataHelper {
|
public class LoanScheduleTestDataHelper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates brand new three installment loan:
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
* with firstDueDate = 02 July 2011
|
||||||
|
*
|
||||||
|
* Date Principal Interest Interest Waived
|
||||||
|
* ==================================================================================
|
||||||
|
* 02 July 2011 1,000 200 0
|
||||||
|
* 02 August 2011 1,000 200 0
|
||||||
|
* 02 September 2011 1,000 200 0
|
||||||
|
*/
|
||||||
public static List<LoanRepaymentScheduleInstallment> createSimpleLoanSchedule(final LocalDate firstDueDate, final MonetaryCurrency currency) {
|
public static List<LoanRepaymentScheduleInstallment> createSimpleLoanSchedule(final LocalDate firstDueDate, final MonetaryCurrency currency) {
|
||||||
LoanRepaymentScheduleInstallment firstInstallment = new LoanRepaymentScheduleInstallmentBuilder(currency)
|
LoanRepaymentScheduleInstallment firstInstallment = new LoanRepaymentScheduleInstallmentBuilder(currency)
|
||||||
|
.withInstallmentNumber(1)
|
||||||
.withDueDate(firstDueDate)
|
.withDueDate(firstDueDate)
|
||||||
.withPrincipal("1000.00")
|
.withPrincipal("1000.00")
|
||||||
.withInterest("200.00")
|
.withInterest("200.00")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
LoanRepaymentScheduleInstallment secondInstallment = new LoanRepaymentScheduleInstallmentBuilder(currency)
|
LoanRepaymentScheduleInstallment secondInstallment = new LoanRepaymentScheduleInstallmentBuilder(currency)
|
||||||
.withDueDate(firstDueDate.plusMonths(1))
|
.withInstallmentNumber(2)
|
||||||
.withPrincipal("1000.00")
|
.withDueDate(firstDueDate.plusMonths(1))
|
||||||
.withInterest("200.00")
|
.withPrincipal("1000.00")
|
||||||
.build();
|
.withInterest("200.00")
|
||||||
|
.build();
|
||||||
|
|
||||||
LoanRepaymentScheduleInstallment thirdInstallment = new LoanRepaymentScheduleInstallmentBuilder(currency)
|
LoanRepaymentScheduleInstallment thirdInstallment = new LoanRepaymentScheduleInstallmentBuilder(currency)
|
||||||
|
.withInstallmentNumber(3)
|
||||||
.withDueDate(firstDueDate.plusMonths(2))
|
.withDueDate(firstDueDate.plusMonths(2))
|
||||||
.withPrincipal("1000.00")
|
.withPrincipal("1000.00")
|
||||||
.withInterest("200.00")
|
.withInterest("200.00")
|
||||||
@@ -33,9 +48,23 @@ public class LoanScheduleTestDataHelper {
|
|||||||
return Arrays.asList(firstInstallment, secondInstallment, thirdInstallment);
|
return Arrays.asList(firstInstallment, secondInstallment, thirdInstallment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates three installment loan with first installment fully completed:
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
* with firstDueDate = 02 July 2011
|
||||||
|
*
|
||||||
|
* Date Principal Interest Interest Waived Completed
|
||||||
|
* ================================================================================================================
|
||||||
|
* 02 July 2011 1,000 200 0 true (principal paid, interest paid)
|
||||||
|
* 02 August 2011 1,000 200 0 false
|
||||||
|
* 02 September 2011 1,000 200 0 false
|
||||||
|
*/
|
||||||
public static List<LoanRepaymentScheduleInstallment> createSimpleLoanScheduleWithFirstInstallmentFullyPaid(final LocalDate firstDueDate, final MonetaryCurrency currency) {
|
public static List<LoanRepaymentScheduleInstallment> createSimpleLoanScheduleWithFirstInstallmentFullyPaid(final LocalDate firstDueDate, final MonetaryCurrency currency) {
|
||||||
|
|
||||||
LoanRepaymentScheduleInstallment firstInstallment = new LoanRepaymentScheduleInstallmentBuilder(currency)
|
LoanRepaymentScheduleInstallment firstInstallment = new LoanRepaymentScheduleInstallmentBuilder(currency)
|
||||||
|
.withInstallmentNumber(1)
|
||||||
.withDueDate(firstDueDate)
|
.withDueDate(firstDueDate)
|
||||||
.withPrincipal("1000.00")
|
.withPrincipal("1000.00")
|
||||||
.withInterest("200.00")
|
.withInterest("200.00")
|
||||||
@@ -43,12 +72,14 @@ public class LoanScheduleTestDataHelper {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
LoanRepaymentScheduleInstallment secondInstallment = new LoanRepaymentScheduleInstallmentBuilder(currency)
|
LoanRepaymentScheduleInstallment secondInstallment = new LoanRepaymentScheduleInstallmentBuilder(currency)
|
||||||
|
.withInstallmentNumber(2)
|
||||||
.withDueDate(firstDueDate.plusMonths(1))
|
.withDueDate(firstDueDate.plusMonths(1))
|
||||||
.withPrincipal("1000.00")
|
.withPrincipal("1000.00")
|
||||||
.withInterest("200.00")
|
.withInterest("200.00")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
LoanRepaymentScheduleInstallment thirdInstallment = new LoanRepaymentScheduleInstallmentBuilder(currency)
|
LoanRepaymentScheduleInstallment thirdInstallment = new LoanRepaymentScheduleInstallmentBuilder(currency)
|
||||||
|
.withInstallmentNumber(3)
|
||||||
.withDueDate(firstDueDate.plusMonths(2))
|
.withDueDate(firstDueDate.plusMonths(2))
|
||||||
.withPrincipal("1000.00")
|
.withPrincipal("1000.00")
|
||||||
.withInterest("200.00")
|
.withInterest("200.00")
|
||||||
|
|||||||
Reference in New Issue
Block a user