/*
* 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.penalties;
import java.math.BigDecimal;
import java.util.Arrays;
import org.joda.time.DateTime;
import org.mifos.test.acceptance.framework.MifosPage;
import org.mifos.test.acceptance.framework.UiTestCaseBase;
import org.mifos.test.acceptance.framework.admin.PenaltyFormParameters;
import org.mifos.test.acceptance.framework.loan.LoanAccountPage;
import org.mifos.test.acceptance.framework.loan.PaymentParameters;
import org.mifos.test.acceptance.framework.loan.RepayLoanParameters;
import org.mifos.test.acceptance.framework.loanproduct.DefineNewLoanProductPage.SubmitFormParameters;
import org.mifos.test.acceptance.framework.testhelpers.BatchJobHelper;
import org.mifos.test.acceptance.framework.testhelpers.FormParametersHelper;
import org.mifos.test.acceptance.framework.testhelpers.NavigationHelper;
import org.mifos.test.acceptance.framework.testhelpers.PenaltyHelper;
import org.mifos.test.acceptance.remote.DateTimeUpdaterRemoteTestingService;
import org.mifos.test.acceptance.util.StringUtil;
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 = {"penalties", "acceptance", "ui"})
@SuppressWarnings({"PMD.SignatureDeclareThrowsException", "PMD.AvoidFinalLocalVariable"})
public class BatchJobPenaltyTest extends UiTestCaseBase {
private static final String[] PENALTY_NAME = new String[] {
"Penalty 5.7.1", "Penalty 5.7.2", "Penalty 5.7.3", "Penalty 5.7.4", "Penalty 5.7.5",
"Penalty 5.7.6", "Penalty 5.7.8", "Penalty 5.7.9"
};
private NavigationHelper navigationHelper;
private PenaltyHelper penaltyHelper;
private DateTimeUpdaterRemoteTestingService dateTimeUpdaterRemoteTestingService;
@Override
@BeforeMethod
public void setUp() throws Exception {
super.setUp();
this.navigationHelper = new NavigationHelper(selenium);
this.penaltyHelper = new PenaltyHelper(selenium);
this.dateTimeUpdaterRemoteTestingService = new DateTimeUpdaterRemoteTestingService(selenium);
initRemote.dataLoadAndCacheRefresh(dbUnitUtilities, "acceptance_small_001_dbunit.xml", dataSource, selenium);
}
@AfterMethod
public void logOut() throws Exception {
(new MifosPage(selenium)).logout();
}
@Test(enabled = true)
public void shouldCalculateOneTimePenaltyOnLoanAccount() throws Exception {
final String accountId = setUpPenaltyAndLoanAccount(PENALTY_NAME[0], PenaltyFormParameters.PERIOD_NONE, "",
PenaltyFormParameters.FREQUENCY_NONE, "0.1", "9,999,999,999");
changeDateTime(04, 1);
penaltyHelper.verifyCalculatePenaltyWithPayment(accountId,
new String[] { "1", "0", "1" },
new String[][] { { "0", "450" }, null /* Installments due */, { "1", "451" }, { "0", "450" }, { "0", "450" }, { "0", "450" },
{ "0", "450" }, { "0", "450" }, null /* Future Installments */, { "0", "450" }, { "0", "450" }, { "0", "450" } },
new String[] { "3,151", "05/04/2012", "2,701" }
);
verifyAfterRepayLoan(accountId, new String[] { "0", "1", "0", "0", "0", "0", "0", "0", "0", "0" }, false);
}
@Test(enabled = true)
public void shouldCalculateDailyAmountPenaltyOnLoanAccount() throws Exception {
final String accountId = setUpPenaltyAndLoanAccount(PENALTY_NAME[1], PenaltyFormParameters.PERIOD_NONE, "",
PenaltyFormParameters.FREQUENCY_DAILY, "0.1", "9,999,999,999");
changeDateTime(04, 1);
penaltyHelper.verifyCalculatePenaltyWithPayment(accountId,
new String[] { "123", "0", "123" },
new String[][] { { "0", "450" }, null /* Installments due */, { "38", "488" }, { "31", "481" }, { "24", "474" }, { "17", "467" },
{ "10", "460" }, { "3", "453" }, null /* Future Installments */, { "0", "450" }, { "0", "450" }, { "0", "450" } },
new String[] { "3,273", "05/04/2012", "2,823" }
);
verifyAfterRepayLoan(accountId, new String[] { "0", "38", "31", "24", "17", "10", "3", "0", "0", "0" }, false);
}
@Test(enabled = true)
public void shounldCalculateWeeklyAmountPenaltyOnLoanAccount() throws Exception {
final String accountId = setUpPenaltyAndLoanAccount(PENALTY_NAME[2], PenaltyFormParameters.PERIOD_NONE, "",
PenaltyFormParameters.FREQUENCY_WEEKLY, "0.1", "9,999,999,999");
changeDateTime(04, 1);
penaltyHelper.verifyCalculatePenaltyWithPayment(accountId,
new String[] { "21", "0", "21" },
new String[][] { { "0", "450" }, null /* Installments due */, { "6", "456" }, { "5", "455" }, { "4", "454" }, { "3", "453" },
{ "2", "452" }, { "1", "451" }, null /* Future Installments */, { "0", "450" }, { "0", "450" }, { "0", "450" } },
new String[] { "3,171", "05/04/2012", "2,721" }
);
verifyAfterRepayLoan(accountId, new String[] { "0", "6", "5", "4", "3", "2", "1", "0", "0", "0" }, false);
navigationHelper.navigateToLoanAccountPage(accountId).navigateToApplyAdjustment().submitAdjustment();
penaltyHelper.verifyCalculatePenaltyWithPayment(accountId,
new String[] { "21", "0", "21" },
new String[][] { { "0", "450" }, null /* Installments due */, { "6", "456" }, { "5", "455" }, { "4", "454" }, { "3", "453" },
{ "2", "452" }, { "1", "451" }, { "0", "450" }, null /* Future Installments */, { "0", "450" }, { "0", "450" } },
new String[] { "3,171", "05/04/2012", "2,721" }
);
navigationHelper.navigateToLoanAccountPage(accountId).removePenalty(1);
verifyAfterRepayLoan(accountId, new String[] { "0", "0", "0", "0", "0", "0", "0", "0", "0", "0" }, true);
}
@Test(enabled = true)
public void shouldCalculateWeeklyAmountPenaltyWithPeriodInstallmentsOnLoanAccount() throws Exception {
final String accountId = setUpPenaltyAndLoanAccount(PENALTY_NAME[3], PenaltyFormParameters.PERIOD_INSTALLMENTS,
"1", PenaltyFormParameters.FREQUENCY_WEEKLY, "0.1", "9,999,999,999");
changeDateTime(04, 1);
penaltyHelper.verifyCalculatePenaltyWithPayment(accountId,
new String[] { "19", "0", "19" },
new String[][] { { "0", "450" }, null /* Installments due */, { "4", "454" }, { "5", "455" }, { "4", "454" }, { "3", "453" },
{ "2", "452" }, { "1", "451" }, null /* Future Installments */, { "0", "450" }, { "0", "450" }, { "0", "450" } },
new String[] { "3,169", "05/04/2012", "2,719" }
);
verifyAfterRepayLoan(accountId, new String[] { "0", "4", "5", "4", "3", "2", "1", "0", "0", "0" }, false);
}
@Test(enabled = true)
public void shouldCalculateWeeklyRatePenaltyWithOutstandingOnLoanAccount() throws Exception {
final String accountId = setUpPenaltyAndLoanAccount(PENALTY_NAME[4], PenaltyFormParameters.PERIOD_NONE, "",
PenaltyFormParameters.FREQUENCY_WEEKLY, "0.5", PenaltyFormParameters.FORMULA_OUTSTANDING_LOAN, "0.1", "9,999,999,999");
changeDateTime(03, 3);
penaltyHelper.verifyCalculatePenaltyWithPayment(accountId,
new String[] { "61.1", "0", "61.1" },
new String[][] { { "0", "450" }, null /* Installments due */, { "40.6", "490.6" }, { "20.5", "470.5" }, null /* Future Installments */,
{ "0", "450" }, { "0", "450" }, { "0", "450" }, { "0", "450" }, { "0", "450" }, { "0", "450" }, { "0", "450" } },
new String[] { "1,411.1", "08/03/2012", "961.1" }
);
verifyAfterRepayLoan(accountId, new String[] { "0", "40.6", "20.5", "0", "0", "0", "0", "0", "0", "0" }, false);
}
@Test(enabled = true)
public void shouldCalculateWeeklyRatePenaltyWithOverdueOnLoanAccount() throws Exception {
final String accountId = setUpPenaltyAndLoanAccount(PENALTY_NAME[5], PenaltyFormParameters.PERIOD_NONE, "",
PenaltyFormParameters.FREQUENCY_WEEKLY, "1", PenaltyFormParameters.FORMULA_OVERDUE_AMOUNT, "0.1", "9,999,999,999");
changeDateTime(03, 3);
penaltyHelper.verifyCalculatePenaltyWithPayment(accountId,
new String[] { "13.5", "0", "13.5" },
new String[][] { { "0", "450" }, null /* Installments due */, { "9", "459" }, { "4.5", "454.5" }, null /* Future Installments */,
{ "0", "450" }, { "0", "450" }, { "0", "450" }, { "0", "450" }, { "0", "450" }, { "0", "450" }, { "0", "450" } },
new String[] { "1,363.5", "08/03/2012", "913.5" }
);
verifyAfterRepayLoan(accountId, new String[] { "0", "9", "4.5", "0", "0", "0", "0", "0", "0", "0" }, false);
}
@Test(enabled = true)
public void shouldCalculateWeeklyRatePenaltyWithPeriodOnLoanAccount() throws Exception {
final String accountId = setUpPenaltyAndLoanAccount(PENALTY_NAME[6], PenaltyFormParameters.PERIOD_DAYS, "7",
PenaltyFormParameters.FREQUENCY_WEEKLY, "0.1", PenaltyFormParameters.FORMULA_OUTSTANDING_PRINCIPAL, "0.1", "9,999,999,999");
changeDateTime(03, 22);
penaltyHelper.verifyCalculatePenaltyWithPayment(accountId,
new String[] { "27", "0", "27" },
new String[][] { { "0", "450" }, null /* Installments due */, { "13.5", "463.5" }, { "9", "459" }, { "4.5", "454.5" },
{ "0", "450" }, { "0", "450" }, null /* Future Installments */, { "0", "450" }, { "0", "450" }, { "0", "450" }, { "0", "450" } },
new String[] { "2,277", "22/03/2012", "1,827" }
);
verifyAfterRepayLoan(accountId, new String[] { "0", "13.5", "9", "4.5", "0", "0", "0", "0", "0", "0" }, false);
}
@Test(enabled = true)
public void shouldCalculateWeeklyRatePenaltyWithLimitsOnLoanAccount() throws Exception {
String accountId = setUpPenaltyAndLoanAccount(PENALTY_NAME[7], PenaltyFormParameters.PERIOD_NONE, "",
PenaltyFormParameters.FREQUENCY_WEEKLY, "1", PenaltyFormParameters.FORMULA_OVERDUE_AMOUNT, "5", "10");
changeDateTime(04, 1);
penaltyHelper.verifyCalculatePenaltyWithPayment(accountId,
new String[] { "10", "0", "10" },
new String[][] { { "0", "450" }, null /* Installments due */, { "9.6", "459.6" }, { "0.4", "450.4" }, { "0", "450" }, { "0", "450" },
{ "0", "450" }, { "0", "450" }, null /* Future Installments */, { "0", "450" }, { "0", "450" }, { "0", "450" } },
new String[] { "3,160", "05/04/2012", "2,710" }
);
verifyAfterRepayLoan(accountId, new String[] { "0", "9.6", "0.4", "0", "0", "0", "0", "0", "0", "0" }, false);
}
@Test(enabled = true)
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
public void shouldNotCalculatePenaltyAfterManuallyRunBatchJob() throws Exception {
String accountId = setUpPenaltyAndLoanAccount("Penalty Correct", PenaltyFormParameters.PERIOD_NONE, "",
PenaltyFormParameters.FREQUENCY_DAILY, "0.1", "9,999,999,999");
changeDateTime(03, 15);
for(int i = 0; i < 2; ++i) {
penaltyHelper.verifyCalculatePenaltyWithPayment(accountId,
new String[] { "42", "0", "42" },
new String[][] { { "0", "450" }, null /* Installments due */, { "21", "471" }, { "14", "464" }, { "7", "457" },
{ "0", "450" }, null /* Future Installments */, { "0", "450" }, { "0", "450" }, { "0", "450" }, { "0", "450" }, { "0", "450" } },
new String[] { "1,842", "15/03/2012", "1,392" }
);
navigationHelper.navigateToAdminPage();
new BatchJobHelper(selenium).runSomeBatchJobs(Arrays.asList("ApplyPenaltyToLoanAccountsTaskJob"));
}
}
private void verifyAfterRepayLoan(final String accountId, final String[] penalties, final boolean secondTime) throws Exception {
RepayLoanParameters params = new RepayLoanParameters();
params.setModeOfRepayment(RepayLoanParameters.CASH);
navigationHelper.navigateToLoanAccountPage(accountId)
.navigateToRepayLoan().submitAndNavigateToRepayLoanConfirmationPage(params)
.submitAndNavigateToLoanAccountDetailsPage();
BigDecimal sum = BigDecimal.ZERO;
BigDecimal principal = new BigDecimal(450);
String[][] schedule = new String[penalties.length][2];
for(int i = 0; i < penalties.length; ++i) {
BigDecimal penalty = BigDecimal.valueOf(Double.valueOf(penalties[i]));
sum = sum.add(penalty.setScale(1, BigDecimal.ROUND_HALF_UP));
schedule[i][0] = penalties[i];
schedule[i][1] = StringUtil.formatNumber(penalty.add(principal).setScale(1, BigDecimal.ROUND_HALF_UP).toString());
}
String sumToString = StringUtil.formatNumber(sum.toString());
penaltyHelper.verifyCalculatePenaltyWithPayment(accountId,
new String[] { sumToString, sumToString, "0" },
schedule,
null
);
if(!secondTime) {
changeDateTime(04, 5);
}
penaltyHelper.verifyCalculatePenaltyWithPayment(accountId,
new String[] { sumToString, sumToString, "0" },
schedule,
null
);
}
private String setUpPenaltyAndLoanAccount(final String name, final String period, final String duration,
final String frequency, final String min, final String max) throws Exception {
String penaltyName = name + StringUtil.getRandomString(4);
changeDateTime(02, 15);
penaltyHelper.createAmountPenalty(penaltyName, period, duration, frequency, min, max, "1");
return createWeeklyLoanAccountWithPenalty(penaltyName);
}
private String setUpPenaltyAndLoanAccount(final String name, final String period, final String duration, final String frequency,
final String rate, final String formula, final String min, final String max) throws Exception {
String penaltyName = name + StringUtil.getRandomString(4);
changeDateTime(02, 15);
penaltyHelper.createRatePenalty(penaltyName, period, duration, frequency, rate, formula, min, max);
return createWeeklyLoanAccountWithPenalty(penaltyName);
}
private String createWeeklyLoanAccountWithPenalty(final String penaltyName) throws Exception {
final SubmitFormParameters formParameters = FormParametersHelper.getWeeklyLoanProductParameters();
formParameters.addPenalty(penaltyName);
formParameters.setDefaultLoanAmount("4500");
formParameters.setInterestTypes(SubmitFormParameters.FLAT);
formParameters.setMinInterestRate("0");
formParameters.setMaxInterestRate("0");
formParameters.setDefaultInterestRate("0");
formParameters.setMaxInstallments("10");
formParameters.setDefInstallments("10");
LoanAccountPage loanAccountPage = penaltyHelper.createWeeklyLoanAccountWithPenalty(formParameters, "Client - Veronica Abisya", true);
PaymentParameters formPayment = new PaymentParameters();
formPayment.setTransactionDateDD("15");
formPayment.setTransactionDateMM("2");
formPayment.setTransactionDateYYYY("2012");
formPayment.setAmount("450");
formPayment.setPaymentType(PaymentParameters.CASH);
loanAccountPage.navigateToApplyPayment()
.submitAndNavigateToApplyPaymentConfirmationPage(formPayment)
.submitAndNavigateToLoanAccountDetailsPage();
penaltyHelper.verifyCalculatePenaltyWithPayment(loanAccountPage.getAccountId(),
new String[] { "0", "0", "0" },
new String[][] { { "0", "450" }, null /* Future Installments */, { "0", "450" }, { "0", "450" }, { "0", "450" }, { "0", "450" },
{ "0", "450" }, { "0", "450" }, { "0", "450" }, { "0", "450" }, { "0", "450" } },
new String[] { "0", "16/02/2012", "0" }
);
return loanAccountPage.getAccountId();
}
private void changeDateTime(final int month, final int day) throws Exception {
dateTimeUpdaterRemoteTestingService.setDateTime(new DateTime(2012, month, day, 13, 0, 0, 0));
navigationHelper.navigateToAdminPage();
new BatchJobHelper(selenium).runSomeBatchJobs(Arrays.asList("ApplyPenaltyToLoanAccountsTaskJob"));
}
}