/*
* Copyright (c) 2005-2011 Grameen Foundation USA
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* See also http://www.apache.org/licenses/LICENSE-2.0.html for an
* explanation of the license and how it is applied.
*/
package org.mifos.test.acceptance.loan;
import java.sql.SQLException;
import org.joda.time.DateTime;
import org.joda.time.ReadableInstant;
import org.joda.time.format.DateTimeFormat;
import org.mifos.test.acceptance.framework.MifosPage;
import org.mifos.test.acceptance.framework.UiTestCaseBase;
import org.mifos.test.acceptance.framework.loan.ApplyAdjustmentPage;
import org.mifos.test.acceptance.framework.loan.LoanAccountPage;
import org.mifos.test.acceptance.framework.loan.RedoLoanAccountPreviewPage;
import org.mifos.test.acceptance.framework.loan.RedoLoanDisbursalEntryPage;
import org.mifos.test.acceptance.framework.loan.RedoLoanDisbursalParameters;
import org.mifos.test.acceptance.framework.loan.RedoLoanDisbursalSchedulePreviewPage;
import org.mifos.test.acceptance.framework.loan.TransactionHistoryPage;
import org.mifos.test.acceptance.framework.loan.ViewNextInstallmentDetailsPage;
import org.mifos.test.acceptance.framework.loan.ViewRepaymentSchedulePage;
import org.mifos.test.acceptance.framework.testhelpers.LoanTestHelper;
import org.mifos.test.acceptance.framework.testhelpers.NavigationHelper;
import org.mifos.test.acceptance.loanproduct.LoanProductTestHelper;
import org.mifos.test.acceptance.remote.DateTimeUpdaterRemoteTestingService;
import org.mifos.test.acceptance.util.ApplicationDatabaseOperation;
import org.mifos.test.acceptance.util.TestDataSetup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@ContextConfiguration(locations = {"classpath:ui-test-context.xml"})
@Test(singleThreaded = true, groups = {"loan", "acceptance", "ui", "no_db_unit"})
public class RedoLoanDisbursalTest extends UiTestCaseBase {
private LoanTestHelper loanTestHelper;
private NavigationHelper navigationHelper;
@Autowired
private ApplicationDatabaseOperation applicationDatabaseOperation;
LoanProductTestHelper loanProductTestHelper;
DateTime systemDateTime;
@Override
@SuppressWarnings("PMD.SignatureDeclareThrowsException")
// one of the dependent methods throws Exception
@BeforeMethod
public void setUp() throws Exception {
super.setUp();
DateTimeUpdaterRemoteTestingService dateTimeUpdaterRemoteTestingService = new DateTimeUpdaterRemoteTestingService(selenium);
DateTime targetTime = new DateTime(2012, 02, 22, 15, 0, 0, 0);
dateTimeUpdaterRemoteTestingService.setDateTime(targetTime);
loanTestHelper = new LoanTestHelper(selenium);
}
@AfterMethod
public void logOut() throws SQLException {
applicationDatabaseOperation.updateGLIM(0);
applicationDatabaseOperation.updateLSIM(0);
(new MifosPage(selenium)).logout();
}
/**
* Verify whether a loan can be redone on a past date with GLIM and LSIM turned on.
* http://mifosforge.jira.com/browse/MIFOSTEST-18
*/
@SuppressWarnings("PMD.SignatureDeclareThrowsException")
public void redoLoanOnPastDateWithLSIMAndGLIM() throws Exception {
applicationDatabaseOperation.updateGLIM(1);
applicationDatabaseOperation.updateLSIM(1);
RedoLoanDisbursalParameters paramsPastDate = new RedoLoanDisbursalParameters();
paramsPastDate.setDisbursalDateDD("21");
paramsPastDate.setDisbursalDateMM("02");
paramsPastDate.setDisbursalDateYYYY("2012");
paramsPastDate.addClient(1, "3000.0", "0009-Horse");
paramsPastDate.addClient(2, "3000.0", "0001-Cow Purchase");
LoanAccountPage loanAccountPage = loanTestHelper.redoLoanDisbursalWithGLIMandLSIM("Default Group", "GroupEmergencyLoan", paramsPastDate);
loanAccountPage.verifyStatus(LoanAccountPage.ACTIVE);
loanAccountPage.verifyPrincipalOriginal("6,000");
}
/*
* Verify a redone loan directly moves into "Closed-Met Obligation"
* state when the loan is wholly paid off before the current date.
*
* http://mifosforge.jira.com/browse/MIFOSTEST-28
*/
@SuppressWarnings("PMD.SignatureDeclareThrowsException")
public void redoLoanDisbursalWithPastDate() throws Exception {
RedoLoanDisbursalParameters paramsPastDate = new RedoLoanDisbursalParameters();
paramsPastDate.setDisbursalDateDD("25");
paramsPastDate.setDisbursalDateMM("02");
paramsPastDate.setDisbursalDateYYYY("2011");
LoanAccountPage loanAccountPage = loanTestHelper.redoLoanDisbursal("Default Group", "WeeklyGroupFlatLoanWithOnetimeFee", paramsPastDate, null, 0, false);
verifyRedoLoanDisbursalWithPastDate(loanAccountPage);
}
private void verifyRedoLoanDisbursalWithPastDate(LoanAccountPage loanAccountPage) {
loanAccountPage.verifyStatus("Closed- Obligation met");
loanAccountPage.verifyTotalOriginalLoan("1029");
loanAccountPage.verifyTotalAmountPaid("1,029");
loanAccountPage.verifyLoanTotalBalance("0");
TransactionHistoryPage transactionHistoryPage = loanAccountPage.navigateToTransactionHistory();
transactionHistoryPage.verifyTransactionHistory(1028.6, 4, 22);
}
/*
* Verify that the status of the loan is Active in Good Standing
* when the loan is not wholly paid off before current date.
* Also verifies that loan cannot be redone on a date equal to
* or greater than the current date.
*
* http://mifosforge.jira.com/browse/MIFOSTEST-15
*/
@SuppressWarnings("PMD.SignatureDeclareThrowsException")
public void redoLoanDisbursalWithPastDateUnpaid() throws Exception {
// Testing redo loan
RedoLoanDisbursalParameters paramsPastDate = new RedoLoanDisbursalParameters();
paramsPastDate.setDisbursalDateDD("25");
paramsPastDate.setDisbursalDateMM("02");
paramsPastDate.setDisbursalDateYYYY("2011");
paramsPastDate.setLoanAmount("3000.0");
paramsPastDate.setInterestRate("10");
paramsPastDate.setNumberOfInstallments("52");
RedoLoanDisbursalParameters paramsCurrentDate = new RedoLoanDisbursalParameters();
paramsCurrentDate.setDisbursalDateDD("22");
paramsCurrentDate.setDisbursalDateMM("2");
paramsCurrentDate.setDisbursalDateYYYY("2012");
LoanAccountPage loanAccountPage = loanTestHelper.redoLoanDisbursal("Default Group", "WeeklyGroupFlatLoanWithOnetimeFee", paramsPastDate, paramsCurrentDate, 0, true);
loanAccountPage.verifyStatus("Active in Good Standing");
loanAccountPage.verifyPerformanceHistory("51", "0");
// Testing multiple reverse payments
String payAmount = "63";
String reverseNote = "Reversed ";
int loanBalance = (int) (Float.parseFloat(loanAccountPage.getTotalBalance()) + 63 * 3);
for (int i = 0; i < 3; i++) {
ApplyAdjustmentPage applyAdjustmentPage = loanAccountPage.navigateToApplyAdjustment();
applyAdjustmentPage.verifyAdjustment(payAmount, reverseNote + (i + 1));
}
verifyMultipleReversePayments(loanAccountPage, payAmount, reverseNote, loanBalance);
}
private void verifyMultipleReversePayments(LoanAccountPage loanAccountPage, String payAmount, String reverseNote, int loanBalance) {
TransactionHistoryPage transactionHistoryPage = loanAccountPage.navigateToTransactionHistory();
transactionHistoryPage.verifyTableForReversedValues(payAmount, 3, reverseNote);
transactionHistoryPage.navigateBack();
ViewNextInstallmentDetailsPage installmentPage = loanAccountPage.navigateToViewNextInstallmentDetails();
installmentPage.verifyInstallmentAmount(6, 2, "0");
installmentPage.verifyInstallmentAmount(12, 2, "0");
installmentPage.navigateBack();
ViewRepaymentSchedulePage repaymentSchedulePage = loanAccountPage.navigateToRepaymentSchedulePage();
repaymentSchedulePage.verifyRepaymentScheduleTableRow(51, 0, "Installments due");
repaymentSchedulePage.verifyRepaymentScheduleTableRow(52, 8, "63");
repaymentSchedulePage.verifyRepaymentScheduleTableRow(53, 8, "63");
repaymentSchedulePage.verifyRepaymentScheduleTableRow(54, 8, "63");
repaymentSchedulePage.verifyRepaymentScheduleTableRow(55, 0, "Future Installments");
repaymentSchedulePage.navigateBack();
loanAccountPage.verifyLoanTotalBalance(Integer.toString(loanBalance));
loanAccountPage.verifyPerformanceHistory("48", "3");
loanAccountPage.verifyStatus("Active in Good Standing");
}
@SuppressWarnings("PMD.SignatureDeclareThrowsException")
public void redoLoanDisbursalForVariableInstallmentLoan() throws Exception {
dataSetUpForVariableInstallmentLoan();
applicationDatabaseOperation.updateLSIM(1);
int interest = 24;
int noOfInstallments = 5;
int loanAmount = 1000;
DateTime disbursalDate = systemDateTime;
RedoLoanDisbursalParameters redoLoanDisbursalParameters = setLoanParams(disbursalDate, interest, noOfInstallments, loanAmount);
loanTestHelper.setApplicationTime(systemDateTime.plusDays(14));
RedoLoanDisbursalEntryPage redoLoanDisbursalEntryPage = navigateToRedoLoanPage();
redoLoanDisbursalEntryPage.enterDisbursementDate(disbursalDate);
// TODO - fix validation of use of fees on variable installment
// String[] invalidFees = getInvalidFees();
// redoLoanDisbursalEntryPage.verifyFeeBlockedForVariableInstallmentLoan(invalidFees);
// RedoLoanDisbursalSchedulePreviewPage redoLoanDisbursalSchedulePreviewPage =
redoLoanDisbursalEntryPage.submitAndNavigateToRedoLoanDisbursalSchedulePreviewPage(redoLoanDisbursalParameters);
// redoLoanDisbursalSchedulePreviewPage.validateRepaymentScheduleFieldDefault(noOfInstallments);
// String maxGap = "10";
// String minGap = "1";
// redoLoanDisbursalSchedulePreviewPage.validateDateFieldValidations(disbursalDate, minGap, maxGap, noOfInstallments);
//
// String minInstalmentAmount = "100";
// redoLoanDisbursalSchedulePreviewPage.verifyInstallmentTotalValidations(noOfInstallments, minInstalmentAmount, disbursalDate, minGap);
//
// redoLoanDisbursalSchedulePreviewPage.verifyValidData(noOfInstallments, minGap, minInstalmentAmount, disbursalDate, maxGap);
// redoLoanDisbursalSchedulePreviewPage.verifyRecalculationWhenDateAndTotalChange();
}
@SuppressWarnings("PMD.SignatureDeclareThrowsException")
public void redoLoanDisbursalForDecliningBalanceLoan() throws Exception {
dataSetUpForVariableInstallmentLoan();
applicationDatabaseOperation.updateLSIM(1);
String[] fees = getInvalidFees();
loanTestHelper.setApplicationTime(systemDateTime.plusDays(14));
RedoLoanDisbursalEntryPage redoLoanDisbursalEntryPage = navigateToRedoLoanPage().selectFee(new String[]{fees[0]});
int interest = 24;
int noOfInstallments = 5;
int loanAmount = 1000;
RedoLoanDisbursalParameters redoLoanDisbursalParameters = setLoanParams(systemDateTime, interest, noOfInstallments, loanAmount);
RedoLoanDisbursalSchedulePreviewPage redoLoanDisbursalSchedulePreviewPage =
redoLoanDisbursalEntryPage.submitAndNavigateToRedoLoanDisbursalSchedulePreviewPage(redoLoanDisbursalParameters);
RedoLoanAccountPreviewPage redoLoanAccountPreviewPage = redoLoanDisbursalSchedulePreviewPage.setPaidField(RedoLoanScheduleData.DECLINING_PRINCIPAL_LATE_PAYMENT_1).clickPreviewAndGoToReviewLoanAccountPage();
String[][] expectedRepaymentSchedule = new String[][] {
{"1", "15-Oct-2010", "19-Oct-2010", "200.4", "4.6", "100", "305"},
{"2", "22-Oct-2010", "19-Oct-2010", "0.4", "4.6", "100", "105"}};
String[][] expectedFutureInstallments = new String[][] {
{"2", "22-Oct-2010", "-", "200", "0", "0", "200"},
{"3", "29-Oct-2010", "-", "200.4", "4.6", "100", "305"},
{"4", "05-Nov-2010", "-", "200.4", "4.6", "100", "305"},
{"5", "12-Nov-2010", "-", "198.4", "5.6", "100", "304"}};
String[][] expectedRepaymentBalance = new String[][] {
{"799.6", "19.4", "400", "1,219"},
{"799.2", "14.8", "300", "1,114"}};
redoLoanAccountPreviewPage.verifyRunningBalance(expectedRepaymentSchedule, expectedFutureInstallments, expectedRepaymentBalance);
}
private RedoLoanDisbursalEntryPage navigateToRedoLoanPage() {
return navigationHelper.
navigateToAdminPage().navigateToRedoLoanDisbursal().
searchAndNavigateToRedoLoanDisbursalPage("Stu1233171716380").
navigateToRedoLoanDisbursalChooseLoanProductPage("Stu1233171716380").
submitAndNavigateToRedoLoanDisbursalEntryPage("WeeklyFlatLoanWithOneTimeFees");
}
@SuppressWarnings("PMD.SignatureDeclareThrowsException")
private void dataSetUpForVariableInstallmentLoan() throws Exception {
navigationHelper = new NavigationHelper(selenium);
loanTestHelper = new LoanTestHelper(selenium);
loanProductTestHelper = new LoanProductTestHelper(selenium);
systemDateTime = new DateTime(2010, 10, 11, 10, 0, 0, 0);
TestDataSetup dataSetup = new TestDataSetup(selenium, applicationDatabaseOperation);
loanTestHelper.setApplicationTime(systemDateTime);
dataSetup.addDecliningPrincipalBalance();
}
private RedoLoanDisbursalParameters setLoanParams(ReadableInstant validDisbursalDate, int interest, int noOfInstallments, int loanAmount) {
RedoLoanDisbursalParameters redoLoanDisbursalParameters = new RedoLoanDisbursalParameters();
redoLoanDisbursalParameters.setInterestRate(String.valueOf(interest));
redoLoanDisbursalParameters.setNumberOfInstallments(String.valueOf(noOfInstallments));
redoLoanDisbursalParameters.setLoanAmount(String.valueOf(loanAmount));
redoLoanDisbursalParameters.setDisbursalDateDD(DateTimeFormat.forPattern("dd").print(validDisbursalDate));
redoLoanDisbursalParameters.setDisbursalDateMM(DateTimeFormat.forPattern("MM").print(validDisbursalDate));
redoLoanDisbursalParameters.setDisbursalDateYYYY(DateTimeFormat.forPattern("yyyy").print(validDisbursalDate));
return redoLoanDisbursalParameters;
}
private String[] getInvalidFees() {
return new String[]{"loanWeeklyFee", "fixedFeePerInterest", "fixedFeePerAmountAndInterest"};
}
}