Merge pull request #1082 from pramodn02/develop

interest recalculation test cases + fixes
This commit is contained in:
Vishwas Babu A J
2014-09-23 14:56:10 -07:00
4 changed files with 197 additions and 49 deletions
@@ -29,6 +29,7 @@ import org.mifosplatform.integrationtests.common.accounting.Account;
import org.mifosplatform.integrationtests.common.accounting.AccountHelper; import org.mifosplatform.integrationtests.common.accounting.AccountHelper;
import org.mifosplatform.integrationtests.common.accounting.JournalEntry; import org.mifosplatform.integrationtests.common.accounting.JournalEntry;
import org.mifosplatform.integrationtests.common.accounting.JournalEntryHelper; import org.mifosplatform.integrationtests.common.accounting.JournalEntryHelper;
import org.mifosplatform.integrationtests.common.accounting.PeriodicAccrualAccountingHelper;
import org.mifosplatform.integrationtests.common.charges.ChargesHelper; import org.mifosplatform.integrationtests.common.charges.ChargesHelper;
import org.mifosplatform.integrationtests.common.loans.LoanApplicationTestBuilder; import org.mifosplatform.integrationtests.common.loans.LoanApplicationTestBuilder;
import org.mifosplatform.integrationtests.common.loans.LoanProductTestBuilder; import org.mifosplatform.integrationtests.common.loans.LoanProductTestBuilder;
@@ -66,6 +67,7 @@ public class ClientLoanIntegrationTest {
private JournalEntryHelper journalEntryHelper; private JournalEntryHelper journalEntryHelper;
private AccountHelper accountHelper; private AccountHelper accountHelper;
private SchedulerJobHelper schedulerJobHelper; private SchedulerJobHelper schedulerJobHelper;
private PeriodicAccrualAccountingHelper periodicAccrualAccountingHelper;
@Before @Before
public void setup() { public void setup() {
@@ -3139,7 +3141,7 @@ public class ClientLoanIntegrationTest {
final Integer loanProductID = createLoanProductWithInterestRecalculation(LoanProductTestBuilder.MIFOS_STANDARD_STRATEGY, final Integer loanProductID = createLoanProductWithInterestRecalculation(LoanProductTestBuilder.MIFOS_STANDARD_STRATEGY,
LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_NONE, LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_NONE,
LoanProductTestBuilder.RECALCULATION_STRATEGY_REDUCE_EMI_AMOUN, LoanProductTestBuilder.RECALCULATION_STRATEGY_REDUCE_EMI_AMOUN,
LoanProductTestBuilder.RECALCULATION_FREQUENCY_TYPE_SAME_AS_REPAYMENT_PERIOD, "0", null); LoanProductTestBuilder.RECALCULATION_FREQUENCY_TYPE_SAME_AS_REPAYMENT_PERIOD, "0", null,null);
final Integer loanID = applyForLoanApplicationForInterestRecalculation(clientID, loanProductID, LOAN_DISBURSEMENT_DATE, null, final Integer loanID = applyForLoanApplicationForInterestRecalculation(clientID, loanProductID, LOAN_DISBURSEMENT_DATE, null,
LoanApplicationTestBuilder.MIFOS_STANDARD_STRATEGY, new ArrayList<HashMap>(0)); LoanApplicationTestBuilder.MIFOS_STANDARD_STRATEGY, new ArrayList<HashMap>(0));
@@ -3204,6 +3206,7 @@ public class ClientLoanIntegrationTest {
addRepaymentValues(expectedvalues, todaysDate, 1, "1771.88", "16.39", "0.0", "0.0"); addRepaymentValues(expectedvalues, todaysDate, 1, "1771.88", "16.39", "0.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "1780.05", "8.22", "0.0", "0.0"); addRepaymentValues(expectedvalues, todaysDate, 1, "1780.05", "8.22", "0.0", "0.0");
verifyLoanRepaymentSchedule(loanSchedule, expectedvalues); verifyLoanRepaymentSchedule(loanSchedule, expectedvalues);
HashMap prepayDetail = this.loanTransactionHelper.getPrepayAmount(this.requestSpec, this.responseSpec, loanID); HashMap prepayDetail = this.loanTransactionHelper.getPrepayAmount(this.requestSpec, this.responseSpec, loanID);
String prepayAmount = String.valueOf(prepayDetail.get("amount")); String prepayAmount = String.valueOf(prepayDetail.get("amount"));
todaysDate = Calendar.getInstance(); todaysDate = Calendar.getInstance();
@@ -3228,7 +3231,7 @@ public class ClientLoanIntegrationTest {
final Integer loanProductID = createLoanProductWithInterestRecalculation(LoanProductTestBuilder.RBI_INDIA_STRATEGY, final Integer loanProductID = createLoanProductWithInterestRecalculation(LoanProductTestBuilder.RBI_INDIA_STRATEGY,
LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_INTEREST, LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_INTEREST,
LoanProductTestBuilder.RECALCULATION_STRATEGY_REDUCE_NUMBER_OF_INSTALLMENTS, LoanProductTestBuilder.RECALCULATION_STRATEGY_REDUCE_NUMBER_OF_INSTALLMENTS,
LoanProductTestBuilder.RECALCULATION_FREQUENCY_TYPE_DAILY, "1", LOAN_DISBURSEMENT_DATE); LoanProductTestBuilder.RECALCULATION_FREQUENCY_TYPE_DAILY, "1", LOAN_DISBURSEMENT_DATE,null);
final Integer loanID = applyForLoanApplicationForInterestRecalculation(clientID, loanProductID, LOAN_DISBURSEMENT_DATE, final Integer loanID = applyForLoanApplicationForInterestRecalculation(clientID, loanProductID, LOAN_DISBURSEMENT_DATE,
LOAN_DISBURSEMENT_DATE, LoanApplicationTestBuilder.RBI_INDIA_STRATEGY, new ArrayList<HashMap>(0)); LOAN_DISBURSEMENT_DATE, LoanApplicationTestBuilder.RBI_INDIA_STRATEGY, new ArrayList<HashMap>(0));
@@ -3266,6 +3269,15 @@ public class ClientLoanIntegrationTest {
verifyLoanRepaymentSchedule(loanSchedule, expectedvalues); verifyLoanRepaymentSchedule(loanSchedule, expectedvalues);
loanSchedule = this.loanTransactionHelper.getLoanFutureRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
expectedvalues = new ArrayList<>();
todaysDate = Calendar.getInstance();
addRepaymentValues(expectedvalues, todaysDate, 0, "4965.31", "92.51", "0.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2505.67", "23.24", "0.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2529.02", "11.67", "0.0", "0.0");
verifyLoanRepaymentSchedule(loanSchedule, expectedvalues, 0);
todaysDate = Calendar.getInstance(); todaysDate = Calendar.getInstance();
todaysDate.add(Calendar.DAY_OF_MONTH, -7); todaysDate.add(Calendar.DAY_OF_MONTH, -7);
final String LOAN_FIRST_REPAYMENT_DATE = dateFormat.format(todaysDate.getTime()); final String LOAN_FIRST_REPAYMENT_DATE = dateFormat.format(todaysDate.getTime());
@@ -3302,6 +3314,14 @@ public class ClientLoanIntegrationTest {
addRepaymentValues(expectedvalues, todaysDate, 1, "1009.87", "4.66", "0.0", "0.0"); addRepaymentValues(expectedvalues, todaysDate, 1, "1009.87", "4.66", "0.0", "0.0");
verifyLoanRepaymentSchedule(loanSchedule, expectedvalues); verifyLoanRepaymentSchedule(loanSchedule, expectedvalues);
HashMap prepayDetail = this.loanTransactionHelper.getPrepayAmount(this.requestSpec, this.responseSpec, loanID);
String prepayAmount = String.valueOf(prepayDetail.get("amount"));
todaysDate = Calendar.getInstance();
String LOAN_REPAYMENT_DATE = dateFormat.format(todaysDate.getTime());
this.loanTransactionHelper.makeRepayment(LOAN_REPAYMENT_DATE, new Float(prepayAmount), loanID);
loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
LoanStatusChecker.verifyLoanAccountIsClosed(loanStatusHashMap);
} }
@Test @Test
@@ -3313,6 +3333,7 @@ public class ClientLoanIntegrationTest {
Calendar todaysDate = Calendar.getInstance(); Calendar todaysDate = Calendar.getInstance();
todaysDate.add(Calendar.DAY_OF_MONTH, -14); todaysDate.add(Calendar.DAY_OF_MONTH, -14);
final String LOAN_DISBURSEMENT_DATE = dateFormat.format(todaysDate.getTime()); final String LOAN_DISBURSEMENT_DATE = dateFormat.format(todaysDate.getTime());
todaysDate.add(Calendar.DAY_OF_MONTH, -2);
final String REST_START_DATE = dateFormat.format(todaysDate.getTime()); final String REST_START_DATE = dateFormat.format(todaysDate.getTime());
todaysDate = Calendar.getInstance(); todaysDate = Calendar.getInstance();
@@ -3335,7 +3356,7 @@ public class ClientLoanIntegrationTest {
final Integer loanProductID = createLoanProductWithInterestRecalculation(LoanProductTestBuilder.MIFOS_STANDARD_STRATEGY, final Integer loanProductID = createLoanProductWithInterestRecalculation(LoanProductTestBuilder.MIFOS_STANDARD_STRATEGY,
LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_INTEREST_AND_FEE, LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_INTEREST_AND_FEE,
LoanProductTestBuilder.RECALCULATION_STRATEGY_RESCHEDULE_NEXT_REPAYMENTS, LoanProductTestBuilder.RECALCULATION_STRATEGY_RESCHEDULE_NEXT_REPAYMENTS,
LoanProductTestBuilder.RECALCULATION_FREQUENCY_TYPE_WEEKLY, "1", REST_START_DATE); LoanProductTestBuilder.RECALCULATION_FREQUENCY_TYPE_WEEKLY, "1", REST_START_DATE,null);
final Integer loanID = applyForLoanApplicationForInterestRecalculation(clientID, loanProductID, LOAN_DISBURSEMENT_DATE, final Integer loanID = applyForLoanApplicationForInterestRecalculation(clientID, loanProductID, LOAN_DISBURSEMENT_DATE,
REST_START_DATE, LoanApplicationTestBuilder.MIFOS_STANDARD_STRATEGY, charges); REST_START_DATE, LoanApplicationTestBuilder.MIFOS_STANDARD_STRATEGY, charges);
@@ -3366,9 +3387,9 @@ public class ClientLoanIntegrationTest {
expectedvalues = new ArrayList<>(); expectedvalues = new ArrayList<>();
todaysDate = Calendar.getInstance(); todaysDate = Calendar.getInstance();
addRepaymentValues(expectedvalues, todaysDate, -1, "2482.76", "46.15", "100.0", "0.0"); addRepaymentValues(expectedvalues, todaysDate, -1, "2482.76", "46.15", "100.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2482.09", "46.82", "0.0", "0.0"); addRepaymentValues(expectedvalues, todaysDate, 1, "2490.75", "38.16", "0.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2505.67", "23.24", "12.79", "0.0"); addRepaymentValues(expectedvalues, todaysDate, 1, "2505.71", "23.2", "11.91", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2529.48", "11.67", "0.0", "0.0"); addRepaymentValues(expectedvalues, todaysDate, 1, "2520.78", "11.63", "0.0", "0.0");
verifyLoanRepaymentSchedule(loanSchedule, expectedvalues); verifyLoanRepaymentSchedule(loanSchedule, expectedvalues);
@@ -3397,9 +3418,9 @@ public class ClientLoanIntegrationTest {
expectedvalues = new ArrayList<>(); expectedvalues = new ArrayList<>();
todaysDate = Calendar.getInstance(); todaysDate = Calendar.getInstance();
addRepaymentValues(expectedvalues, todaysDate, -1, "2482.76", "46.15", "100.0", "0.0"); addRepaymentValues(expectedvalues, todaysDate, -1, "2482.76", "46.15", "100.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "5065.31", "34.69", "0.0", "0.0"); addRepaymentValues(expectedvalues, todaysDate, 1, "5100", "27.96", "0.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "0", "11.32", "10.35", "0.0"); addRepaymentValues(expectedvalues, todaysDate, 1, "0", "11.16", "9.64", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2451.93", "11.32", "0.0", "0.0"); addRepaymentValues(expectedvalues, todaysDate, 1, "2417.24", "11.16", "0.0", "0.0");
verifyLoanRepaymentSchedule(loanSchedule, expectedvalues); verifyLoanRepaymentSchedule(loanSchedule, expectedvalues);
HashMap prepayDetail = this.loanTransactionHelper.getPrepayAmount(this.requestSpec, this.responseSpec, loanID); HashMap prepayDetail = this.loanTransactionHelper.getPrepayAmount(this.requestSpec, this.responseSpec, loanID);
@@ -3412,7 +3433,107 @@ public class ClientLoanIntegrationTest {
} }
private void addRepaymentValues(List<Map<String, Object>> expectedvalues, Calendar todaysDate, int addMonths, String principalDue, @Test
public void testLoanScheduleWithInterestRecalculation_WITH_PERIODIC_ACCOUNTING() {
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
this.periodicAccrualAccountingHelper = new PeriodicAccrualAccountingHelper(this.requestSpec, this.responseSpec);
this.journalEntryHelper = new JournalEntryHelper(this.requestSpec, this.responseSpec);
DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy");
final Account assetAccount = this.accountHelper.createAssetAccount();
final Account incomeAccount = this.accountHelper.createIncomeAccount();
final Account expenseAccount = this.accountHelper.createExpenseAccount();
final Account overpaymentAccount = this.accountHelper.createLiabilityAccount();
Calendar todaysDate = Calendar.getInstance();
todaysDate.add(Calendar.DAY_OF_MONTH, -14);
final String LOAN_DISBURSEMENT_DATE = dateFormat.format(todaysDate.getTime());
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
Account[] accounts = { assetAccount, incomeAccount, expenseAccount, overpaymentAccount };
final Integer loanProductID = createLoanProductWithInterestRecalculation(LoanProductTestBuilder.MIFOS_STANDARD_STRATEGY,
LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_NONE,
LoanProductTestBuilder.RECALCULATION_STRATEGY_REDUCE_EMI_AMOUN,
LoanProductTestBuilder.RECALCULATION_FREQUENCY_TYPE_SAME_AS_REPAYMENT_PERIOD, "0", null, accounts);
final Integer loanID = applyForLoanApplicationForInterestRecalculation(clientID, loanProductID, LOAN_DISBURSEMENT_DATE, null,
LoanApplicationTestBuilder.MIFOS_STANDARD_STRATEGY, new ArrayList<HashMap>(0));
Assert.assertNotNull(loanID);
HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
ArrayList<HashMap> loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
List<Map<String, Object>> expectedvalues = new ArrayList<>();
todaysDate = Calendar.getInstance();
addRepaymentValues(expectedvalues, todaysDate, -1, "2482.76", "46.15", "0.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2494.22", "34.69", "0.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2505.73", "23.18", "0.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2517.29", "11.62", "0.0", "0.0");
verifyLoanRepaymentSchedule(loanSchedule, expectedvalues);
System.out.println("-----------------------------------APPROVE LOAN-----------------------------------------");
loanStatusHashMap = this.loanTransactionHelper.approveLoan(LOAN_DISBURSEMENT_DATE, loanID);
LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
System.out.println("-------------------------------DISBURSE LOAN-------------------------------------------");
loanStatusHashMap = this.loanTransactionHelper.disburseLoan(LOAN_DISBURSEMENT_DATE, loanID);
LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
expectedvalues = new ArrayList<>();
todaysDate = Calendar.getInstance();
addRepaymentValues(expectedvalues, todaysDate, -1, "2482.76", "46.15", "0.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2482.76", "46.15", "0.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2505.67", "23.24", "0.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2528.81", "11.67", "0.0", "0.0");
verifyLoanRepaymentSchedule(loanSchedule, expectedvalues);
final JournalEntry[] assetAccountInitialEntry = { new JournalEntry(10000.0f, JournalEntry.TransactionType.CREDIT),
new JournalEntry(10000.0f, JournalEntry.TransactionType.DEBIT), };
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, LOAN_DISBURSEMENT_DATE, assetAccountInitialEntry);
todaysDate = Calendar.getInstance();
String runOndate = dateFormat.format(todaysDate.getTime());
this.periodicAccrualAccountingHelper.runPeriodicAccrualAccounting(runOndate);
this.loanTransactionHelper.checkAccrualTransactionForRepayment(LocalDate.now().minusDays(7), 46.15f, 0f, 0f, loanID);
this.loanTransactionHelper.checkAccrualTransactionForRepayment(LocalDate.now(), 46.15f, 0f, 0f, loanID);
todaysDate = Calendar.getInstance();
todaysDate.add(Calendar.DAY_OF_MONTH, -7);
final String LOAN_FIRST_REPAYMENT_DATE = dateFormat.format(todaysDate.getTime());
Float totalDueForCurrentPeriod = (Float) loanSchedule.get(1).get("totalDueForPeriod");
this.loanTransactionHelper.makeRepayment(LOAN_FIRST_REPAYMENT_DATE, totalDueForCurrentPeriod, loanID);
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
expectedvalues = new ArrayList<>();
todaysDate = Calendar.getInstance();
addRepaymentValues(expectedvalues, todaysDate, -1, "2482.76", "46.15", "0.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2494.22", "34.69", "0.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2505.73", "23.18", "0.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2517.29", "11.62", "0.0", "0.0");
verifyLoanRepaymentSchedule(loanSchedule, expectedvalues);
this.loanTransactionHelper.checkAccrualTransactionForRepayment(LocalDate.now().minusDays(7), 46.15f, 0f, 0f, loanID);
this.loanTransactionHelper.checkAccrualTransactionForRepayment(LocalDate.now(), 34.69f, 0f, 0f, loanID);
HashMap prepayDetail = this.loanTransactionHelper.getPrepayAmount(this.requestSpec, this.responseSpec, loanID);
String prepayAmount = String.valueOf(prepayDetail.get("amount"));
todaysDate = Calendar.getInstance();
String LOAN_REPAYMENT_DATE = dateFormat.format(todaysDate.getTime());
this.loanTransactionHelper.makeRepayment(LOAN_REPAYMENT_DATE, new Float(prepayAmount), loanID);
loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
LoanStatusChecker.verifyLoanAccountIsClosed(loanStatusHashMap);
this.loanTransactionHelper.checkAccrualTransactionForRepayment(LocalDate.now().minusDays(7), 46.15f, 0f, 0f, loanID);
this.loanTransactionHelper.checkAccrualTransactionForRepayment(LocalDate.now(), 34.69f, 0f, 0f, loanID);
}
private void addRepaymentValues(List<Map<String, Object>> expectedvalues, Calendar todaysDate, int addMonths, String principalDue,
String interestDue, String feeChargesDue, String penaltyChargesDue) { String interestDue, String feeChargesDue, String penaltyChargesDue) {
Map<String, Object> values = new HashMap<>(3); Map<String, Object> values = new HashMap<>(3);
values.put("dueDate", getDateAsArray(todaysDate, addMonths)); values.put("dueDate", getDateAsArray(todaysDate, addMonths));
@@ -3438,22 +3559,26 @@ public class ClientLoanIntegrationTest {
private Integer createLoanProductWithInterestRecalculation(final String repaymentStrategy, private Integer createLoanProductWithInterestRecalculation(final String repaymentStrategy,
final String interestRecalculationCompoundingMethod, final String rescheduleStrategyMethod, final String interestRecalculationCompoundingMethod, final String rescheduleStrategyMethod,
final String recalculationRestFrequencyType, final String recalculationRestFrequencyInterval, final String recalculationRestFrequencyType, final String recalculationRestFrequencyInterval,
final String recalculationRestFrequencyDate) { final String recalculationRestFrequencyDate, final Account[] accounts) {
System.out.println("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------"); System.out.println("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------");
final String loanProductJSON = new LoanProductTestBuilder() // LoanProductTestBuilder builder = new LoanProductTestBuilder()
.withPrincipal("10000000.00") // .withPrincipal("10000000.00")
.withNumberOfRepayments("24") // .withNumberOfRepayments("24")
.withRepaymentAfterEvery("1") // .withRepaymentAfterEvery("1")
.withRepaymentTypeAsWeek() // .withRepaymentTypeAsWeek()
.withinterestRatePerPeriod("2") // .withinterestRatePerPeriod("2")
.withInterestRateFrequencyTypeAsMonths() // .withInterestRateFrequencyTypeAsMonths()
.withRepaymentStrategy(repaymentStrategy) // .withRepaymentStrategy(repaymentStrategy)
.withAmortizationTypeAsEqualPrincipalPayment() // .withAmortizationTypeAsEqualPrincipalPayment()
.withInterestTypeAsDecliningBalance() // .withInterestTypeAsDecliningBalance()
.withInterestRecalculationDetails(interestRecalculationCompoundingMethod, rescheduleStrategyMethod)// .withInterestRecalculationDetails(interestRecalculationCompoundingMethod, rescheduleStrategyMethod)
.withInterestRecalculationRestFrequencyDetails(recalculationRestFrequencyType, recalculationRestFrequencyInterval, .withInterestRecalculationRestFrequencyDetails(recalculationRestFrequencyType, recalculationRestFrequencyInterval,
recalculationRestFrequencyDate)// recalculationRestFrequencyDate);
.build(null); if (accounts != null) {
builder = builder.withAccountingRulePeriodicAccrual(accounts);
}
final String loanProductJSON = builder.build(null);
return this.loanTransactionHelper.getLoanProductId(loanProductJSON); return this.loanTransactionHelper.getLoanProductId(loanProductJSON);
} }
@@ -3481,20 +3606,24 @@ public class ClientLoanIntegrationTest {
} }
private void verifyLoanRepaymentSchedule(final ArrayList<HashMap> loanSchedule, List<Map<String, Object>> expectedvalues) { private void verifyLoanRepaymentSchedule(final ArrayList<HashMap> loanSchedule, List<Map<String, Object>> expectedvalues) {
System.out.println("--------------------VERIFYING THE PRINCIPAL DUES,INTEREST DUE AND DUE DATE--------------------------"); int index = 1;
int i = 1; verifyLoanRepaymentSchedule(loanSchedule, expectedvalues, index);
for (Map<String, Object> values : expectedvalues) {
assertEquals("Checking for Due Date for Month " + i, values.get("dueDate"), loanSchedule.get(i).get("dueDate"));
validateNumberForEqualWithMsg("Checking for Principal Due for Month " + i, String.valueOf(values.get("principalDue")),
String.valueOf(loanSchedule.get(i).get("principalDue")));
validateNumberForEqualWithMsg("Checking for Interest Due for Month " + i, String.valueOf(values.get("interestDue")),
String.valueOf(loanSchedule.get(i).get("interestDue")));
validateNumberForEqualWithMsg("Checking for Fee charge Due for Month " + i, String.valueOf(values.get("feeChargesDue")),
String.valueOf(loanSchedule.get(i).get("feeChargesDue")));
validateNumberForEqualWithMsg("Checking for Penalty charge Due for Month " + i,
String.valueOf(values.get("penaltyChargesDue")), String.valueOf(loanSchedule.get(i).get("penaltyChargesDue")));
i++;
}
} }
private void verifyLoanRepaymentSchedule(final ArrayList<HashMap> loanSchedule, List<Map<String, Object>> expectedvalues, int index) {
System.out.println("--------------------VERIFYING THE PRINCIPAL DUES,INTEREST DUE AND DUE DATE--------------------------");
for (Map<String, Object> values : expectedvalues) {
assertEquals("Checking for Due Date for installment " + index, values.get("dueDate"), loanSchedule.get(index).get("dueDate"));
validateNumberForEqualWithMsg("Checking for Principal Due for installment " + index,
String.valueOf(values.get("principalDue")), String.valueOf(loanSchedule.get(index).get("principalDue")));
validateNumberForEqualWithMsg("Checking for Interest Due for installment " + index, String.valueOf(values.get("interestDue")),
String.valueOf(loanSchedule.get(index).get("interestDue")));
validateNumberForEqualWithMsg("Checking for Fee charge Due for installment " + index,
String.valueOf(values.get("feeChargesDue")), String.valueOf(loanSchedule.get(index).get("feeChargesDue")));
validateNumberForEqualWithMsg("Checking for Penalty charge Due for installment " + index,
String.valueOf(values.get("penaltyChargesDue")), String.valueOf(loanSchedule.get(index).get("penaltyChargesDue")));
index++;
}
}
} }
@@ -63,7 +63,7 @@ public class LoanTransactionHelper {
public ArrayList getLoanFutureRepaymentSchedule(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, public ArrayList getLoanFutureRepaymentSchedule(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
final Integer loanID) { final Integer loanID) {
final String URL = "/mifosng-provider/api/v1/loans/" + loanID + "?associations=repaymentSchedule&futureSchedule&" + Utils.TENANT_IDENTIFIER; final String URL = "/mifosng-provider/api/v1/loans/" + loanID + "?associations=repaymentSchedule,futureSchedule&" + Utils.TENANT_IDENTIFIER;
final HashMap response = Utils.performServerGet(requestSpec, responseSpec, URL, "repaymentSchedule"); final HashMap response = Utils.performServerGet(requestSpec, responseSpec, URL, "repaymentSchedule");
return (ArrayList) response.get("futurePeriods"); return (ArrayList) response.get("futurePeriods");
} }
@@ -444,6 +444,13 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
final LoanTransaction preCloseTransaction) { final LoanTransaction preCloseTransaction) {
List<RecalculationDetail> earlypaymentDetail = new ArrayList<>(); List<RecalculationDetail> earlypaymentDetail = new ArrayList<>();
Money currentInstallmentOutstanding = installment.getTotalOutstanding(currency); Money currentInstallmentOutstanding = installment.getTotalOutstanding(currency);
LocalDate maxTransactionDate = null;
Set<LocalDate> transaDates = recalculationDates.keySet();
for (LocalDate transactionDate : transaDates) {
if (maxTransactionDate == null || transactionDate.isAfter(maxTransactionDate)) {
maxTransactionDate = transactionDate;
}
}
for (final LoanTransaction loanTransaction : transactionsPostDisbursement) { for (final LoanTransaction loanTransaction : transactionsPostDisbursement) {
Money amountToProcess = null; Money amountToProcess = null;
LocalDate transactionDate = loanTransaction.getTransactionDate(); LocalDate transactionDate = loanTransaction.getTransactionDate();
@@ -454,10 +461,14 @@ public abstract class AbstractLoanRepaymentScheduleTransactionProcessor implemen
if (newLoanTransaction.isRepayment() || newLoanTransaction.isInterestWaiver() || newLoanTransaction.isRecoveryRepayment()) { if (newLoanTransaction.isRepayment() || newLoanTransaction.isInterestWaiver() || newLoanTransaction.isRecoveryRepayment()) {
newLoanTransaction.resetDerivedComponents(); newLoanTransaction.resetDerivedComponents();
} }
Money unProcessed = processTransaction(newLoanTransaction, currency, installments, amountToProcess); Money unProcessed = processTransaction(newLoanTransaction, currency, installments, amountToProcess);
if (transactionDate.isAfter(installment.getFromDate()) && transactionDate.isBefore(installment.getDueDate())) { if (loanTransaction.getTransactionDate().isEqual(maxTransactionDate) && transactionDate.isAfter(installment.getFromDate())
&& transactionDate.isBefore(installment.getDueDate())) {
Money earlyPayment = currentInstallmentOutstanding.minus(installment.getTotalOutstanding(currency)); Money earlyPayment = currentInstallmentOutstanding.minus(installment.getTotalOutstanding(currency));
if (earlyPayment.isGreaterThanZero() && (newLoanTransaction.isRepayment() || newLoanTransaction.isInterestWaiver() || newLoanTransaction.isRecoveryRepayment())) { if (earlyPayment.isGreaterThanZero()
&& (newLoanTransaction.isRepayment() || newLoanTransaction.isInterestWaiver() || newLoanTransaction
.isRecoveryRepayment())) {
earlypaymentDetail.add(new RecalculationDetail(false, transactionDate, null, earlyPayment, false)); earlypaymentDetail.add(new RecalculationDetail(false, transactionDate, null, earlyPayment, false));
} }
currentInstallmentOutstanding = installment.getTotalOutstanding(currency); currentInstallmentOutstanding = installment.getTotalOutstanding(currency);
@@ -405,6 +405,10 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
outstandingBalance = outstandingBalance.zero(); outstandingBalance = outstandingBalance.zero();
} }
} }
if (fixedEmiAmount.isZero() && !recalculatedInterestComponent) {
fixedEmiAmount = principalForThisPeriod.plus(interestForThisinstallment);
}
reducePrincipal = reducePrincipal.minus(reducePrincipalForCurrentInstallment); reducePrincipal = reducePrincipal.minus(reducePrincipalForCurrentInstallment);
if (principalForThisPeriod.isGreaterThan(reducePrincipalForCurrentInstallment)) { if (principalForThisPeriod.isGreaterThan(reducePrincipalForCurrentInstallment)) {
@@ -436,10 +440,6 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
reducePrincipal = reducePrincipal.plus(reducePrincipalForCurrentInstallment); reducePrincipal = reducePrincipal.plus(reducePrincipalForCurrentInstallment);
if (fixedEmiAmount.isZero() && !recalculatedInterestComponent) {
fixedEmiAmount = principalForThisPeriod.plus(interestForThisinstallment);
}
actualOutstandingbalance = actualOutstandingbalance.minus(reducePrincipal); actualOutstandingbalance = actualOutstandingbalance.minus(reducePrincipal);
if (actualOutstandingbalance.isLessThanZero()) { if (actualOutstandingbalance.isLessThanZero()) {
actualOutstandingbalance = actualOutstandingbalance.zero(); actualOutstandingbalance = actualOutstandingbalance.zero();
@@ -1292,9 +1292,13 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
} }
} }
if (installment.isRecalculatedInterestComponent() && installment.getPrincipal(currency).isGreaterThanZero()) { /*
diffAmt.add(new RecalculationDetail(false, installment.getDueDate(), null, installment.getPrincipal(currency), false)); * if (installment.isRecalculatedInterestComponent() &&
} * installment.getPrincipal(currency).isGreaterThanZero()) {
* diffAmt.add(new RecalculationDetail(false,
* installment.getDueDate(), null,
* installment.getPrincipal(currency), false)); }
*/
List<RecalculationDetail> earlypaymentDetail = loanRepaymentScheduleTransactionProcessor.handleRepaymentSchedule( List<RecalculationDetail> earlypaymentDetail = loanRepaymentScheduleTransactionProcessor.handleRepaymentSchedule(
transactionsForInstallment, currency, processinstallmets, installment, recalculationDates, preCloseTransaction); transactionsForInstallment, currency, processinstallmets, installment, recalculationDates, preCloseTransaction);
@@ -1648,18 +1652,22 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
List<LoanRepaymentScheduleInstallment> installments, MonetaryCurrency currency, final LoanApplicationTerms applicationTerms, List<LoanRepaymentScheduleInstallment> installments, MonetaryCurrency currency, final LoanApplicationTerms applicationTerms,
MathContext mc, final Set<LoanCharge> loanCharges) { MathContext mc, final Set<LoanCharge> loanCharges) {
LoanTransaction precloseTransaction = null; LoanTransaction precloseTransaction = null;
Money collectedPrincipal = Money.zero(currency);
for (LoanTransaction loanTransaction : loanTransactions) { for (LoanTransaction loanTransaction : loanTransactions) {
if (precloseTransaction == null if (precloseTransaction == null
|| (!precloseTransaction.getTransactionDate().isAfter(loanTransaction.getTransactionDate()) && (loanTransaction.getId() == null || (precloseTransaction || (!precloseTransaction.getTransactionDate().isAfter(loanTransaction.getTransactionDate()) && (loanTransaction.getId() == null || (precloseTransaction
.getId() != null && loanTransaction.getId().compareTo(precloseTransaction.getId()) == 1)))) { .getId() != null && loanTransaction.getId().compareTo(precloseTransaction.getId()) == 1)))) {
precloseTransaction = loanTransaction; precloseTransaction = loanTransaction;
} }
collectedPrincipal = collectedPrincipal.plus(loanTransaction.getPrincipalPortion());
} }
if (precloseTransaction != null) { if (precloseTransaction != null) {
LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment = calculatePrepaymentAmount(installments, currency, LoanRepaymentScheduleInstallment loanRepaymentScheduleInstallment = calculatePrepaymentAmount(installments, currency,
precloseTransaction.getTransactionDate(), applicationTerms.getInterestChargedFromLocalDate(), applicationTerms, mc, precloseTransaction.getTransactionDate(), applicationTerms.getInterestChargedFromLocalDate(), applicationTerms, mc,
loanCharges); loanCharges);
if (precloseTransaction.getAmount(currency).isLessThan(loanRepaymentScheduleInstallment.getTotalOutstanding(currency))) { Money pendingPrinciapl = applicationTerms.getPrincipal().minus(collectedPrincipal).plus(precloseTransaction.getPrincipalPortion());
if (pendingPrinciapl.isGreaterThan(loanRepaymentScheduleInstallment.getPrincipal(currency))
|| precloseTransaction.getAmount(currency).isLessThan(loanRepaymentScheduleInstallment.getTotalOutstanding(currency))) {
precloseTransaction = null; precloseTransaction = null;
} }
} }