support flexible repayment strategies for loans.
This commit is contained in:
+392
@@ -0,0 +1,392 @@
|
||||
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 DefaultLoanRepaymentScheduleTransactionProcessorTest {
|
||||
|
||||
// class under test
|
||||
private DefaultLoanRepaymentScheduleTransactionProcessor 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 DefaultLoanRepaymentScheduleTransactionProcessor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario 1: Single transaction which is less than the interest component of the first installment.
|
||||
*
|
||||
* Expectation:
|
||||
* - First installment shows interest completed equal to that of transactions, zero principal completed. (payment order interest, principal)
|
||||
* - transaction has interest portion equal to transaction amount, and zero principal portion
|
||||
*/
|
||||
@Test
|
||||
public void givenSingleOnTimeLoanTransactionShouldPayoffInterestComponentFirst() {
|
||||
|
||||
// setup
|
||||
LoanRepaymentScheduleInstallment singleInstallment = this.installments.get(0);
|
||||
|
||||
Money oneHundredDollars = new MoneyBuilder().with(usDollars).with("100.00").build();
|
||||
LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(oneHundredDollars).build();
|
||||
|
||||
// execute test
|
||||
processor.handleTransaction(onTimePartialPayment, usDollars, installments);
|
||||
|
||||
// verification of derived fields on installments
|
||||
assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("0.00", "100.00", singleInstallment);
|
||||
assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("0.00", "100.00", onTimePartialPayment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario 2: Two transactions which is less than the interest component of the first installment.
|
||||
*
|
||||
* Expectation:
|
||||
* - First installment shows interest completed equal to that of transactions, zero principal completed. (payment order interest, principal)
|
||||
* - transactions has interest portion equal to transaction amount, and zero principal portion
|
||||
*/
|
||||
@Test
|
||||
public void givenMultipleOnTimeLoanTransactionShouldPayoffInterestComponentFirst() {
|
||||
|
||||
// setup
|
||||
LoanRepaymentScheduleInstallment singleInstallment = this.installments.get(0);
|
||||
|
||||
Money oneHundredDollars = new MoneyBuilder().with(usDollars).with("100.00").build();
|
||||
LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(oneHundredDollars).build();
|
||||
|
||||
Money fiftyDollars = new MoneyBuilder().with(usDollars).with("50.00").build();
|
||||
LoanTransaction secondOnTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(fiftyDollars).build();
|
||||
|
||||
|
||||
// execute test
|
||||
processor.handleTransaction(onTimePartialPayment, usDollars, installments);
|
||||
processor.handleTransaction(secondOnTimePartialPayment, usDollars, installments);
|
||||
|
||||
// verification of derived fields on installments
|
||||
assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("0.00", "150.00", singleInstallment);
|
||||
|
||||
assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("0.00", "100.00", onTimePartialPayment);
|
||||
assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("0.00", "50.00", secondOnTimePartialPayment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario 3: Single transaction which is greater than the interest component of the first installment but less than the total due for installment.
|
||||
*
|
||||
* Expectation:
|
||||
* - First installment shows interest completed equal to that interest due, remainder is against principal completed. (payment order interest, principal)
|
||||
* - transaction has interest portion equal to interest expected and principal portion of remainder.
|
||||
*/
|
||||
@Test
|
||||
public void givenSingleOnTimeLoanTransactionShouldPayoffInterestThenPrincipalComponents() {
|
||||
|
||||
// setup
|
||||
LoanRepaymentScheduleInstallment singleInstallment = this.installments.get(0);
|
||||
|
||||
Money amount = new MoneyBuilder().with(usDollars).with("300.00").build();
|
||||
LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(amount).build();
|
||||
|
||||
// execute test
|
||||
processor.handleTransaction(onTimePartialPayment, usDollars, installments);
|
||||
|
||||
// verification of derived fields on installments
|
||||
assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("100.00", "200.00", singleInstallment);
|
||||
assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("100.00", "200.00", onTimePartialPayment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario 4: Single transaction which is greater than the interest component of the first installment but less than the total due for installment.
|
||||
*
|
||||
* Expectation:
|
||||
* - First installment shows interest completed equal to that interest due, remainder is against principal completed. (payment order interest, principal)
|
||||
* - transaction has interest portion equal to interest expected and principal portion of remainder.
|
||||
*/
|
||||
@Test
|
||||
public void givenMultipleOnTimeLoanTransactionShouldPayoffInterestThenPrincipalComponents() {
|
||||
|
||||
// setup
|
||||
LoanRepaymentScheduleInstallment singleInstallment = this.installments.get(0);
|
||||
|
||||
Money amount = new MoneyBuilder().with(usDollars).with("300.00").build();
|
||||
LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(amount).build();
|
||||
|
||||
Money secondTransactionAmount = new MoneyBuilder().with(usDollars).with("50.00").build();
|
||||
LoanTransaction secondOnTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(secondTransactionAmount).build();
|
||||
|
||||
// execute test
|
||||
processor.handleTransaction(onTimePartialPayment, usDollars, installments);
|
||||
processor.handleTransaction(secondOnTimePartialPayment, usDollars, installments);
|
||||
|
||||
// verification of derived fields on installments
|
||||
assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("150.00", "200.00", singleInstallment);
|
||||
|
||||
assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("100.00", "200.00", onTimePartialPayment);
|
||||
assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("50.00", "0.00", secondOnTimePartialPayment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario 5:Single transaction which is equal to the total due for installment.
|
||||
*
|
||||
* Expectation:
|
||||
* - First installment shows interest completed and principal completed equal to their due amounts. (payment order interest, principal)
|
||||
* - transaction has interest portion and principal portions
|
||||
*/
|
||||
@Test
|
||||
public void givenSingleFullOnTimeLoanTransactionShouldPayoffInterestThenPrincipalComponentInFull() {
|
||||
|
||||
// setup
|
||||
LoanRepaymentScheduleInstallment singleInstallment = this.installments.get(0);
|
||||
|
||||
Money amount = new MoneyBuilder().with(usDollars).with("1200.00").build();
|
||||
LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(amount).build();
|
||||
|
||||
// execute test
|
||||
processor.handleTransaction(onTimePartialPayment, usDollars, installments);
|
||||
|
||||
// verification of derived fields on installments
|
||||
assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("1000.00", "200.00", singleInstallment);
|
||||
assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("1000.00", "200.00", onTimePartialPayment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario 6: Multiple transactions which together equal to the total due for installment.
|
||||
*
|
||||
* Expectation:
|
||||
* - First installment shows interest completed and principal completed equal to their due amounts. (payment order interest, principal)
|
||||
* - transaction has interest portion and principal portions
|
||||
*/
|
||||
@Test
|
||||
public void givenMuliptleOnTimeLoanTransactionsThatInFullShouldPayoffInterestThenPrincipalComponentInFull() {
|
||||
|
||||
// setup
|
||||
LoanRepaymentScheduleInstallment singleInstallment = this.installments.get(0);
|
||||
|
||||
Money amount = new MoneyBuilder().with(usDollars).with("600.00").build();
|
||||
LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(amount).build();
|
||||
|
||||
Money secondTransactionAmount = new MoneyBuilder().with(usDollars).with("600.00").build();
|
||||
LoanTransaction secondOnTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(secondTransactionAmount).build();
|
||||
|
||||
// execute test
|
||||
processor.handleTransaction(onTimePartialPayment, usDollars, installments);
|
||||
processor.handleTransaction(secondOnTimePartialPayment, usDollars, installments);
|
||||
|
||||
// verification of derived fields on installments
|
||||
assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("1000.00", "200.00", singleInstallment);
|
||||
assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("400.00", "200.00", onTimePartialPayment);
|
||||
assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("600.00", "0.00", secondOnTimePartialPayment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario 7: Single transaction which is greater than total due for first installment.
|
||||
*
|
||||
* Expectation:
|
||||
* - First installment shows interest completed and principal completed equal to their due amounts. (payment order interest, principal)
|
||||
* - Second installment shows principal completed equal to the remaining amount
|
||||
* - transaction has interest portion and principal portions, the principal portion is the sum of principal completed for first and second installments
|
||||
*/
|
||||
@Test
|
||||
public void givenSingleOnTimeLoanTransactionThatOverpaysInstallmentShouldPayoffInterestThenPrincipalComponentInFullOfFirstInstallmentWithRemainingOverpaymentAgainstPrincipalOfNextInstallment() {
|
||||
|
||||
// setup
|
||||
Money amount = new MoneyBuilder().with(usDollars).with("1300.00").build();
|
||||
LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(amount).build();
|
||||
|
||||
// execute test
|
||||
processor.handleTransaction(onTimePartialPayment, usDollars, installments);
|
||||
|
||||
// verification of derived fields on installments
|
||||
LoanRepaymentScheduleInstallment firstInstallment = this.installments.get(0);
|
||||
assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("1000.00", "200.00", firstInstallment);
|
||||
|
||||
LoanRepaymentScheduleInstallment secondInstallment = this.installments.get(1);
|
||||
assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("100.00", "0.00", secondInstallment);
|
||||
|
||||
assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("1100.00", "200.00", onTimePartialPayment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario 8: Multiple transactions which together are greater than total due for first installment.
|
||||
*
|
||||
* Expectation:
|
||||
* - First installment shows interest completed and principal completed equal to their due amounts. (payment order interest, principal)
|
||||
* - Second installment shows principal completed equal to the remaining amount
|
||||
*/
|
||||
@Test
|
||||
public void givenMultipleOnTimeLoanTransactionThatOverpaysInstallmentShouldPayoffInterestThenPrincipalComponentInFullOfFirstInstallmentWithRemainingOverpaymentAgainstPrincipalOfNextInstallment() {
|
||||
|
||||
// setup
|
||||
Money amount = new MoneyBuilder().with(usDollars).with("600.00").build();
|
||||
LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(amount).build();
|
||||
|
||||
Money secondTransactionAmount = new MoneyBuilder().with(usDollars).with("700.00").build();
|
||||
LoanTransaction secondOnTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(secondTransactionAmount).build();
|
||||
|
||||
// execute test
|
||||
processor.handleTransaction(onTimePartialPayment, usDollars, installments);
|
||||
processor.handleTransaction(secondOnTimePartialPayment, usDollars, installments);
|
||||
|
||||
// verification of derived fields on installments
|
||||
LoanRepaymentScheduleInstallment singleInstallment = this.installments.get(0);
|
||||
assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("1000.00", "200.00", singleInstallment);
|
||||
|
||||
LoanRepaymentScheduleInstallment secondInstallment = this.installments.get(1);
|
||||
assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("100.00", "0.00", secondInstallment);
|
||||
|
||||
assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("400.00", "200.00", onTimePartialPayment);
|
||||
assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("700.00", "0.00", secondOnTimePartialPayment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario 9: Single transaction which overpays first installment and second installment with outstanding amount been account as principal in third installment.
|
||||
*
|
||||
* Where an installments principal is paid for fully in advance - the interest component is waived.
|
||||
*/
|
||||
@Test
|
||||
public void givenOverPaymentShouldPayoffInterestThenPrincipalComponentsOfFirstInstallmentWithRemainingOverpaymentAgainstPrincipalOfAllSubsequentInstallments() {
|
||||
// setup
|
||||
Money amount = new MoneyBuilder().with(usDollars).with("3000.00").build();
|
||||
LoanTransaction onTimePartialPayment = new LoanTransactionBuilder().repayment().with(july2nd).with(amount).build();
|
||||
|
||||
// execute test
|
||||
processor.handleTransaction(onTimePartialPayment, usDollars, installments);
|
||||
|
||||
// verification of derived fields on installments
|
||||
LoanRepaymentScheduleInstallment firstInstallment = this.installments.get(0);
|
||||
assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("1000.00"), interestOf("200.00"), interestWaivedOf("0.00"), firstInstallment, usDollars);
|
||||
|
||||
LoanRepaymentScheduleInstallment secondInstallment = this.installments.get(1);
|
||||
assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("1000.00"), interestOf("0.00"), interestWaivedOf("200.00"), secondInstallment, usDollars);
|
||||
|
||||
LoanRepaymentScheduleInstallment thirdInstallment = this.installments.get(2);
|
||||
assertThatLoanInstallmentHasDerivedFieldsOf(principalOf("800.00"), interestOf("0.00"), interestWaivedOf("0.00"), thirdInstallment, usDollars);
|
||||
|
||||
assertThatLoanTransactionHasDerivedFieldsOf(principalOf("2800.00"), interestOf("200.00"), interestWaivedOf("200.00"), onTimePartialPayment, usDollars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario 10: Single transaction which is a repayment in advance
|
||||
*/
|
||||
@Test
|
||||
public void givenRepaymentOfInstallmentInAdvanceShouldPayoffOnlyPrincipalComponent() {
|
||||
// setup
|
||||
installments = LoanScheduleTestDataHelper.createSimpleLoanScheduleWithFirstInstallmentFullyPaid(july2nd, usDollars);
|
||||
LoanRepaymentScheduleInstallment firstInstallment = this.installments.get(0);
|
||||
LocalDate paymentInAdvanceDate = firstInstallment.getDueDate().minusDays(1);
|
||||
|
||||
Money amount = new MoneyBuilder().with(usDollars).with("900.00").build();
|
||||
LoanTransaction paymentInAdvance = new LoanTransactionBuilder().repayment().with(paymentInAdvanceDate).with(amount).build();
|
||||
|
||||
// execute test
|
||||
processor.handleTransaction(paymentInAdvance, usDollars, installments);
|
||||
|
||||
// verification of derived fields on installments
|
||||
LoanRepaymentScheduleInstallment secondInstallment = this.installments.get(1);
|
||||
assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("900.00", "0.00", secondInstallment);
|
||||
|
||||
assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("900.00", "0.00", paymentInAdvance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario 11: Single transaction which is a repayment many days early but still does not qualify for 'in advance'.
|
||||
*/
|
||||
@Test
|
||||
public void givenRepaymentOfInstallmentBeforeDueDateButNotInAdvanceShouldPayoffInterestAndPrincipalComponents() {
|
||||
// setup
|
||||
installments = LoanScheduleTestDataHelper.createSimpleLoanScheduleWithFirstInstallmentFullyPaid(july2nd, usDollars);
|
||||
LoanRepaymentScheduleInstallment firstInstallment = this.installments.get(0);
|
||||
LocalDate paymentBeforeDueDateButNotInAdvanceDate = firstInstallment.getDueDate().plusDays(1);
|
||||
|
||||
Money amount = new MoneyBuilder().with(usDollars).with("900.00").build();
|
||||
LoanTransaction paymentBeforeDueDateButNotInAdvance = new LoanTransactionBuilder().repayment().with(paymentBeforeDueDateButNotInAdvanceDate).with(amount).build();
|
||||
|
||||
// execute test
|
||||
processor.handleTransaction(paymentBeforeDueDateButNotInAdvance, usDollars, installments);
|
||||
|
||||
// verification of derived fields on installments
|
||||
LoanRepaymentScheduleInstallment secondInstallment = this.installments.get(1);
|
||||
assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf("700.00", "200.00", secondInstallment);
|
||||
|
||||
assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf("700.00", "200.00", paymentBeforeDueDateButNotInAdvance);
|
||||
}
|
||||
|
||||
private void assertThatLoanTransactionHasDerivedFieldsForPrincipalInterestOf(
|
||||
final String principal, final String interest, final LoanTransaction transaction) {
|
||||
|
||||
Money expectedInterestPortion = new MoneyBuilder().with(usDollars).with(interest).build();
|
||||
assertThat(transaction.getInterestPortion(usDollars).toString(), is(expectedInterestPortion.toString()));
|
||||
|
||||
Money expectedPrincipalPortion = new MoneyBuilder().with(usDollars).with(principal).build();
|
||||
assertThat(transaction.getPrincipalPortion(usDollars).toString(), is(expectedPrincipalPortion.toString()));
|
||||
}
|
||||
|
||||
private void assertThatLoanInstallmentHasDerivedFieldsForPrincipalInterestOf(final String principal, final String interest,
|
||||
final LoanRepaymentScheduleInstallment installment) {
|
||||
Money expectedInterestCompleted = new MoneyBuilder().with(usDollars).with(interest).build();
|
||||
assertThat(installment.getInterestCompleted(usDollars).toString(), is(expectedInterestCompleted.toString()));
|
||||
|
||||
Money expectedPrincipalCompleted = new MoneyBuilder().with(usDollars).with(principal).build();
|
||||
assertThat(installment.getPrincipalCompleted(usDollars).toString(), is(expectedPrincipalCompleted.toString()));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
+12
-2
@@ -8,11 +8,11 @@ public class LoanRepaymentScheduleInstallmentBuilder {
|
||||
|
||||
private Loan loan = null;
|
||||
private Integer installmentNumber = Integer.valueOf(1);
|
||||
// private LocalDate from = LocalDate.now();
|
||||
private LocalDate dueDate = LocalDate.now();
|
||||
private MonetaryCurrency currencyDetail = new MonetaryCurrencyBuilder().build();
|
||||
private Money principal = new MoneyBuilder().build();
|
||||
private Money interest = new MoneyBuilder().build();
|
||||
private boolean completed = false;
|
||||
|
||||
public LoanRepaymentScheduleInstallmentBuilder(MonetaryCurrency currencyDetail) {
|
||||
this.currencyDetail = currencyDetail;
|
||||
@@ -21,7 +21,12 @@ public class LoanRepaymentScheduleInstallmentBuilder {
|
||||
}
|
||||
|
||||
public LoanRepaymentScheduleInstallment build() {
|
||||
return new LoanRepaymentScheduleInstallment(loan, installmentNumber, dueDate, principal.getAmount(), interest.getAmount());
|
||||
LoanRepaymentScheduleInstallment installment = new LoanRepaymentScheduleInstallment(loan, installmentNumber, dueDate, principal.getAmount(), interest.getAmount());
|
||||
if (completed) {
|
||||
installment.payPrincipalComponent(principal);
|
||||
installment.payInterestComponent(interest);
|
||||
}
|
||||
return installment;
|
||||
}
|
||||
|
||||
public LoanRepaymentScheduleInstallmentBuilder withPrincipal(String withPrincipal) {
|
||||
@@ -38,4 +43,9 @@ public class LoanRepaymentScheduleInstallmentBuilder {
|
||||
this.dueDate = withDueDate;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LoanRepaymentScheduleInstallmentBuilder completed() {
|
||||
this.completed = true;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
package org.mifosng.platform.loan.domain;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosng.platform.currency.domain.MonetaryCurrency;
|
||||
|
||||
/**
|
||||
* Helper class for creating loan schedule data suitable for testing.
|
||||
*/
|
||||
public class LoanScheduleTestDataHelper {
|
||||
|
||||
public static List<LoanRepaymentScheduleInstallment> createSimpleLoanSchedule(final LocalDate firstDueDate, final MonetaryCurrency currency) {
|
||||
LoanRepaymentScheduleInstallment firstInstallment = new LoanRepaymentScheduleInstallmentBuilder(currency)
|
||||
.withDueDate(firstDueDate)
|
||||
.withPrincipal("1000.00")
|
||||
.withInterest("200.00")
|
||||
.build();
|
||||
|
||||
LoanRepaymentScheduleInstallment secondInstallment = new LoanRepaymentScheduleInstallmentBuilder(currency)
|
||||
.withDueDate(firstDueDate.plusMonths(1))
|
||||
.withPrincipal("1000.00")
|
||||
.withInterest("200.00")
|
||||
.build();
|
||||
|
||||
LoanRepaymentScheduleInstallment thirdInstallment = new LoanRepaymentScheduleInstallmentBuilder(currency)
|
||||
.withDueDate(firstDueDate.plusMonths(2))
|
||||
.withPrincipal("1000.00")
|
||||
.withInterest("200.00")
|
||||
.build();
|
||||
|
||||
return Arrays.asList(firstInstallment, secondInstallment, thirdInstallment);
|
||||
}
|
||||
|
||||
public static List<LoanRepaymentScheduleInstallment> createSimpleLoanScheduleWithFirstInstallmentFullyPaid(final LocalDate firstDueDate, final MonetaryCurrency currency) {
|
||||
|
||||
LoanRepaymentScheduleInstallment firstInstallment = new LoanRepaymentScheduleInstallmentBuilder(currency)
|
||||
.withDueDate(firstDueDate)
|
||||
.withPrincipal("1000.00")
|
||||
.withInterest("200.00")
|
||||
.completed()
|
||||
.build();
|
||||
|
||||
LoanRepaymentScheduleInstallment secondInstallment = new LoanRepaymentScheduleInstallmentBuilder(currency)
|
||||
.withDueDate(firstDueDate.plusMonths(1))
|
||||
.withPrincipal("1000.00")
|
||||
.withInterest("200.00")
|
||||
.build();
|
||||
|
||||
LoanRepaymentScheduleInstallment thirdInstallment = new LoanRepaymentScheduleInstallmentBuilder(currency)
|
||||
.withDueDate(firstDueDate.plusMonths(2))
|
||||
.withPrincipal("1000.00")
|
||||
.withInterest("200.00")
|
||||
.build();
|
||||
|
||||
return Arrays.asList(firstInstallment, secondInstallment, thirdInstallment);
|
||||
}
|
||||
|
||||
}
|
||||
+21
-5
@@ -5,17 +5,33 @@ import org.mifosng.platform.currency.domain.Money;
|
||||
|
||||
public class LoanTransactionBuilder {
|
||||
|
||||
private Money amount = new MoneyBuilder().build();
|
||||
private LocalDate paymentDate = LocalDate.now();
|
||||
private Money transactionAmount = new MoneyBuilder().build();
|
||||
private LocalDate transactionDate = LocalDate.now();
|
||||
private boolean repayment = false;
|
||||
|
||||
public LoanTransaction build() {
|
||||
return LoanTransaction.repayment(amount, paymentDate);
|
||||
|
||||
LoanTransaction transaction = null;
|
||||
|
||||
if (repayment) {
|
||||
transaction = LoanTransaction.repayment(transactionAmount, transactionDate);
|
||||
}
|
||||
|
||||
return transaction;
|
||||
}
|
||||
|
||||
public LoanTransactionBuilder with(Money newAmount) {
|
||||
this.amount = newAmount;
|
||||
public LoanTransactionBuilder with(final Money newAmount) {
|
||||
this.transactionAmount = newAmount;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LoanTransactionBuilder with(final LocalDate withTransactionDate) {
|
||||
this.transactionDate = withTransactionDate;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LoanTransactionBuilder repayment() {
|
||||
this.repayment = true;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user