diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm
index c2206ef0e..8639e2913 100644
--- a/api-docs/apiLive.htm
+++ b/api-docs/apiLive.htm
@@ -11296,6 +11296,12 @@ Request Body:
| Override the default value for rounding currency to multiples of value provided. |
+
+ | instalmentAmountInMultiplesOf |
+
+
+ | Override the default value for rounding instalment amount to multiples of value provided. |
+
| principal |
@@ -11402,7 +11408,12 @@ Request Body:
| Field represents percentage of current instalment principal amount for comparing against principal outstanding to add another repayment instalment. If the outstanding principal amount is less then calculated amount, remaining outstanding amount will be added to current instalment. Default value for multi disburse loan is 50% and non-multi disburse loan is 0%
-
+ |
+
+ | canDefineInstalmentAmount |
+
+
+ | if provided as true, then fixed instalment amount can be provided from loan account.
|
@@ -12786,7 +12797,7 @@ GET https://DomainName/api/v1/loanproducts/{productId}
numberOfRepaymentVariationsForBorrowerCycle,
interestRateVariationsForBorrowerCycle,
multiDisburseLoan,maxTrancheCount,
- outstandingLoanBalance,overdueDaysForNPA,holdGuaranteeFunds, principalThresholdForLastInstalment, accountMovesOutOfNPAOnlyOnArrearsCompletion
+ outstandingLoanBalance,overdueDaysForNPA,holdGuaranteeFunds, principalThresholdForLastInstalment, accountMovesOutOfNPAOnlyOnArrearsCompletion, canDefineInstalmentAmount, instalmentAmountInMultiplesOf
diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientLoanIntegrationTest.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientLoanIntegrationTest.java
index 58f9c8358..883c2c3e6 100644
--- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientLoanIntegrationTest.java
+++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientLoanIntegrationTest.java
@@ -1050,16 +1050,16 @@ public class ClientLoanIntegrationTest {
assertEquals("Checking for Due Date for 2nd Month", new ArrayList<>(Arrays.asList(2011, 11, 20)), loanSchedule.get(2)
.get("dueDate"));
- assertEquals("Checking for Principal Due for 2nd Month", new Float("2969.71"), loanSchedule.get(2).get("principalDue"));
+ assertEquals("Checking for Principal Due for 2nd Month", new Float("2969.72"), loanSchedule.get(2).get("principalDue"));
assertEquals("Checking for Interest Due for 2nd Month", new Float("181.77"), loanSchedule.get(2).get("interestOriginalDue"));
assertEquals("Checking for Due Date for 3rd Month", new ArrayList<>(Arrays.asList(2011, 12, 20)), loanSchedule.get(3)
.get("dueDate"));
- assertEquals("Checking for Principal Due for 3rd Month", new Float("3029.1"), loanSchedule.get(3).get("principalDue"));
+ assertEquals("Checking for Principal Due for 3rd Month", new Float("3029.11"), loanSchedule.get(3).get("principalDue"));
assertEquals("Checking for Interest Due for 3rd Month", new Float("122.38"), loanSchedule.get(3).get("interestOriginalDue"));
assertEquals("Checking for Due Date for 4th Month", new ArrayList<>(Arrays.asList(2012, 1, 20)), loanSchedule.get(4).get("dueDate"));
- assertEquals("Checking for Principal Due for 4th Month", new Float("3089.7"), loanSchedule.get(4).get("principalDue"));
+ assertEquals("Checking for Principal Due for 4th Month", new Float("3089.68"), loanSchedule.get(4).get("principalDue"));
assertEquals("Checking for Interest Due for 4th Month", new Float("61.79"), loanSchedule.get(4).get("interestOriginalDue"));
}
@@ -1317,9 +1317,9 @@ public class ClientLoanIntegrationTest {
validateCharge(flatInstallmentFee, loanCharges, "50", "100.00", "50.0", "50.0");
System.out.println("----------Make repayment 2------------");
- this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3251.48"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3251.49"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 November 2011",
- new JournalEntry(Float.valueOf("3251.48"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("2969.71"),
+ new JournalEntry(Float.valueOf("3251.49"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("2969.72"),
JournalEntry.TransactionType.CREDIT));
this.journalEntryHelper.checkJournalEntryForIncomeAccount(incomeAccount, "20 November 2011",
new JournalEntry(Float.valueOf("100.00"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("181.77"),
@@ -1357,9 +1357,9 @@ public class ClientLoanIntegrationTest {
JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("240"), JournalEntry.TransactionType.CREDIT));
System.out.println("----------Make repayment 3 advance------------");
- this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3301.48"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3301.49"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 November 2011",
- new JournalEntry(Float.valueOf("3301.48"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("3129.1"),
+ new JournalEntry(Float.valueOf("3301.49"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("3129.11"),
JournalEntry.TransactionType.CREDIT));
this.journalEntryHelper.checkJournalEntryForIncomeAccount(incomeAccount, "20 November 2011",
new JournalEntry(Float.valueOf("50.00"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("122.38"),
@@ -1370,7 +1370,7 @@ public class ClientLoanIntegrationTest {
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
HashMap fourthInstallment = loanSchedule.get(4);
validateNumberForEqual("100", String.valueOf(fourthInstallment.get("penaltyChargesOutstanding")));
- validateNumberForEqual("3239.70", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
+ validateNumberForEqual("3239.68", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
System.out.println("----------Pay applied penalty ------------");
this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("100"), loanID);
@@ -1382,12 +1382,12 @@ public class ClientLoanIntegrationTest {
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
fourthInstallment = loanSchedule.get(4);
validateNumberForEqual("0", String.valueOf(fourthInstallment.get("penaltyChargesOutstanding")));
- validateNumberForEqual("3139.70", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
+ validateNumberForEqual("3139.68", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
System.out.println("----------Make repayment 4 ------------");
- this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("3139.70"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("3139.68"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 January 2012", new JournalEntry(
- Float.valueOf("3139.70"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("3089.70"),
+ Float.valueOf("3139.68"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("3089.68"),
JournalEntry.TransactionType.CREDIT));
this.journalEntryHelper.checkJournalEntryForIncomeAccount(incomeAccount, "20 January 2012", new JournalEntry(
Float.valueOf("50.00"), JournalEntry.TransactionType.CREDIT));
@@ -1496,9 +1496,9 @@ public class ClientLoanIntegrationTest {
validateCharge(percentageInstallmentFee, loanCharges, "1", "61.19", "29.11", "29.70");
System.out.println("----------Make repayment 2------------");
- this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3271.48"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3271.49"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 November 2011",
- new JournalEntry(Float.valueOf("3271.48"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("2969.71"),
+ new JournalEntry(Float.valueOf("3271.49"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("2969.72"),
JournalEntry.TransactionType.CREDIT));
this.journalEntryHelper.checkJournalEntryForIncomeAccount(incomeAccount, "20 November 2011",
new JournalEntry(Float.valueOf("120.00"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("181.77"),
@@ -1536,9 +1536,9 @@ public class ClientLoanIntegrationTest {
JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("240"), JournalEntry.TransactionType.CREDIT));
System.out.println("----------Make repayment 3 advance------------");
- this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3301.77"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3301.78"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 November 2011",
- new JournalEntry(Float.valueOf("3301.77"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("3149.10"),
+ new JournalEntry(Float.valueOf("3301.78"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("3149.11"),
JournalEntry.TransactionType.CREDIT));
this.journalEntryHelper.checkJournalEntryForIncomeAccount(incomeAccount, "20 November 2011",
new JournalEntry(Float.valueOf("30.29"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("122.38"),
@@ -1549,7 +1549,7 @@ public class ClientLoanIntegrationTest {
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
HashMap fourthInstallment = loanSchedule.get(4);
validateNumberForEqual("120", String.valueOf(fourthInstallment.get("penaltyChargesOutstanding")));
- validateNumberForEqual("3240.60", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
+ validateNumberForEqual("3240.58", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
System.out.println("----------Pay applied penalty ------------");
this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("120"), loanID);
@@ -1561,12 +1561,12 @@ public class ClientLoanIntegrationTest {
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
fourthInstallment = loanSchedule.get(4);
validateNumberForEqual("0", String.valueOf(fourthInstallment.get("penaltyChargesOutstanding")));
- validateNumberForEqual("3120.60", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
+ validateNumberForEqual("3120.58", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
System.out.println("----------Make repayment 4 ------------");
- this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("3120.60"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("3120.58"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 January 2012", new JournalEntry(
- Float.valueOf("3120.60"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("3089.70"),
+ Float.valueOf("3120.58"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("3089.68"),
JournalEntry.TransactionType.CREDIT));
this.journalEntryHelper.checkJournalEntryForIncomeAccount(incomeAccount, "20 January 2012", new JournalEntry(
Float.valueOf("30.90"), JournalEntry.TransactionType.CREDIT));
@@ -1679,9 +1679,9 @@ public class ClientLoanIntegrationTest {
validateCharge(amountPlusInterestPercentageInstallmentFee, loanCharges, "1", "63.02", "31.51", "31.51");
System.out.println("----------Make repayment 2------------");
- this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3277.54"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3277.55"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 November 2011",
- new JournalEntry(Float.valueOf("3277.54"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("2969.71"),
+ new JournalEntry(Float.valueOf("3277.55"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("2969.72"),
JournalEntry.TransactionType.CREDIT));
this.journalEntryHelper.checkJournalEntryForIncomeAccount(incomeAccount, "20 November 2011",
new JournalEntry(Float.valueOf("126.06"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("181.77"),
@@ -1721,9 +1721,9 @@ public class ClientLoanIntegrationTest {
JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("240"), JournalEntry.TransactionType.CREDIT));
System.out.println("----------Make repayment 3 advance------------");
- this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3302.99"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3303"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 November 2011",
- new JournalEntry(Float.valueOf("3302.99"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("3149.10"),
+ new JournalEntry(Float.valueOf("3303"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("3149.11"),
JournalEntry.TransactionType.CREDIT));
this.journalEntryHelper.checkJournalEntryForIncomeAccount(incomeAccount, "20 November 2011",
new JournalEntry(Float.valueOf("31.51"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("122.38"),
@@ -1736,7 +1736,7 @@ public class ClientLoanIntegrationTest {
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
HashMap fourthInstallment = loanSchedule.get(4);
validateNumberForEqual("120", String.valueOf(fourthInstallment.get("penaltyChargesOutstanding")));
- validateNumberForEqual("3241.21", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
+ validateNumberForEqual("3241.19", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
System.out.println("----------Pay applied penalty ------------");
this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("120"), loanID);
@@ -1748,12 +1748,12 @@ public class ClientLoanIntegrationTest {
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
fourthInstallment = loanSchedule.get(4);
validateNumberForEqual("0", String.valueOf(fourthInstallment.get("penaltyChargesOutstanding")));
- validateNumberForEqual("3121.21", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
+ validateNumberForEqual("3121.19", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
System.out.println("----------Make repayment 4 ------------");
- this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("3121.21"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("3121.19"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 January 2012", new JournalEntry(
- Float.valueOf("3121.21"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("3089.70"),
+ Float.valueOf("3121.19"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("3089.68"),
JournalEntry.TransactionType.CREDIT));
this.journalEntryHelper.checkJournalEntryForIncomeAccount(incomeAccount, "20 January 2012", new JournalEntry(
Float.valueOf("31.51"), JournalEntry.TransactionType.CREDIT));
@@ -1878,11 +1878,11 @@ public class ClientLoanIntegrationTest {
new JournalEntry(Float.valueOf("50.0"), JournalEntry.TransactionType.DEBIT));
System.out.println("----------Make repayment 2------------");
- this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3251.48"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3251.49"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 November 2011",
- new JournalEntry(Float.valueOf("3251.48"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("100"),
+ new JournalEntry(Float.valueOf("3251.49"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("100"),
JournalEntry.TransactionType.CREDIT),
- new JournalEntry(Float.valueOf("181.77"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("2969.71"),
+ new JournalEntry(Float.valueOf("181.77"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("2969.72"),
JournalEntry.TransactionType.CREDIT));
loanSchedule.clear();
@@ -1924,11 +1924,11 @@ public class ClientLoanIntegrationTest {
JournalEntry.TransactionType.CREDIT));
System.out.println("----------Make repayment 3 advance------------");
- this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3301.48"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3301.49"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 November 2011",
- new JournalEntry(Float.valueOf("3301.48"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("50.00"),
+ new JournalEntry(Float.valueOf("3301.49"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("50.00"),
JournalEntry.TransactionType.CREDIT),
- new JournalEntry(Float.valueOf("122.38"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3129.10"),
+ new JournalEntry(Float.valueOf("122.38"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3129.11"),
JournalEntry.TransactionType.CREDIT));
this.loanTransactionHelper.addChargesForLoan(loanID, LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(
String.valueOf(flatPenaltySpecifiedDueDate), "10 January 2012", "100"));
@@ -1936,7 +1936,7 @@ public class ClientLoanIntegrationTest {
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
HashMap fourthInstallment = loanSchedule.get(4);
validateNumberForEqual("100", String.valueOf(fourthInstallment.get("penaltyChargesOutstanding")));
- validateNumberForEqual("3239.70", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
+ validateNumberForEqual("3239.68", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
System.out.println("----------Pay applied penalty ------------");
this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("100"), loanID);
@@ -1946,13 +1946,13 @@ public class ClientLoanIntegrationTest {
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
fourthInstallment = loanSchedule.get(4);
validateNumberForEqual("0", String.valueOf(fourthInstallment.get("penaltyChargesOutstanding")));
- validateNumberForEqual("3139.70", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
+ validateNumberForEqual("3139.68", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
System.out.println("----------Make over payment for repayment 4 ------------");
this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("3220.60"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 January 2012", new JournalEntry(
- Float.valueOf("3139.70"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("50.00"),
- JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3089.70"), JournalEntry.TransactionType.CREDIT));
+ Float.valueOf("3139.68"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("50.00"),
+ JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3089.68"), JournalEntry.TransactionType.CREDIT));
loanStatusHashMap = (HashMap) this.loanTransactionHelper.getLoanDetail(this.requestSpec, this.responseSpec, loanID, "status");
LoanStatusChecker.verifyLoanAccountIsOverPaid(loanStatusHashMap);
}
@@ -2072,11 +2072,11 @@ public class ClientLoanIntegrationTest {
new JournalEntry(Float.valueOf("29.7"), JournalEntry.TransactionType.DEBIT));
System.out.println("----------Make repayment 2------------");
- this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3271.48"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3271.49"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 November 2011",
- new JournalEntry(Float.valueOf("3271.48"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("120"),
+ new JournalEntry(Float.valueOf("3271.49"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("120"),
JournalEntry.TransactionType.CREDIT),
- new JournalEntry(Float.valueOf("181.77"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("2969.71"),
+ new JournalEntry(Float.valueOf("181.77"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("2969.72"),
JournalEntry.TransactionType.CREDIT));
loanSchedule.clear();
@@ -2118,11 +2118,11 @@ public class ClientLoanIntegrationTest {
JournalEntry.TransactionType.CREDIT));
System.out.println("----------Make repayment 3 advance------------");
- this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3301.77"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3301.78"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 November 2011",
- new JournalEntry(Float.valueOf("3301.77"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("30.29"),
+ new JournalEntry(Float.valueOf("3301.78"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("30.29"),
JournalEntry.TransactionType.CREDIT),
- new JournalEntry(Float.valueOf("122.38"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3149.10"),
+ new JournalEntry(Float.valueOf("122.38"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3149.11"),
JournalEntry.TransactionType.CREDIT));
this.loanTransactionHelper.addChargesForLoan(loanID, LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(
String.valueOf(percentagePenaltySpecifiedDueDate), "10 January 2012", "1"));
@@ -2130,7 +2130,7 @@ public class ClientLoanIntegrationTest {
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
HashMap fourthInstallment = loanSchedule.get(4);
validateNumberForEqual("120", String.valueOf(fourthInstallment.get("penaltyChargesOutstanding")));
- validateNumberForEqual("3240.60", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
+ validateNumberForEqual("3240.58", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
System.out.println("----------Pay applied penalty ------------");
this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("120"), loanID);
@@ -2140,13 +2140,13 @@ public class ClientLoanIntegrationTest {
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
fourthInstallment = loanSchedule.get(4);
validateNumberForEqual("0", String.valueOf(fourthInstallment.get("penaltyChargesOutstanding")));
- validateNumberForEqual("3120.60", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
+ validateNumberForEqual("3120.58", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
System.out.println("----------Make over payment for repayment 4 ------------");
- this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("3220.60"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("3220.58"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 January 2012", new JournalEntry(
- Float.valueOf("3120.60"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("30.90"),
- JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3089.70"), JournalEntry.TransactionType.CREDIT));
+ Float.valueOf("3120.58"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("30.90"),
+ JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3089.68"), JournalEntry.TransactionType.CREDIT));
loanStatusHashMap = (HashMap) this.loanTransactionHelper.getLoanDetail(this.requestSpec, this.responseSpec, loanID, "status");
LoanStatusChecker.verifyLoanAccountIsOverPaid(loanStatusHashMap);
}
@@ -2278,11 +2278,11 @@ public class ClientLoanIntegrationTest {
new JournalEntry(Float.valueOf("31.51"), JournalEntry.TransactionType.DEBIT));
System.out.println("----------Make repayment 2------------");
- this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3277.54"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3277.55"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 November 2011",
- new JournalEntry(Float.valueOf("3277.54"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("126.06"),
+ new JournalEntry(Float.valueOf("3277.55"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("126.06"),
JournalEntry.TransactionType.CREDIT),
- new JournalEntry(Float.valueOf("181.77"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("2969.71"),
+ new JournalEntry(Float.valueOf("181.77"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("2969.72"),
JournalEntry.TransactionType.CREDIT));
loanSchedule.clear();
@@ -2326,11 +2326,11 @@ public class ClientLoanIntegrationTest {
JournalEntry.TransactionType.CREDIT));
System.out.println("----------Make repayment 3 advance------------");
- this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3302.99"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3303"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 November 2011",
- new JournalEntry(Float.valueOf("3302.99"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("31.51"),
+ new JournalEntry(Float.valueOf("3303"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("31.51"),
JournalEntry.TransactionType.CREDIT),
- new JournalEntry(Float.valueOf("122.38"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3149.10"),
+ new JournalEntry(Float.valueOf("122.38"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3149.11"),
JournalEntry.TransactionType.CREDIT));
this.loanTransactionHelper.addChargesForLoan(
loanID,
@@ -2340,7 +2340,7 @@ public class ClientLoanIntegrationTest {
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
HashMap fourthInstallment = loanSchedule.get(4);
validateNumberForEqual("120", String.valueOf(fourthInstallment.get("penaltyChargesOutstanding")));
- validateNumberForEqual("3241.21", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
+ validateNumberForEqual("3241.19", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
System.out.println("----------Pay applied penalty ------------");
this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("120"), loanID);
@@ -2350,13 +2350,13 @@ public class ClientLoanIntegrationTest {
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
fourthInstallment = loanSchedule.get(4);
validateNumberForEqual("0", String.valueOf(fourthInstallment.get("penaltyChargesOutstanding")));
- validateNumberForEqual("3121.21", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
+ validateNumberForEqual("3121.19", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
System.out.println("----------Make over payment for repayment 4 ------------");
this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("3221.61"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 January 2012", new JournalEntry(
- Float.valueOf("3121.21"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("31.51"),
- JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3089.70"), JournalEntry.TransactionType.CREDIT));
+ Float.valueOf("3121.19"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("31.51"),
+ JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3089.68"), JournalEntry.TransactionType.CREDIT));
loanStatusHashMap = (HashMap) this.loanTransactionHelper.getLoanDetail(this.requestSpec, this.responseSpec, loanID, "status");
LoanStatusChecker.verifyLoanAccountIsOverPaid(loanStatusHashMap);
}
@@ -2483,11 +2483,11 @@ public class ClientLoanIntegrationTest {
checkAccrualTransactions(loanSchedule, loanID);
System.out.println("----------Make repayment 2------------");
- this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3251.48"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3251.49"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 November 2011",
- new JournalEntry(Float.valueOf("3251.48"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("100.00"),
+ new JournalEntry(Float.valueOf("3251.49"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("100.00"),
JournalEntry.TransactionType.CREDIT),
- new JournalEntry(Float.valueOf("181.77"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("2969.71"),
+ new JournalEntry(Float.valueOf("181.77"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("2969.72"),
JournalEntry.TransactionType.CREDIT));
loanSchedule.clear();
@@ -2529,11 +2529,11 @@ public class ClientLoanIntegrationTest {
JournalEntry.TransactionType.CREDIT));
System.out.println("----------Make repayment 3 advance------------");
- this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3301.48"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3301.49"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 November 2011",
- new JournalEntry(Float.valueOf("3301.48"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("50"),
+ new JournalEntry(Float.valueOf("3301.49"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("50"),
JournalEntry.TransactionType.CREDIT),
- new JournalEntry(Float.valueOf("122.38"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3129.10"),
+ new JournalEntry(Float.valueOf("122.38"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3129.11"),
JournalEntry.TransactionType.CREDIT));
this.loanTransactionHelper.addChargesForLoan(loanID, LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(
@@ -2542,7 +2542,7 @@ public class ClientLoanIntegrationTest {
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
HashMap fourthInstallment = loanSchedule.get(4);
validateNumberForEqual("100", String.valueOf(fourthInstallment.get("penaltyChargesOutstanding")));
- validateNumberForEqual("3239.70", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
+ validateNumberForEqual("3239.68", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
System.out.println("----------Pay applied penalty ------------");
this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("100"), loanID);
@@ -2552,13 +2552,13 @@ public class ClientLoanIntegrationTest {
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
fourthInstallment = loanSchedule.get(4);
validateNumberForEqual("0", String.valueOf(fourthInstallment.get("penaltyChargesOutstanding")));
- validateNumberForEqual("3139.70", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
+ validateNumberForEqual("3139.68", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
System.out.println("----------Make repayment 4 ------------");
- this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("3139.70"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("3139.68"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 January 2012", new JournalEntry(
- Float.valueOf("3139.70"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("50.00"),
- JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3089.70"), JournalEntry.TransactionType.CREDIT));
+ Float.valueOf("3139.68"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("50.00"),
+ JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3089.68"), JournalEntry.TransactionType.CREDIT));
loanStatusHashMap = (HashMap) this.loanTransactionHelper.getLoanDetail(this.requestSpec, this.responseSpec, loanID, "status");
LoanStatusChecker.verifyLoanAccountIsClosed(loanStatusHashMap);
}
@@ -2689,11 +2689,11 @@ public class ClientLoanIntegrationTest {
checkAccrualTransactions(loanSchedule, loanID);
System.out.println("----------Make repayment 2------------");
- this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3271.48"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3271.49"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 November 2011",
- new JournalEntry(Float.valueOf("3271.48"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("120"),
+ new JournalEntry(Float.valueOf("3271.49"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("120"),
JournalEntry.TransactionType.CREDIT),
- new JournalEntry(Float.valueOf("181.77"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("2969.71"),
+ new JournalEntry(Float.valueOf("181.77"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("2969.72"),
JournalEntry.TransactionType.CREDIT));
loanSchedule.clear();
@@ -2735,11 +2735,11 @@ public class ClientLoanIntegrationTest {
JournalEntry.TransactionType.CREDIT));
System.out.println("----------Make repayment 3 advance------------");
- this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3301.77"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3301.78"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 November 2011",
- new JournalEntry(Float.valueOf("3301.77"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("30.29"),
+ new JournalEntry(Float.valueOf("3301.78"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("30.29"),
JournalEntry.TransactionType.CREDIT),
- new JournalEntry(Float.valueOf("122.38"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3149.1"),
+ new JournalEntry(Float.valueOf("122.38"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3149.11"),
JournalEntry.TransactionType.CREDIT));
this.loanTransactionHelper.addChargesForLoan(loanID, LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(
@@ -2748,7 +2748,7 @@ public class ClientLoanIntegrationTest {
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
HashMap fourthInstallment = loanSchedule.get(4);
validateNumberForEqual("120", String.valueOf(fourthInstallment.get("penaltyChargesOutstanding")));
- validateNumberForEqual("3240.60", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
+ validateNumberForEqual("3240.58", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
System.out.println("----------Pay applied penalty ------------");
this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("120"), loanID);
@@ -2758,13 +2758,13 @@ public class ClientLoanIntegrationTest {
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
fourthInstallment = loanSchedule.get(4);
validateNumberForEqual("0", String.valueOf(fourthInstallment.get("penaltyChargesOutstanding")));
- validateNumberForEqual("3120.60", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
+ validateNumberForEqual("3120.58", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
System.out.println("----------Make repayment 4 ------------");
- this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("3120.60"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("3120.58"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 January 2012", new JournalEntry(
- Float.valueOf("3120.60"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("30.90"),
- JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3089.70"), JournalEntry.TransactionType.CREDIT));
+ Float.valueOf("3120.58"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("30.90"),
+ JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3089.68"), JournalEntry.TransactionType.CREDIT));
loanStatusHashMap = (HashMap) this.loanTransactionHelper.getLoanDetail(this.requestSpec, this.responseSpec, loanID, "status");
LoanStatusChecker.verifyLoanAccountIsClosed(loanStatusHashMap);
}
@@ -2899,11 +2899,11 @@ public class ClientLoanIntegrationTest {
checkAccrualTransactions(loanSchedule, loanID);
System.out.println("----------Make repayment 2------------");
- this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3277.54"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3277.55"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 November 2011",
- new JournalEntry(Float.valueOf("3277.54"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("126.06"),
+ new JournalEntry(Float.valueOf("3277.55"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("126.06"),
JournalEntry.TransactionType.CREDIT),
- new JournalEntry(Float.valueOf("181.77"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("2969.71"),
+ new JournalEntry(Float.valueOf("181.77"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("2969.72"),
JournalEntry.TransactionType.CREDIT));
loanSchedule.clear();
@@ -2947,11 +2947,11 @@ public class ClientLoanIntegrationTest {
JournalEntry.TransactionType.CREDIT));
System.out.println("----------Make repayment 3 advance------------");
- this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3302.99"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3303"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 November 2011",
- new JournalEntry(Float.valueOf("3302.99"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("31.51"),
+ new JournalEntry(Float.valueOf("3303"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("31.51"),
JournalEntry.TransactionType.CREDIT),
- new JournalEntry(Float.valueOf("122.38"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3149.1"),
+ new JournalEntry(Float.valueOf("122.38"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3149.11"),
JournalEntry.TransactionType.CREDIT));
this.loanTransactionHelper.addChargesForLoan(
@@ -2962,7 +2962,7 @@ public class ClientLoanIntegrationTest {
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
HashMap fourthInstallment = loanSchedule.get(4);
validateNumberForEqual("120", String.valueOf(fourthInstallment.get("penaltyChargesOutstanding")));
- validateNumberForEqual("3241.21", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
+ validateNumberForEqual("3241.19", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
System.out.println("----------Pay applied penalty ------------");
this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("120"), loanID);
@@ -2972,13 +2972,13 @@ public class ClientLoanIntegrationTest {
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
fourthInstallment = loanSchedule.get(4);
validateNumberForEqual("0", String.valueOf(fourthInstallment.get("penaltyChargesOutstanding")));
- validateNumberForEqual("3121.21", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
+ validateNumberForEqual("3121.19", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
System.out.println("----------Make repayment 4 ------------");
- this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("3121.21"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("3121.19"), loanID);
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 January 2012", new JournalEntry(
- Float.valueOf("3121.21"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("31.51"),
- JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3089.70"), JournalEntry.TransactionType.CREDIT));
+ Float.valueOf("3121.19"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("31.51"),
+ JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3089.68"), JournalEntry.TransactionType.CREDIT));
loanStatusHashMap = (HashMap) this.loanTransactionHelper.getLoanDetail(this.requestSpec, this.responseSpec, loanID, "status");
LoanStatusChecker.verifyLoanAccountIsClosed(loanStatusHashMap);
}
@@ -3067,16 +3067,16 @@ public class ClientLoanIntegrationTest {
HashMap secondInstallment = loanSchedule.get(2);
HashMap thirdInstallment = loanSchedule.get(3);
- validateNumberForEqual("3100", String.valueOf(secondInstallment.get("totalOutstandingForPeriod")));
- validateNumberForEqual("3100", String.valueOf(thirdInstallment.get("totalOutstandingForPeriod")));
+ validateNumberForEqual("3200", String.valueOf(secondInstallment.get("totalOutstandingForPeriod")));
+ validateNumberForEqual("3200", String.valueOf(thirdInstallment.get("totalOutstandingForPeriod")));
- validateNumberForEqual("2900", String.valueOf(secondInstallment.get("principalOutstanding")));
- validateNumberForEqual("3000", String.valueOf(thirdInstallment.get("principalOutstanding")));
+ validateNumberForEqual("3000", String.valueOf(secondInstallment.get("principalOutstanding")));
+ validateNumberForEqual("3100", String.valueOf(thirdInstallment.get("principalOutstanding")));
/***
* Make payment for installment #2
*/
- this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3300"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 November 2011", Float.valueOf("3200"), loanID);
loanSchedule.clear();
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
/***
@@ -3094,17 +3094,17 @@ public class ClientLoanIntegrationTest {
* with the excess amount
*/
thirdInstallment = loanSchedule.get(3);
- validateNumberForEqual("2900", String.valueOf(thirdInstallment.get("totalOutstandingForPeriod")));
- validateNumberForEqual("2900", String.valueOf(thirdInstallment.get("principalOutstanding")));
- validateNumberForEqual("100", String.valueOf(thirdInstallment.get("principalPaid")));
- validateNumberForEqual("100", String.valueOf(thirdInstallment.get("interestPaid")));
- validateNumberForEqual("0.00", String.valueOf(thirdInstallment.get("interestOutstanding")));
+ validateNumberForEqual("3200", String.valueOf(thirdInstallment.get("totalOutstandingForPeriod")));
+ validateNumberForEqual("3100", String.valueOf(thirdInstallment.get("principalOutstanding")));
+ validateNumberForEqual("0", String.valueOf(thirdInstallment.get("principalPaid")));
+ validateNumberForEqual("0", String.valueOf(thirdInstallment.get("interestPaid")));
+ validateNumberForEqual("100.00", String.valueOf(thirdInstallment.get("interestOutstanding")));
/***
* Make payment with due amount of 3rd installment on 4th installment
* date
*/
- this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("2900"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("3200"), loanID);
loanSchedule.clear();
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
@@ -3118,11 +3118,11 @@ public class ClientLoanIntegrationTest {
validateNumberForEqual("100", String.valueOf(thirdInstallment.get("totalOutstandingForPeriod")));
validateNumberForEqual("100", String.valueOf(thirdInstallment.get("principalOutstanding")));
- validateNumberForEqual("3100", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
+ validateNumberForEqual("2900", String.valueOf(fourthInstallment.get("totalOutstandingForPeriod")));
validateNumberForEqual("100", String.valueOf(fourthInstallment.get("interestPaid")));
validateNumberForEqual("0.00", String.valueOf(fourthInstallment.get("interestOutstanding")));
- this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("3200"), loanID);
+ this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("3000"), loanID);
/***
* verify loan is closed as we paid full amount
diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/GroupLoanIntegrationTest.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/GroupLoanIntegrationTest.java
index 158e7b3c7..387ffe2b3 100644
--- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/GroupLoanIntegrationTest.java
+++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/GroupLoanIntegrationTest.java
@@ -105,17 +105,17 @@ public class GroupLoanIntegrationTest {
assertEquals("Checking for Due Date for 2nd Month", new ArrayList<>(Arrays.asList(2011, 11, 20)),
loanSchedule.get(2).get("dueDate"));
- assertEquals("Checking for Principal Due for 2nd Month", new Float("2969.71"), loanSchedule.get(2).get("principalDue"));
+ assertEquals("Checking for Principal Due for 2nd Month", new Float("2969.72"), loanSchedule.get(2).get("principalDue"));
assertEquals("Checking for Interest Due for 2nd Month", new Float("181.77"), loanSchedule.get(2).get("interestOriginalDue"));
assertEquals("Checking for Due Date for 3rd Month", new ArrayList<>(Arrays.asList(2011, 12, 20)),
loanSchedule.get(3).get("dueDate"));
- assertEquals("Checking for Principal Due for 3rd Month", new Float("3029.1"), loanSchedule.get(3).get("principalDue"));
+ assertEquals("Checking for Principal Due for 3rd Month", new Float("3029.11"), loanSchedule.get(3).get("principalDue"));
assertEquals("Checking for Interest Due for 3rd Month", new Float("122.38"), loanSchedule.get(3).get("interestOriginalDue"));
assertEquals("Checking for Due Date for 4th Month", new ArrayList<>(Arrays.asList(2012, 1, 20)),
loanSchedule.get(4).get("dueDate"));
- assertEquals("Checking for Principal Due for 4th Month", new Float("3089.7"), loanSchedule.get(4).get("principalDue"));
+ assertEquals("Checking for Principal Due for 4th Month", new Float("3089.68"), loanSchedule.get(4).get("principalDue"));
assertEquals("Checking for Interest Due for 4th Month", new Float("61.79"), loanSchedule.get(4).get("interestOriginalDue"));
}
}
\ No newline at end of file
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/organisation/monetary/domain/Money.java b/mifosng-provider/src/main/java/org/mifosplatform/organisation/monetary/domain/Money.java
index e9e300185..076201f05 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/organisation/monetary/domain/Money.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/organisation/monetary/domain/Money.java
@@ -74,21 +74,27 @@ public class Money implements Comparable {
// round monetary amounts into multiplesof say 20/50.
if (inMultiplesOf != null && this.currencyDigitsAfterDecimal == 0 && inMultiplesOf > 0 && amountScaled.doubleValue() > 0) {
final double existingVal = amountScaled.doubleValue();
- final double ceilingOfValue = ceiling(existingVal, inMultiplesOf);
- final double floorOfValue = floor(existingVal, inMultiplesOf);
-
- final double floorDiff = existingVal - floorOfValue;
- final double ceilDiff = ceilingOfValue - existingVal;
-
- if (ceilDiff > floorDiff) {
- amountScaled = BigDecimal.valueOf(floorOfValue);
- } else {
- amountScaled = BigDecimal.valueOf(ceilingOfValue);
- }
+ amountScaled = BigDecimal.valueOf(roundToMultiplesOf(existingVal, inMultiplesOf));
}
this.amount = amountScaled.setScale(this.currencyDigitsAfterDecimal, RoundingMode.HALF_EVEN);
}
+ public static double roundToMultiplesOf(final double existingVal, final Integer inMultiplesOf) {
+ double amountScaled = existingVal;
+ final double ceilingOfValue = ceiling(existingVal, inMultiplesOf);
+ final double floorOfValue = floor(existingVal, inMultiplesOf);
+
+ final double floorDiff = existingVal - floorOfValue;
+ final double ceilDiff = ceilingOfValue - existingVal;
+
+ if (ceilDiff > floorDiff) {
+ amountScaled = floorOfValue;
+ } else {
+ amountScaled = ceilingOfValue;
+ }
+ return amountScaled;
+ }
+
public static double ceiling(final double n, final double s) {
double c;
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java
index 87ce1d5ee..db9ba90a2 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanAccountData.java
@@ -152,6 +152,8 @@ public class LoanAccountData {
private final Boolean multiDisburseLoan;
+ private final Boolean canDefineInstalmentAmount;
+
private final BigDecimal fixedEmiAmount;
private final BigDecimal maxOutstandingLoanBalance;
@@ -263,6 +265,7 @@ public class LoanAccountData {
final PortfolioAccountData linkedAccount = null;
final Collection disbursementData = null;
final Boolean multiDisburseLoan = null;
+ final Boolean canDefineInstalmentAmount = null;
final BigDecimal fixedEmiAmount = null;
final BigDecimal maxOutstandingLoanBalance = null;
final Collection emiAmountVariations = null;
@@ -293,10 +296,10 @@ public class LoanAccountData {
interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions,
fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions, calendarOptions,
syncDisbursementWithMeeting, loancounter, loanProductCounter, notes, accountLinkingOptions, linkedAccount,
- disbursementData, multiDisburseLoan, fixedEmiAmount, maxOutstandingLoanBalance, emiAmountVariations, memberVariations,
- product, inArrears, graceOnArrearsAgeing, overdueCharges, isNPA, daysInMonthType, daysInYearType,
- isInterestRecalculationEnabled, interestRecalculationData, originalSchedule, createStandingInstructionAtDisbursement,
- paidInAdvance);
+ disbursementData, multiDisburseLoan, canDefineInstalmentAmount, fixedEmiAmount, maxOutstandingLoanBalance,
+ emiAmountVariations, memberVariations, product, inArrears, graceOnArrearsAgeing, overdueCharges, isNPA, daysInMonthType,
+ daysInYearType, isInterestRecalculationEnabled, interestRecalculationData, originalSchedule,
+ createStandingInstructionAtDisbursement, paidInAdvance);
}
/**
@@ -382,6 +385,7 @@ public class LoanAccountData {
final PortfolioAccountData linkedAccount = null;
final Collection disbursementData = null;
final Boolean multiDisburseLoan = null;
+ final Boolean canDefineInstalmentAmount = null;
final BigDecimal fixedEmiAmount = null;
final BigDecimal maxOutstandingLoanBalance = null;
final Collection emiAmountVariations = null;
@@ -412,10 +416,10 @@ public class LoanAccountData {
interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions,
fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions, calendarOptions,
syncDisbursementWithMeeting, loancounter, loanProductCounter, notes, accountLinkingOptions, linkedAccount,
- disbursementData, multiDisburseLoan, fixedEmiAmount, maxOutstandingLoanBalance, emiAmountVariations, memberVariations,
- product, inArrears, graceOnArrearsAgeing, overdueCharges, isNPA, daysInMonthType, daysInYearType,
- isInterestRecalculationEnabled, interestRecalculationData, originalSchedule, createStandingInstructionAtDisbursement,
- paidInAdvance);
+ disbursementData, multiDisburseLoan, canDefineInstalmentAmount, fixedEmiAmount, maxOutstandingLoanBalance,
+ emiAmountVariations, memberVariations, product, inArrears, graceOnArrearsAgeing, overdueCharges, isNPA, daysInMonthType,
+ daysInYearType, isInterestRecalculationEnabled, interestRecalculationData, originalSchedule,
+ createStandingInstructionAtDisbursement, paidInAdvance);
}
public static LoanAccountData populateClientDefaults(final LoanAccountData acc, final LoanAccountData clientAcc) {
@@ -436,10 +440,11 @@ public class LoanAccountData {
acc.interestTypeOptions, acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null,
acc.loanOfficerOptions, acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions,
acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, acc.notes, acc.accountLinkingOptions,
- acc.linkedAccount, acc.disbursementDetails, acc.multiDisburseLoan, acc.fixedEmiAmount, acc.maxOutstandingLoanBalance,
- acc.emiAmountVariations, acc.memberVariations, acc.product, acc.inArrears, acc.graceOnArrearsAgeing, acc.overdueCharges,
- acc.isNPA, acc.daysInMonthType, acc.daysInYearType, acc.isInterestRecalculationEnabled, acc.interestRecalculationData,
- acc.originalSchedule, acc.createStandingInstructionAtDisbursement, acc.paidInAdvance);
+ acc.linkedAccount, acc.disbursementDetails, acc.multiDisburseLoan, acc.canDefineInstalmentAmount, acc.fixedEmiAmount,
+ acc.maxOutstandingLoanBalance, acc.emiAmountVariations, acc.memberVariations, acc.product, acc.inArrears,
+ acc.graceOnArrearsAgeing, acc.overdueCharges, acc.isNPA, acc.daysInMonthType, acc.daysInYearType,
+ acc.isInterestRecalculationEnabled, acc.interestRecalculationData, acc.originalSchedule,
+ acc.createStandingInstructionAtDisbursement, acc.paidInAdvance);
}
/**
@@ -526,6 +531,7 @@ public class LoanAccountData {
final PortfolioAccountData linkedAccount = null;
final Collection disbursementData = null;
final Boolean multiDisburseLoan = null;
+ final Boolean canDefineInstalmentAmount = null;
final BigDecimal fixedEmiAmount = null;
final BigDecimal maxOutstandingBalance = null;
final Collection emiAmountVariations = null;
@@ -556,9 +562,10 @@ public class LoanAccountData {
interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions,
fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions, calendarOptions,
syncDisbursementWithMeeting, loancounter, loanProductCounter, notes, accountLinkingOptions, linkedAccount,
- disbursementData, multiDisburseLoan, fixedEmiAmount, maxOutstandingBalance, emiAmountVariations, memberVariations, product,
- inArrears, graceOnArrearsAgeing, overdueCharges, isNPA, daysInMonthType, daysInYearType, isInterestRecalculationEnabled,
- interestRecalculationData, originalSchedule, createStandingInstructionAtDisbursement, paidInAdvance);
+ disbursementData, multiDisburseLoan, canDefineInstalmentAmount, fixedEmiAmount, maxOutstandingBalance, emiAmountVariations,
+ memberVariations, product, inArrears, graceOnArrearsAgeing, overdueCharges, isNPA, daysInMonthType, daysInYearType,
+ isInterestRecalculationEnabled, interestRecalculationData, originalSchedule, createStandingInstructionAtDisbursement,
+ paidInAdvance);
}
public static LoanAccountData populateGroupDefaults(final LoanAccountData acc, final LoanAccountData groupAcc) {
@@ -579,10 +586,11 @@ public class LoanAccountData {
acc.interestTypeOptions, acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null,
acc.loanOfficerOptions, acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions,
acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, acc.notes, acc.accountLinkingOptions,
- acc.linkedAccount, acc.disbursementDetails, acc.multiDisburseLoan, acc.fixedEmiAmount, acc.maxOutstandingLoanBalance,
- acc.emiAmountVariations, acc.memberVariations, acc.product, acc.inArrears, acc.graceOnArrearsAgeing, acc.overdueCharges,
- acc.isNPA, acc.daysInMonthType, acc.daysInYearType, acc.isInterestRecalculationEnabled, acc.interestRecalculationData,
- acc.originalSchedule, acc.createStandingInstructionAtDisbursement, acc.paidInAdvance);
+ acc.linkedAccount, acc.disbursementDetails, acc.multiDisburseLoan, acc.canDefineInstalmentAmount, acc.fixedEmiAmount,
+ acc.maxOutstandingLoanBalance, acc.emiAmountVariations, acc.memberVariations, acc.product, acc.inArrears,
+ acc.graceOnArrearsAgeing, acc.overdueCharges, acc.isNPA, acc.daysInMonthType, acc.daysInYearType,
+ acc.isInterestRecalculationEnabled, acc.interestRecalculationData, acc.originalSchedule,
+ acc.createStandingInstructionAtDisbursement, acc.paidInAdvance);
}
public static LoanAccountData loanProductWithTemplateDefaults(final LoanProductData product,
@@ -715,10 +723,11 @@ public class LoanAccountData {
amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions,
chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions, calendarOptions,
syncDisbursementWithMeeting, loancounter, loanProductCounter, notes, accountLinkingOptions, linkedAccount,
- disbursementData, product.getMultiDisburseLoan(), fixedEmi, product.getOutstandingLoanBalance(), emiAmountVariations,
- memberVariations, product, inArrears, product.getGraceOnArrearsAgeing(), product.overdueFeeCharges(), isNPA,
- product.getDaysInMonthType(), product.getDaysInYearType(), product.isInterestRecalculationEnabled(),
- product.toLoanInterestRecalculationData(), originalSchedule, createStandingInstructionAtDisbursement, paidInAdvance);
+ disbursementData, product.getMultiDisburseLoan(), product.canDefineInstalmentAmount(), fixedEmi,
+ product.getOutstandingLoanBalance(), emiAmountVariations, memberVariations, product, inArrears,
+ product.getGraceOnArrearsAgeing(), product.overdueFeeCharges(), isNPA, product.getDaysInMonthType(),
+ product.getDaysInYearType(), product.isInterestRecalculationEnabled(), product.toLoanInterestRecalculationData(),
+ originalSchedule, createStandingInstructionAtDisbursement, paidInAdvance);
}
public static LoanAccountData populateLoanProductDefaults(final LoanAccountData acc, final LoanProductData product) {
@@ -769,11 +778,11 @@ public class LoanAccountData {
repaymentStrategyOptions, interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions,
interestCalculationPeriodTypeOptions, fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions,
loanCollateralOptions, calendarOptions, acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, notes,
- acc.accountLinkingOptions, acc.linkedAccount, acc.disbursementDetails, product.getMultiDisburseLoan(), acc.fixedEmiAmount,
- product.getOutstandingLoanBalance(), acc.emiAmountVariations, acc.memberVariations, product, acc.inArrears,
- product.getGraceOnArrearsAgeing(), product.overdueFeeCharges(), acc.isNPA, product.getDaysInMonthType(),
- product.getDaysInYearType(), product.isInterestRecalculationEnabled(), product.toLoanInterestRecalculationData(),
- acc.originalSchedule, acc.createStandingInstructionAtDisbursement, paidInAdvance);
+ acc.accountLinkingOptions, acc.linkedAccount, acc.disbursementDetails, product.getMultiDisburseLoan(),
+ product.canDefineInstalmentAmount(), acc.fixedEmiAmount, product.getOutstandingLoanBalance(), acc.emiAmountVariations,
+ acc.memberVariations, product, acc.inArrears, product.getGraceOnArrearsAgeing(), product.overdueFeeCharges(), acc.isNPA,
+ product.getDaysInMonthType(), product.getDaysInYearType(), product.isInterestRecalculationEnabled(),
+ product.toLoanInterestRecalculationData(), acc.originalSchedule, acc.createStandingInstructionAtDisbursement, paidInAdvance);
}
/*
@@ -795,9 +804,9 @@ public class LoanAccountData {
final Integer graceOnInterestCharged, final LocalDate interestChargedFromDate, final LoanApplicationTimelineData timeline,
final LoanSummaryData loanSummary, final BigDecimal feeChargesDueAtDisbursementCharged,
final Boolean syncDisbursementWithMeeting, final Integer loancounter, final Integer loanProductCounter,
- final Boolean multiDisburseLoan, final BigDecimal fixedEmiAmont, final BigDecimal outstandingLoanBalance,
- final Boolean inArrears, final Integer graceOnArrearsAgeing, final Boolean isNPA, final EnumOptionData daysInMonthType,
- final EnumOptionData daysInYearType, final boolean isInterestRecalculationEnabled,
+ final Boolean multiDisburseLoan, Boolean canDefineInstalmentAmount, final BigDecimal fixedEmiAmont,
+ final BigDecimal outstandingLoanBalance, final Boolean inArrears, final Integer graceOnArrearsAgeing, final Boolean isNPA,
+ final EnumOptionData daysInMonthType, final EnumOptionData daysInYearType, final boolean isInterestRecalculationEnabled,
final LoanInterestRecalculationData interestRecalculationData, final Boolean createStandingInstructionAtDisbursement) {
final LoanScheduleData repaymentSchedule = null;
@@ -847,9 +856,10 @@ public class LoanAccountData {
amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions, fundOptions, chargeOptions,
chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions, calendarOptions,
syncDisbursementWithMeeting, loancounter, loanProductCounter, notes, accountLinkingOptions, linkedAccount,
- disbursementData, multiDisburseLoan, fixedEmiAmont, outstandingLoanBalance, emiAmountVariations, memberVariations, product,
- inArrears, graceOnArrearsAgeing, overdueCharges, isNPA, daysInMonthType, daysInYearType, isInterestRecalculationEnabled,
- interestRecalculationData, originalSchedule, createStandingInstructionAtDisbursement, paidInAdvance);
+ disbursementData, multiDisburseLoan, canDefineInstalmentAmount, fixedEmiAmont, outstandingLoanBalance, emiAmountVariations,
+ memberVariations, product, inArrears, graceOnArrearsAgeing, overdueCharges, isNPA, daysInMonthType, daysInYearType,
+ isInterestRecalculationEnabled, interestRecalculationData, originalSchedule, createStandingInstructionAtDisbursement,
+ paidInAdvance);
}
/*
@@ -889,9 +899,10 @@ public class LoanAccountData {
interestRateFrequencyTypeOptions, amortizationTypeOptions, interestTypeOptions, interestCalculationPeriodTypeOptions,
fundOptions, chargeOptions, chargeTemplate, loanOfficerOptions, loanPurposeOptions, loanCollateralOptions, calendarOptions,
acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, notes, accountLinkingOptions, linkedAccount,
- disbursementDetails, acc.multiDisburseLoan, acc.fixedEmiAmount, acc.maxOutstandingLoanBalance, emiAmountVariations,
- acc.memberVariations, acc.product, acc.inArrears, acc.graceOnArrearsAgeing, overdueCharges, acc.isNPA, acc.daysInMonthType,
- acc.daysInYearType, acc.isInterestRecalculationEnabled, acc.interestRecalculationData, acc.originalSchedule,
+ disbursementDetails, acc.multiDisburseLoan, acc.canDefineInstalmentAmount, acc.fixedEmiAmount,
+ acc.maxOutstandingLoanBalance, emiAmountVariations, acc.memberVariations, acc.product, acc.inArrears,
+ acc.graceOnArrearsAgeing, overdueCharges, acc.isNPA, acc.daysInMonthType, acc.daysInYearType,
+ acc.isInterestRecalculationEnabled, acc.interestRecalculationData, acc.originalSchedule,
acc.createStandingInstructionAtDisbursement, paidInAdvance);
}
@@ -924,10 +935,11 @@ public class LoanAccountData {
acc.interestTypeOptions, acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null,
acc.loanOfficerOptions, acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions,
acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, acc.notes, acc.accountLinkingOptions,
- acc.linkedAccount, acc.disbursementDetails, acc.multiDisburseLoan, acc.fixedEmiAmount, acc.maxOutstandingLoanBalance,
- acc.emiAmountVariations, acc.memberVariations, acc.product, acc.inArrears, acc.graceOnArrearsAgeing, acc.overdueCharges,
- acc.isNPA, acc.daysInMonthType, acc.daysInYearType, acc.isInterestRecalculationEnabled, acc.interestRecalculationData,
- acc.originalSchedule, acc.createStandingInstructionAtDisbursement, acc.paidInAdvance);
+ acc.linkedAccount, acc.disbursementDetails, acc.multiDisburseLoan, acc.canDefineInstalmentAmount, acc.fixedEmiAmount,
+ acc.maxOutstandingLoanBalance, acc.emiAmountVariations, acc.memberVariations, acc.product, acc.inArrears,
+ acc.graceOnArrearsAgeing, acc.overdueCharges, acc.isNPA, acc.daysInMonthType, acc.daysInYearType,
+ acc.isInterestRecalculationEnabled, acc.interestRecalculationData, acc.originalSchedule,
+ acc.createStandingInstructionAtDisbursement, acc.paidInAdvance);
}
public static LoanAccountData associateMemberVariations(final LoanAccountData acc, final Map memberLoanCycle) {
@@ -984,10 +996,11 @@ public class LoanAccountData {
acc.interestTypeOptions, acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null,
acc.loanOfficerOptions, acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions,
acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, acc.notes, acc.accountLinkingOptions,
- acc.linkedAccount, acc.disbursementDetails, acc.multiDisburseLoan, acc.fixedEmiAmount, acc.maxOutstandingLoanBalance,
- acc.emiAmountVariations, memberVariations, acc.product, acc.inArrears, acc.graceOnArrearsAgeing, acc.overdueCharges,
- acc.isNPA, acc.daysInMonthType, acc.daysInYearType, acc.isInterestRecalculationEnabled, acc.interestRecalculationData,
- acc.originalSchedule, acc.createStandingInstructionAtDisbursement, acc.paidInAdvance);
+ acc.linkedAccount, acc.disbursementDetails, acc.multiDisburseLoan, acc.canDefineInstalmentAmount, acc.fixedEmiAmount,
+ acc.maxOutstandingLoanBalance, acc.emiAmountVariations, memberVariations, acc.product, acc.inArrears,
+ acc.graceOnArrearsAgeing, acc.overdueCharges, acc.isNPA, acc.daysInMonthType, acc.daysInYearType,
+ acc.isInterestRecalculationEnabled, acc.interestRecalculationData, acc.originalSchedule,
+ acc.createStandingInstructionAtDisbursement, acc.paidInAdvance);
}
public static LoanAccountData withInterestRecalculationCalendarData(final LoanAccountData acc, final CalendarData calendarData) {
@@ -1010,10 +1023,11 @@ public class LoanAccountData {
acc.interestTypeOptions, acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null,
acc.loanOfficerOptions, acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions,
acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, acc.notes, acc.accountLinkingOptions,
- acc.linkedAccount, acc.disbursementDetails, acc.multiDisburseLoan, acc.fixedEmiAmount, acc.maxOutstandingLoanBalance,
- acc.emiAmountVariations, acc.memberVariations, acc.product, acc.inArrears, acc.graceOnArrearsAgeing, acc.overdueCharges,
- acc.isNPA, acc.daysInMonthType, acc.daysInYearType, acc.isInterestRecalculationEnabled, interestRecalculationData,
- acc.originalSchedule, acc.createStandingInstructionAtDisbursement, acc.paidInAdvance);
+ acc.linkedAccount, acc.disbursementDetails, acc.multiDisburseLoan, acc.canDefineInstalmentAmount, acc.fixedEmiAmount,
+ acc.maxOutstandingLoanBalance, acc.emiAmountVariations, acc.memberVariations, acc.product, acc.inArrears,
+ acc.graceOnArrearsAgeing, acc.overdueCharges, acc.isNPA, acc.daysInMonthType, acc.daysInYearType,
+ acc.isInterestRecalculationEnabled, interestRecalculationData, acc.originalSchedule,
+ acc.createStandingInstructionAtDisbursement, acc.paidInAdvance);
}
public static LoanAccountData withOriginalSchedule(final LoanAccountData acc, final LoanScheduleData originalSchedule) {
@@ -1034,10 +1048,11 @@ public class LoanAccountData {
acc.interestTypeOptions, acc.interestCalculationPeriodTypeOptions, acc.fundOptions, acc.chargeOptions, null,
acc.loanOfficerOptions, acc.loanPurposeOptions, acc.loanCollateralOptions, acc.calendarOptions,
acc.syncDisbursementWithMeeting, acc.loanCounter, acc.loanProductCounter, acc.notes, acc.accountLinkingOptions,
- acc.linkedAccount, acc.disbursementDetails, acc.multiDisburseLoan, acc.fixedEmiAmount, acc.maxOutstandingLoanBalance,
- acc.emiAmountVariations, acc.memberVariations, acc.product, acc.inArrears, acc.graceOnArrearsAgeing, acc.overdueCharges,
- acc.isNPA, acc.daysInMonthType, acc.daysInYearType, acc.isInterestRecalculationEnabled, acc.interestRecalculationData,
- originalSchedule, acc.createStandingInstructionAtDisbursement, acc.paidInAdvance);
+ acc.linkedAccount, acc.disbursementDetails, acc.multiDisburseLoan, acc.canDefineInstalmentAmount, acc.fixedEmiAmount,
+ acc.maxOutstandingLoanBalance, acc.emiAmountVariations, acc.memberVariations, acc.product, acc.inArrears,
+ acc.graceOnArrearsAgeing, acc.overdueCharges, acc.isNPA, acc.daysInMonthType, acc.daysInYearType,
+ acc.isInterestRecalculationEnabled, acc.interestRecalculationData, originalSchedule,
+ acc.createStandingInstructionAtDisbursement, acc.paidInAdvance);
}
private LoanAccountData(
@@ -1092,11 +1107,11 @@ public class LoanAccountData {
final Boolean syncDisbursementWithMeeting, final Integer loanCounter, final Integer loanProductCounter,
final Collection notes, final Collection accountLinkingOptions,
final PortfolioAccountData linkedAccount, final Collection disbursementDetails,
- final Boolean multiDisburseLoan, BigDecimal fixedEmiAmount, final BigDecimal maxOutstandingLoanBalance,
- final Collection emiAmountVariations, final Map memberVariations,
- final LoanProductData product, final Boolean inArrears, final Integer graceOnArrearsAgeing,
- final Collection overdueCharges, final Boolean isNPA, final EnumOptionData daysInMonthType,
- final EnumOptionData daysInYearType, final boolean isInterestRecalculationEnabled,
+ final Boolean multiDisburseLoan, final Boolean canDefineInstalmentAmount, BigDecimal fixedEmiAmount,
+ final BigDecimal maxOutstandingLoanBalance, final Collection emiAmountVariations,
+ final Map memberVariations, final LoanProductData product, final Boolean inArrears,
+ final Integer graceOnArrearsAgeing, final Collection overdueCharges, final Boolean isNPA,
+ final EnumOptionData daysInMonthType, final EnumOptionData daysInYearType, final boolean isInterestRecalculationEnabled,
final LoanInterestRecalculationData interestRecalculationData, final LoanScheduleData originalSchedule,
final Boolean createStandingInstructionAtDisbursement, final PaidInAdvanceData paidInAdvance) {
this.id = id;
@@ -1219,6 +1234,14 @@ public class LoanAccountData {
this.accountLinkingOptions = accountLinkingOptions;
this.disbursementDetails = disbursementDetails;
this.multiDisburseLoan = multiDisburseLoan;
+
+ Boolean canDefineEMIAmount = canDefineInstalmentAmount;
+ if (canDefineInstalmentAmount == null) {
+ canDefineEMIAmount = multiDisburseLoan;
+ } else if (multiDisburseLoan != null) {
+ canDefineEMIAmount = canDefineInstalmentAmount || multiDisburseLoan;
+ }
+ this.canDefineInstalmentAmount = canDefineEMIAmount;
this.fixedEmiAmount = fixedEmiAmount;
this.maxOutstandingLoanBalance = maxOutstandingLoanBalance;
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java
index 650d33012..64d4d2314 100755
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java
@@ -24,7 +24,6 @@ import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
-import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
@@ -1388,9 +1387,6 @@ public class Loan extends AbstractPersistable {
if (loanProduct.isMultiDisburseLoan()) {
updateDisbursementDetails(command, actualChanges);
- if (command.isChangeInBigDecimalParameterNamed(LoanApiConstants.emiAmountParameterName, this.fixedEmiAmount)) {
- this.fixedEmiAmount = command.bigDecimalValueOfParameterNamed(LoanApiConstants.emiAmountParameterName);
- }
if (command.isChangeInBigDecimalParameterNamed(LoanApiConstants.maxOutstandingBalanceParameterName,
this.maxOutstandingLoanBalance)) {
this.maxOutstandingLoanBalance = command
@@ -1407,6 +1403,15 @@ public class Loan extends AbstractPersistable {
}
} else {
this.disbursementDetails.clear();
+ }
+
+ if (loanProduct.isMultiDisburseLoan() || loanProduct.canDefineInstalmentAmount()) {
+ if (command.isChangeInBigDecimalParameterNamed(LoanApiConstants.emiAmountParameterName, this.fixedEmiAmount)) {
+ this.fixedEmiAmount = command.bigDecimalValueOfParameterNamed(LoanApiConstants.emiAmountParameterName);
+ actualChanges.put(LoanApiConstants.emiAmountParameterName, this.fixedEmiAmount);
+ actualChanges.put("recalculateLoanSchedule", true);
+ }
+ } else {
this.fixedEmiAmount = null;
}
@@ -2066,10 +2071,15 @@ public class Loan extends AbstractPersistable {
public void regenerateScheduleOnDisbursement(final ScheduleGeneratorDTO scheduleGeneratorDTO, final boolean recalculateSchedule,
final LocalDate actualDisbursementDate, BigDecimal emiAmount, final AppUser currentUser) {
boolean isEmiAmountChanged = false;
- if (this.loanProduct.isMultiDisburseLoan() && emiAmount != null && emiAmount.compareTo(retriveLastEmiAmount()) != 0) {
- LoanTermVariations loanVariationTerms = new LoanTermVariations(LoanTermVariationType.EMI_AMOUNT.getValue(),
- actualDisbursementDate.toDate(), emiAmount, this);
- this.loanTermVariations.add(loanVariationTerms);
+ if ((this.loanProduct.isMultiDisburseLoan() || this.loanProduct.canDefineInstalmentAmount()) && emiAmount != null
+ && emiAmount.compareTo(retriveLastEmiAmount()) != 0) {
+ if (this.loanProduct.isMultiDisburseLoan()) {
+ LoanTermVariations loanVariationTerms = new LoanTermVariations(LoanTermVariationType.EMI_AMOUNT.getValue(),
+ actualDisbursementDate.toDate(), emiAmount, this);
+ this.loanTermVariations.add(loanVariationTerms);
+ } else {
+ this.fixedEmiAmount = emiAmount;
+ }
isEmiAmountChanged = true;
}
@@ -2306,7 +2316,7 @@ public class Loan extends AbstractPersistable {
getExpectedFirstRepaymentOnDate(), scheduleGeneratorDTO.getCalculatedRepaymentsStartingFromDate(), getInArrearsTolerance(),
this.loanRepaymentScheduleDetail, this.loanProduct.isMultiDisburseLoan(), this.fixedEmiAmount, disbursementData,
this.maxOutstandingLoanBalance, loanVariationTermsData, getInterestChargedFromDate(),
- this.loanProduct.getPrincipalThresholdForLastInstalment());
+ this.loanProduct.getPrincipalThresholdForLastInstalment(), this.loanProduct.getInstalmentAmountInMultiplesOf());
final LoanScheduleModel loanSchedule = loanScheduleGenerator.generate(mc, loanApplicationTerms, charges(),
scheduleGeneratorDTO.getHolidayDetailDTO());
@@ -4640,7 +4650,7 @@ public class Loan extends AbstractPersistable {
this.loanProduct.isMultiDisburseLoan(), this.fixedEmiAmount, disbursementData, this.maxOutstandingLoanBalance,
loanVariationTermsData, getInterestChargedFromDate(), this.loanInterestRecalculationDetails,
calendarInstanceForInterestRecalculation, recalculationFrequencyType,
- this.loanProduct.getPrincipalThresholdForLastInstalment());
+ this.loanProduct.getPrincipalThresholdForLastInstalment(), this.loanProduct.getInstalmentAmountInMultiplesOf());
return loanApplicationTerms;
}
@@ -4684,7 +4694,7 @@ public class Loan extends AbstractPersistable {
loanTermPeriodFrequencyType, nthDayType, dayOfWeekType, getDisbursementDate(), getExpectedFirstRepaymentOnDate(), null,
getInArrearsTolerance(), this.loanRepaymentScheduleDetail, this.loanProduct.isMultiDisburseLoan(), this.fixedEmiAmount,
disbursementData, this.maxOutstandingLoanBalance, loanVariationTermsData, getInterestChargedFromDate(),
- this.loanProduct.getPrincipalThresholdForLastInstalment());
+ this.loanProduct.getPrincipalThresholdForLastInstalment(), this.loanProduct.getInstalmentAmountInMultiplesOf());
installment = loanScheduleGenerator.calculatePrepaymentAmount(this.repaymentScheduleInstallments, getCurrency(),
LocalDate.now(), getInterestChargedFromDate(), loanApplicationTerms, mc, charges());
@@ -4886,7 +4896,7 @@ public class Loan extends AbstractPersistable {
dayOfWeekType, expectedDisbursementDate, repaymentsStartingFromDate, calculatedRepaymentsStartingFromDate,
inArrearsToleranceMoney, this.loanRepaymentScheduleDetail, loanProduct.isMultiDisburseLoan(), emiAmount, disbursementData,
maxOutstandingBalance, loanVariationTermsData, interestChargedFromDate,
- this.loanProduct.getPrincipalThresholdForLastInstalment());
+ this.loanProduct.getPrincipalThresholdForLastInstalment(), this.loanProduct.getInstalmentAmountInMultiplesOf());
}
/**
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java
index 8b0a7b649..02673ec6b 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java
@@ -117,7 +117,6 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
outstandingBalance = outstandingBalance.zero().plus(disburseAmt);
}
Money reducePrincipal = totalCumulativePrincipal.zero();
- Money fixedEmiAmount = totalCumulativePrincipal.zero();
int daysCalcForInstallmentNumber = 0;
LocalDate scheduleStartDateAsPerFrequency = periodStartDate;
while (!outstandingBalance.isZero()) {
@@ -191,7 +190,6 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
BigDecimal disburseAmt = BigDecimal.ZERO;
if (loanApplicationTerms.isMultiDisburseLoan()) {
loanApplicationTerms.setFixedEmiAmountForPeriod(scheduledDueDate);
- fixedEmiAmount = fixedEmiAmount.zero().plus(loanApplicationTerms.getFixedEmiAmount());
final Collection disbursementDatas = new ArrayList<>();
LocalDate tillDate = scheduledDueDate;
if (prepayDate != null && prepayDate.isBefore(tillDate)) {
@@ -233,16 +231,12 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
if (!loanApplicationTerms.isMultiDisburseLoan()) {
loanApplicationTerms.setFixedEmiAmount(null);
}
- fixedEmiAmount = fixedEmiAmount.zero();
outstandingBalance = outstandingBalance.minus(reducePrincipal);
balanceForcalculation = balanceForcalculation.minus(reducePrincipal);
totalCumulativePrincipal = totalCumulativePrincipal.plus(reducePrincipal);
reducePrincipal = reducePrincipal.zero();
break;
case REDUCE_NUMBER_OF_INSTALLMENTS:
- if (fixedEmiAmount.isGreaterThanZero()) {
- loanApplicationTerms.setFixedEmiAmount(fixedEmiAmount.getAmount());
- }
outstandingBalance = outstandingBalance.minus(reducePrincipal);
balanceForcalculation = balanceForcalculation.minus(reducePrincipal);
totalCumulativePrincipal = totalCumulativePrincipal.plus(reducePrincipal);
@@ -385,14 +379,10 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
// Exclude principal portion for interest only installments
if (!recalculatedInterestComponent) {
principalForThisPeriod = principalInterestForThisPeriod.principal();
- if (diffAmt != null && !diffAmt.isEmpty() && loanApplicationTerms.getAmortizationMethod().isEqualInstallment()) {
- Money principalToBeAdjust = principalForThisPeriod.zero();
- if (fixedEmiAmount.isZero()) {
- principalToBeAdjust = principalInterestForThisPeriod.interest().minus(interestForThisinstallment);
-
- } else {
- principalToBeAdjust = fixedEmiAmount.minus(principalForThisPeriod).minus(interestForThisinstallment);
- }
+ if (((diffAmt != null && !diffAmt.isEmpty()) || interestToBeAdded.compareTo(BigDecimal.ZERO) == 1)
+ && loanApplicationTerms.getAmortizationMethod().isEqualInstallment()) {
+ Money principalToBeAdjust = Money.of(currency, loanApplicationTerms.getFixedEmiAmount()).minus(principalForThisPeriod)
+ .minus(interestForThisinstallment);
principalForThisPeriod = principalForThisPeriod.plus(principalToBeAdjust);
principalForThisPeriod = loanApplicationTerms.adjustPrincipalIfLastRepaymentPeriod(principalForThisPeriod,
totalCumulativePrincipal.plus(principalForThisPeriod), periodNumber);
@@ -407,9 +397,6 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
}
}
- if (fixedEmiAmount.isZero() && !recalculatedInterestComponent) {
- fixedEmiAmount = principalForThisPeriod.plus(interestForThisinstallment);
- }
reducePrincipal = reducePrincipal.minus(reducePrincipalForCurrentInstallment);
if (principalForThisPeriod.isGreaterThan(reducePrincipalForCurrentInstallment)) {
@@ -543,6 +530,8 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
}
}
+ loanApplicationTerms.resetFixedEmiAmount();
+
return LoanScheduleModel.from(periods, applicationCurrency, loanTermInDays, principalDisbursed, totalPrincipalExpected,
totalPrincipalPaid, totalInterestCharged, totalFeeChargesCharged, totalPenaltyChargesCharged, totalRepaymentExpected,
totalOutstanding);
@@ -794,12 +783,12 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
Money principalDue = Money.of(currency, period.principalDue());
Money interestDue = Money.of(currency, period.interestDue());
-
- if(principalDue.isZero() && interestDue.isZero()) {
+
+ if (principalDue.isZero() && interestDue.isZero()) {
period.updateFeeChargesDue(Money.zero(currency));
period.updatePenaltyChargesDue(Money.zero(currency));
}
-
+
Money feeChargesDue = Money.of(currency, period.feeChargesDue());
Money penaltyChargesDue = Money.of(currency, period.penaltyChargesDue());
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
index 37527700c..93bedc3c9 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
@@ -112,6 +112,8 @@ public final class LoanApplicationTerms {
private BigDecimal fixedEmiAmount;
+ private final BigDecimal actualFixedEmiAmount;
+
private final BigDecimal maxOutstandingBalance;
private final List emiAmountVariations;
@@ -133,6 +135,7 @@ public final class LoanApplicationTerms {
private final RecalculationFrequencyType recalculationFrequencyType;
private final BigDecimal principalThresholdForLastInstalment;
+ private final Integer instalmentAmountInMultiplesOf;
public static LoanApplicationTerms assembleFrom(final ApplicationCurrency currency, final Integer loanTermFrequency,
final PeriodFrequencyType loanTermPeriodFrequencyType, final Integer numberOfRepayments, final Integer repaymentEvery,
@@ -147,7 +150,7 @@ public final class LoanApplicationTerms {
final List disbursementDatas, final BigDecimal maxOutstandingBalance,
final List emiAmountVariations, final Integer graceOnArrearsAgeing,
final DaysInMonthType daysInMonthType, final DaysInYearType daysInYearType, final boolean isInterestRecalculationEnabled,
- BigDecimal principalThresholdForLastInstalment) {
+ BigDecimal principalThresholdForLastInstalment, Integer instalmentAmountInMultiplesOf) {
final LoanRescheduleStrategyMethod rescheduleStrategyMethod = null;
final InterestRecalculationCompoundingMethod interestRecalculationCompoundingMethod = null;
@@ -160,7 +163,7 @@ public final class LoanApplicationTerms {
graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, inArrearsTolerance, multiDisburseLoan, emiAmount,
disbursementDatas, maxOutstandingBalance, emiAmountVariations, graceOnArrearsAgeing, daysInMonthType, daysInYearType,
isInterestRecalculationEnabled, rescheduleStrategyMethod, interestRecalculationCompoundingMethod, restCalendarInstance,
- recalculationFrequencyType, principalThresholdForLastInstalment);
+ recalculationFrequencyType, principalThresholdForLastInstalment, instalmentAmountInMultiplesOf);
}
public static LoanApplicationTerms assembleFrom(final ApplicationCurrency applicationCurrency, final Integer loanTermFrequency,
@@ -170,7 +173,7 @@ public final class LoanApplicationTerms {
final LoanProductRelatedDetail loanProductRelatedDetail, final boolean multiDisburseLoan, final BigDecimal emiAmount,
final List disbursementDatas, final BigDecimal maxOutstandingBalance,
final List emiAmountVariations, final LocalDate interestChargedFromDate,
- final BigDecimal principalThresholdForLastInstalment) {
+ final BigDecimal principalThresholdForLastInstalment, Integer instalmentAmountInMultiplesOf) {
final Integer numberOfRepayments = loanProductRelatedDetail.getNumberOfRepayments();
final Integer repaymentEvery = loanProductRelatedDetail.getRepayEvery();
@@ -206,7 +209,7 @@ public final class LoanApplicationTerms {
multiDisburseLoan, emiAmount, disbursementDatas, maxOutstandingBalance, emiAmountVariations,
loanProductRelatedDetail.getGraceOnDueDate(), daysInMonthType, daysInYearType, isInterestRecalculationEnabled,
rescheduleStrategyMethod, interestRecalculationCompoundingMethod, restCalendarInstance, recalculationFrequencyType,
- principalThresholdForLastInstalment);
+ principalThresholdForLastInstalment, instalmentAmountInMultiplesOf);
}
public static LoanApplicationTerms assembleFrom(final ApplicationCurrency applicationCurrency, final Integer loanTermFrequency,
@@ -216,7 +219,8 @@ public final class LoanApplicationTerms {
final BigDecimal emiAmount, final List disbursementDatas, final BigDecimal maxOutstandingBalance,
final List emiAmountVariations, final LocalDate interestChargedFromDate,
final LoanInterestRecalculationDetails interestRecalculationDetails, final CalendarInstance restCalendarInstance,
- final RecalculationFrequencyType recalculationFrequencyType, final BigDecimal principalThresholdForLastInstalment) {
+ final RecalculationFrequencyType recalculationFrequencyType, final BigDecimal principalThresholdForLastInstalment,
+ Integer instalmentAmountInMultiplesOf) {
final Integer numberOfRepayments = loanProductRelatedDetail.getNumberOfRepayments();
final Integer repaymentEvery = loanProductRelatedDetail.getRepayEvery();
@@ -254,7 +258,7 @@ public final class LoanApplicationTerms {
disbursementDatas, maxOutstandingBalance, emiAmountVariations, loanProductRelatedDetail.getGraceOnDueDate(),
daysInMonthType, daysInYearType, isInterestRecalculationEnabled, rescheduleStrategyMethod,
interestRecalculationCompoundingMethod, restCalendarInstance, recalculationFrequencyType,
- principalThresholdForLastInstalment);
+ principalThresholdForLastInstalment, instalmentAmountInMultiplesOf);
}
public static LoanApplicationTerms assembleFrom(final Integer repaymentEvery, final PeriodFrequencyType repaymentPeriodFrequencyType,
@@ -272,7 +276,8 @@ public final class LoanApplicationTerms {
applicationTerms.graceOnArrearsAgeing, applicationTerms.daysInMonthType, applicationTerms.daysInYearType,
applicationTerms.interestRecalculationEnabled, applicationTerms.rescheduleStrategyMethod,
applicationTerms.interestRecalculationCompoundingMethod, applicationTerms.restCalendarInstance,
- applicationTerms.recalculationFrequencyType, applicationTerms.principalThresholdForLastInstalment);
+ applicationTerms.recalculationFrequencyType, applicationTerms.principalThresholdForLastInstalment,
+ applicationTerms.instalmentAmountInMultiplesOf);
}
private LoanApplicationTerms(final ApplicationCurrency currency, final Integer loanTermFrequency,
@@ -290,7 +295,7 @@ public final class LoanApplicationTerms {
final boolean isInterestRecalculationEnabled, final LoanRescheduleStrategyMethod rescheduleStrategyMethod,
final InterestRecalculationCompoundingMethod interestRecalculationCompoundingMethod,
final CalendarInstance restCalendarInstance, final RecalculationFrequencyType recalculationFrequencyType,
- final BigDecimal principalThresholdForLastInstalment) {
+ final BigDecimal principalThresholdForLastInstalment, final Integer instalmentAmountInMultiplesOf) {
this.currency = currency;
this.loanTermFrequency = loanTermFrequency;
this.loanTermPeriodFrequencyType = loanTermPeriodFrequencyType;
@@ -320,6 +325,7 @@ public final class LoanApplicationTerms {
this.inArrearsTolerance = inArrearsTolerance;
this.multiDisburseLoan = multiDisburseLoan;
this.fixedEmiAmount = emiAmount;
+ this.actualFixedEmiAmount = emiAmount;
this.disbursementDatas = disbursementDatas;
this.maxOutstandingBalance = maxOutstandingBalance;
this.emiAmountVariations = emiAmountVariations;
@@ -332,6 +338,7 @@ public final class LoanApplicationTerms {
this.restCalendarInstance = restCalendarInstance;
this.recalculationFrequencyType = recalculationFrequencyType;
this.principalThresholdForLastInstalment = principalThresholdForLastInstalment;
+ this.instalmentAmountInMultiplesOf = instalmentAmountInMultiplesOf;
}
public Money adjustPrincipalIfLastRepaymentPeriod(final Money principalForPeriod, final Money totalCumulativePrincipalToDate,
@@ -517,15 +524,6 @@ public final class LoanApplicationTerms {
return periodNumber == numberOfRepayments;
}
- private Money calculateTotalDueForEqualInstallmentLoan(final BigDecimal periodicInterestRate) {
-
- final int periodsElapsed = 0;
- final double paymentPerRepaymentPeriod = paymentPerPeriod(periodicInterestRate, this.principal, periodsElapsed);
- double totalRepayment = paymentPerRepaymentPeriod * this.numberOfRepayments;
-
- return Money.of(this.principal.getCurrency(), BigDecimal.valueOf(totalRepayment));
- }
-
/**
* general method to calculate totalInterestDue discounting any grace
* settings
@@ -810,14 +808,21 @@ public final class LoanApplicationTerms {
private double paymentPerPeriod(final BigDecimal periodicInterestRate, final Money balance, final int periodsElapsed) {
- if (fixedEmiAmount != null) { return fixedEmiAmount.doubleValue(); }
- final double futureValue = 0;
- final double principalDouble = balance.getAmount().multiply(BigDecimal.valueOf(-1)).doubleValue();
+ if (this.fixedEmiAmount == null) {
+ final double futureValue = 0;
+ final double principalDouble = balance.getAmount().multiply(BigDecimal.valueOf(-1)).doubleValue();
- final Integer periodsRemaining = this.numberOfRepayments - periodsElapsed;
+ final Integer periodsRemaining = this.numberOfRepayments - periodsElapsed;
- return FinanicalFunctions.pmt(periodicInterestRate.doubleValue(), periodsRemaining.doubleValue(), principalDouble, futureValue,
- false);
+ double installmentAmount = FinanicalFunctions.pmt(periodicInterestRate.doubleValue(), periodsRemaining.doubleValue(),
+ principalDouble, futureValue, false);
+
+ if (this.instalmentAmountInMultiplesOf != null) {
+ installmentAmount = Money.roundToMultiplesOf(installmentAmount, this.instalmentAmountInMultiplesOf);
+ }
+ setFixedEmiAmount(BigDecimal.valueOf(installmentAmount));
+ }
+ return this.fixedEmiAmount.doubleValue();
}
private Money calculateDecliningInterestDueForInstallmentBeforeApplyingGrace(final PaymentPeriodsInOneYearCalculator calculator,
@@ -1023,6 +1028,10 @@ public final class LoanApplicationTerms {
this.fixedEmiAmount = fixedEmiAmount;
}
+ public void resetFixedEmiAmount() {
+ this.fixedEmiAmount = this.actualFixedEmiAmount;
+ }
+
public LoanRescheduleStrategyMethod getLoanRescheduleStrategyMethod() {
return LoanRescheduleStrategyMethod.REDUCE_EMI_AMOUNT;
}
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
index 08e961184..fa882351b 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
@@ -199,8 +199,8 @@ public class LoanScheduleAssembler {
}
/*
- * If it is JLG loan/Group Loan synched with a meeting, then make sure first
- * repayment falls on meeting date
+ * If it is JLG loan/Group Loan synched with a meeting, then make sure
+ * first repayment falls on meeting date
*/
if ((loanType.isJLGAccount() || loanType.isGroupAccount()) && calendar != null) {
validateRepaymentsStartDateWithMeetingDates(calculatedRepaymentsStartingFromDate, calendar);
@@ -249,8 +249,9 @@ public class LoanScheduleAssembler {
final DaysInYearType daysInYearType = loanProduct.fetchDaysInYearType();
final boolean isInterestRecalculationEnabled = loanProduct.isInterestRecalculationEnabled();
-
+
final BigDecimal principalThresholdForLastInstalment = loanProduct.getPrincipalThresholdForLastInstalment();
+ final Integer instalmentAmountInMultiplesOf = loanProduct.getInstalmentAmountInMultiplesOf();
return LoanApplicationTerms.assembleFrom(applicationCurrency, loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments,
repaymentEvery, repaymentPeriodFrequencyType, nthDay, weekDayType, amortizationMethod, interestMethod,
@@ -258,7 +259,8 @@ public class LoanScheduleAssembler {
principalMoney, expectedDisbursementDate, repaymentsStartingFromDate, calculatedRepaymentsStartingFromDate,
graceOnPrincipalPayment, graceOnInterestPayment, graceOnInterestCharged, interestChargedFromDate, inArrearsToleranceMoney,
loanProduct.isMultiDisburseLoan(), emiAmount, disbursementDatas, maxOutstandingBalance, loanVariationTermsData,
- graceOnArrearsAgeing, daysInMonthType, daysInYearType, isInterestRecalculationEnabled, principalThresholdForLastInstalment);
+ graceOnArrearsAgeing, daysInMonthType, daysInYearType, isInterestRecalculationEnabled, principalThresholdForLastInstalment,
+ instalmentAmountInMultiplesOf);
}
private List fetchDisbursementData(final JsonObject command) {
@@ -444,7 +446,7 @@ public class LoanScheduleAssembler {
final LocalDate dateBasedOnMinimumDaysBetweenDisbursalAndFirstRepayment = expectedDisbursementDate
.plusDays(minimumDaysBetweenDisbursalAndFirstRepayment);
- if ((loanType.isJLGAccount()|| loanType.isGroupAccount()) && calendar != null) {
+ if ((loanType.isJLGAccount() || loanType.isGroupAccount()) && calendar != null) {
final LocalDate refernceDateForCalculatingFirstRepaymentDate = expectedDisbursementDate;
derivedFirstRepayment = deriveFirstRepaymentDateForJLGLoans(repaymentEvery, expectedDisbursementDate,
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformServiceImpl.java
index f8942ddc1..dcda24532 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformServiceImpl.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/loanschedule/service/LoanScheduleCalculationPlatformServiceImpl.java
@@ -95,19 +95,19 @@ public class LoanScheduleCalculationPlatformServiceImpl implements LoanScheduleC
* TODO: Vishwas, this is probably not required, test and remove the
* same
**/
+ final Long productId = this.fromJsonHelper.extractLongNamed("productId", query.parsedJson());
+ final LoanProduct loanProduct = this.loanProductRepository.findOne(productId);
+ if (loanProduct == null) { throw new LoanProductNotFoundException(productId); }
+
if (validateParams) {
boolean isMeetingMandatoryForJLGLoans = configurationDomainService.isMeetingMandatoryForJLGLoans();
- this.loanApiJsonDeserializer.validateForCreate(query.json(), isMeetingMandatoryForJLGLoans);
+ this.loanApiJsonDeserializer.validateForCreate(query.json(), isMeetingMandatoryForJLGLoans, loanProduct);
}
this.fromApiJsonDeserializer.validate(query.json());
final List dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan");
- final Long productId = this.fromJsonHelper.extractLongNamed("productId", query.parsedJson());
- final LoanProduct loanProduct = this.loanProductRepository.findOne(productId);
- if (loanProduct == null) { throw new LoanProductNotFoundException(productId); }
-
if (loanProduct.useBorrowerCycle()) {
final Long clientId = this.fromJsonHelper.extractLongNamed("clientId", query.parsedJson());
final Long groupId = this.fromJsonHelper.extractLongNamed("groupId", query.parsedJson());
diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java
index 9cf83f342..9093805a6 100644
--- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java
+++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonHelper.java
@@ -21,6 +21,7 @@ import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
+import org.mifosplatform.infrastructure.core.exception.UnsupportedParameterException;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.portfolio.accountdetails.domain.AccountType;
import org.mifosplatform.portfolio.loanaccount.api.LoanApiConstants;
@@ -78,7 +79,7 @@ public final class LoanApplicationCommandFromApiJsonHelper {
this.apiJsonHelper = apiJsonHelper;
}
- public void validateForCreate(final String json, final boolean isMeetingMandatoryForJLGLoans) {
+ public void validateForCreate(final String json, final boolean isMeetingMandatoryForJLGLoans, final LoanProduct loanProduct) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken