diff --git a/mifosng-db/migrations/core_db/V169__update_dashboard_reports_to_core_reports_use_report_to_false.sql b/mifosng-db/migrations/core_db/V169__update_dashboard_reports_to_core_reports_use_report_to_false.sql new file mode 100644 index 000000000..d6fbdb630 --- /dev/null +++ b/mifosng-db/migrations/core_db/V169__update_dashboard_reports_to_core_reports_use_report_to_false.sql @@ -0,0 +1 @@ +UPDATE stretchy_report SET core_report=1, use_report=0 WHERE report_name in ('ClientTrendsByDay','ClientTrendsByWeek','ClientTrendsByMonth','LoanTrendsByDay','LoanTrendsByWeek','LoanTrendsByMonth','Demand_Vs_Collection','Disbursal_Vs_Awaitingdisbursal'); \ No newline at end of file diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/AccountingScenarioIntegrationTest.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/AccountingScenarioIntegrationTest.java index 68ccffaa1..f1d2405f6 100644 --- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/AccountingScenarioIntegrationTest.java +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/AccountingScenarioIntegrationTest.java @@ -13,6 +13,7 @@ import org.junit.Before; import org.junit.Test; import org.mifosplatform.integrationtests.common.ClientHelper; import org.mifosplatform.integrationtests.common.CommonConstants; +import org.mifosplatform.integrationtests.common.SchedulerJobHelper; import org.mifosplatform.integrationtests.common.Utils; import org.mifosplatform.integrationtests.common.accounting.Account; import org.mifosplatform.integrationtests.common.accounting.AccountHelper; @@ -79,6 +80,7 @@ public class AccountingScenarioIntegrationTest { private FixedDepositAccountHelper fixedDepositAccountHelper; private RecurringDepositProductHelper recurringDepositProductHelper; private RecurringDepositAccountHelper recurringDepositAccountHelper; + private SchedulerJobHelper schedulerJobHelper; @Before public void setup() { @@ -90,10 +92,11 @@ public class AccountingScenarioIntegrationTest { this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec); this.accountHelper = new AccountHelper(this.requestSpec, this.responseSpec); this.journalEntryHelper = new JournalEntryHelper(this.requestSpec, this.responseSpec); + this.schedulerJobHelper = new SchedulerJobHelper(this.requestSpec, this.responseSpec); } @Test - public void checkAccountingFlow() { + public void checkUpfrontAccrualAccountingFlow() { final Account assetAccount = this.accountHelper.createAssetAccount(); final Account incomeAccount = this.accountHelper.createIncomeAccount(); final Account expenseAccount = this.accountHelper.createExpenseAccount(); @@ -518,4 +521,235 @@ public class AccountingScenarioIntegrationTest { return this.recurringDepositAccountHelper.applyRecurringDepositApplication(recurringDepositApplicationJSON, this.requestSpec, this.responseSpec); } + + @Test + public void checkPeriodicAccrualAccountingFlow() { + final Account assetAccount = this.accountHelper.createAssetAccount(); + final Account incomeAccount = this.accountHelper.createIncomeAccount(); + final Account expenseAccount = this.accountHelper.createExpenseAccount(); + final Account overpaymentAccount = this.accountHelper.createLiabilityAccount(); + + final Integer loanProductID = createLoanProductWithPeriodicAccrualAccountingEnabled(assetAccount, incomeAccount, expenseAccount, + overpaymentAccount); + + final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, this.DATE_OF_JOINING); + final Integer loanID = applyForLoanApplication(clientID, loanProductID); + + HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); + LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); + + loanStatusHashMap = this.loanTransactionHelper.approveLoan(this.EXPECTED_DISBURSAL_DATE, loanID); + LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap); + LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap); + + loanStatusHashMap = this.loanTransactionHelper.disburseLoan(this.EXPECTED_DISBURSAL_DATE, loanID); + LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap); + + // CHECK ACCOUNT ENTRIES + System.out.println("Entries ......"); + final float PRINCIPAL_VALUE_FOR_EACH_PERIOD = 2000.0f; + final float TOTAL_INTEREST = 1000.0f; + final JournalEntry[] assetAccountInitialEntry = { new JournalEntry(this.LP_PRINCIPAL, JournalEntry.TransactionType.CREDIT), + new JournalEntry(this.LP_PRINCIPAL, JournalEntry.TransactionType.DEBIT), }; + this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, this.EXPECTED_DISBURSAL_DATE, assetAccountInitialEntry); + + final String jobName = "Add Accrual Transactions"; + try { + this.schedulerJobHelper.excuteJob(jobName); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + // MAKE 1 + System.out.println("Repayment 1 ......"); + final float FIRST_INTEREST = 200.0f; + final float FIRST_PRINCIPAL = 2000.0f; + this.loanTransactionHelper.checkAccrualTransactionForRepayment(this.REPAYMENT_DATE[1], FIRST_INTEREST, loanID); + this.loanTransactionHelper.makeRepayment(this.REPAYMENT_DATE[1], this.REPAYMENT_AMOUNT[1], loanID); + float expected_value = this.LP_PRINCIPAL - PRINCIPAL_VALUE_FOR_EACH_PERIOD; + this.loanTransactionHelper.verifyRepaymentScheduleEntryFor(1, expected_value, loanID); + final JournalEntry[] assetAccountFirstEntry = { new JournalEntry(this.REPAYMENT_AMOUNT[1], JournalEntry.TransactionType.DEBIT), + new JournalEntry(FIRST_INTEREST, JournalEntry.TransactionType.CREDIT), + new JournalEntry(FIRST_PRINCIPAL, JournalEntry.TransactionType.CREDIT), }; + this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, this.REPAYMENT_DATE[1], assetAccountFirstEntry); + System.out.println("Repayment 1 Done......"); + + // REPAYMENT 2 + System.out.println("Repayment 2 ......"); + this.loanTransactionHelper.makeRepayment(this.REPAYMENT_DATE[2], this.REPAYMENT_AMOUNT[2], loanID); + final float SECOND_AND_THIRD_INTEREST = 400.0f; + final float SECOND_PRINCIPAL = this.REPAYMENT_AMOUNT[2] - SECOND_AND_THIRD_INTEREST; + expected_value = expected_value - PRINCIPAL_VALUE_FOR_EACH_PERIOD; + this.loanTransactionHelper.checkAccrualTransactionForRepayment(this.REPAYMENT_DATE[2], FIRST_INTEREST, loanID); + this.loanTransactionHelper.checkAccrualTransactionForRepayment(this.REPAYMENT_DATE[3], FIRST_INTEREST, loanID); + this.loanTransactionHelper.verifyRepaymentScheduleEntryFor(2, expected_value, loanID); + final JournalEntry[] assetAccountSecondEntry = { new JournalEntry(this.REPAYMENT_AMOUNT[2], JournalEntry.TransactionType.DEBIT), + new JournalEntry(SECOND_AND_THIRD_INTEREST, JournalEntry.TransactionType.CREDIT), + new JournalEntry(SECOND_PRINCIPAL, JournalEntry.TransactionType.CREDIT), }; + this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, this.REPAYMENT_DATE[2], assetAccountSecondEntry); + System.out.println("Repayment 2 Done ......"); + + // WAIVE INTEREST + System.out.println("Waive Interest ......"); + this.loanTransactionHelper.checkAccrualTransactionForRepayment(this.REPAYMENT_DATE[4], FIRST_INTEREST, loanID); + this.loanTransactionHelper.checkAccrualTransactionForRepayment(this.REPAYMENT_DATE[5], FIRST_INTEREST, loanID); + this.loanTransactionHelper.waiveInterest(this.REPAYMENT_DATE[4], this.AMOUNT_TO_BE_WAIVE.toString(), loanID); + + final JournalEntry waivedEntry = new JournalEntry(this.AMOUNT_TO_BE_WAIVE, JournalEntry.TransactionType.CREDIT); + this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, this.REPAYMENT_DATE[4], waivedEntry); + + final JournalEntry expenseJournalEntry = new JournalEntry(this.AMOUNT_TO_BE_WAIVE, JournalEntry.TransactionType.DEBIT); + this.journalEntryHelper.checkJournalEntryForExpenseAccount(expenseAccount, this.REPAYMENT_DATE[4], expenseJournalEntry); + System.out.println("Waive Interest Done......"); + + // REPAYMENT 3 + System.out.println("Repayment 3 ......"); + this.loanTransactionHelper.makeRepayment(this.REPAYMENT_DATE[3], this.REPAYMENT_AMOUNT[3], loanID); + expected_value = expected_value - PRINCIPAL_VALUE_FOR_EACH_PERIOD; + final JournalEntry[] assetAccountThirdEntry = { new JournalEntry(this.REPAYMENT_AMOUNT[3], JournalEntry.TransactionType.DEBIT), + new JournalEntry(this.REPAYMENT_AMOUNT[3], JournalEntry.TransactionType.CREDIT) }; + this.loanTransactionHelper.verifyRepaymentScheduleEntryFor(3, expected_value, loanID); + this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, this.REPAYMENT_DATE[3], assetAccountThirdEntry); + System.out.println("Repayment 3 Done ......"); + + // REPAYMENT 4 + System.out.println("Repayment 4 ......"); + this.loanTransactionHelper.makeRepayment(this.REPAYMENT_DATE[4], this.REPAYMENT_AMOUNT[4], loanID); + expected_value = expected_value - PRINCIPAL_VALUE_FOR_EACH_PERIOD; + this.loanTransactionHelper.verifyRepaymentScheduleEntryFor(4, expected_value, loanID); + final JournalEntry[] assetAccountFourthEntry = { new JournalEntry(this.REPAYMENT_AMOUNT[4], JournalEntry.TransactionType.DEBIT), + new JournalEntry(this.REPAYMENT_AMOUNT[4], JournalEntry.TransactionType.CREDIT) }; + this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, this.REPAYMENT_DATE[4], assetAccountFourthEntry); + System.out.println("Repayment 4 Done ......"); + + // Repayment 5 + System.out.println("Repayment 5 ......"); + final JournalEntry[] assetAccountFifthEntry = { new JournalEntry(this.REPAYMENT_AMOUNT[5], JournalEntry.TransactionType.DEBIT), + new JournalEntry(this.REPAYMENT_AMOUNT[5], JournalEntry.TransactionType.CREDIT) }; + expected_value = expected_value - PRINCIPAL_VALUE_FOR_EACH_PERIOD; + this.loanTransactionHelper.makeRepayment(this.REPAYMENT_DATE[5], this.REPAYMENT_AMOUNT[5], loanID); + this.loanTransactionHelper.verifyRepaymentScheduleEntryFor(5, expected_value, loanID); + this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, this.REPAYMENT_DATE[5], assetAccountFifthEntry); + System.out.println("Repayment 5 Done ......"); + } + + private Integer createLoanProductWithPeriodicAccrualAccountingEnabled(final Account... accounts) { + System.out.println("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------"); + final String loanProductJSON = new LoanProductTestBuilder().withPrincipal(this.LP_PRINCIPAL.toString()).withRepaymentTypeAsMonth() + .withRepaymentAfterEvery(this.LP_REPAYMENT_PERIOD).withNumberOfRepayments(this.LP_REPAYMENTS).withRepaymentTypeAsMonth() + .withinterestRatePerPeriod(this.LP_INTEREST_RATE).withInterestRateFrequencyTypeAsMonths() + .withAmortizationTypeAsEqualPrincipalPayment().withInterestTypeAsFlat().withAccountingRulePeriodicAccrual(accounts) + .build(null); + return this.loanTransactionHelper.getLoanProductId(loanProductJSON); + } + + @Test + public void checkCashBasedAccountingFlow() { + final Account assetAccount = this.accountHelper.createAssetAccount(); + final Account incomeAccount = this.accountHelper.createIncomeAccount(); + final Account expenseAccount = this.accountHelper.createExpenseAccount(); + final Account overpaymentAccount = this.accountHelper.createLiabilityAccount(); + + final Integer loanProductID = createLoanProductWithCashBasedAccountingEnabled(assetAccount, incomeAccount, expenseAccount, + overpaymentAccount); + + final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec, this.DATE_OF_JOINING); + final Integer loanID = applyForLoanApplication(clientID, loanProductID); + + HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID); + LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap); + + loanStatusHashMap = this.loanTransactionHelper.approveLoan(this.EXPECTED_DISBURSAL_DATE, loanID); + LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap); + LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap); + + loanStatusHashMap = this.loanTransactionHelper.disburseLoan(this.EXPECTED_DISBURSAL_DATE, loanID); + LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap); + + // CHECK ACCOUNT ENTRIES + System.out.println("Entries ......"); + final float PRINCIPAL_VALUE_FOR_EACH_PERIOD = 2000.0f; + final float TOTAL_INTEREST = 1000.0f; + final JournalEntry[] assetAccountInitialEntry = { new JournalEntry(this.LP_PRINCIPAL, JournalEntry.TransactionType.CREDIT), + new JournalEntry(this.LP_PRINCIPAL, JournalEntry.TransactionType.DEBIT) }; + this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, this.EXPECTED_DISBURSAL_DATE, assetAccountInitialEntry); + + // MAKE 1 + System.out.println("Repayment 1 ......"); + this.loanTransactionHelper.makeRepayment(this.REPAYMENT_DATE[1], this.REPAYMENT_AMOUNT[1], loanID); + final float FIRST_INTEREST = 200.0f; + final float FIRST_PRINCIPAL = 2000.0f; + float expected_value = this.LP_PRINCIPAL - PRINCIPAL_VALUE_FOR_EACH_PERIOD; + this.loanTransactionHelper.verifyRepaymentScheduleEntryFor(1, expected_value, loanID); + final JournalEntry[] assetAccountFirstEntry = { new JournalEntry(this.REPAYMENT_AMOUNT[1], JournalEntry.TransactionType.DEBIT), + new JournalEntry(FIRST_PRINCIPAL, JournalEntry.TransactionType.CREDIT) }; + this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, this.REPAYMENT_DATE[1], assetAccountFirstEntry); + System.out.println("CHECKING INCOME: ******************************************"); + this.journalEntryHelper.checkJournalEntryForIncomeAccount(incomeAccount, this.REPAYMENT_DATE[1], new JournalEntry(FIRST_INTEREST, + JournalEntry.TransactionType.CREDIT)); + System.out.println("Repayment 1 Done......"); + + // REPAYMENT 2 + System.out.println("Repayment 2 ......"); + this.loanTransactionHelper.makeRepayment(this.REPAYMENT_DATE[2], this.REPAYMENT_AMOUNT[2], loanID); + final float SECOND_AND_THIRD_INTEREST = 400.0f; + final float SECOND_PRINCIPAL = this.REPAYMENT_AMOUNT[2] - SECOND_AND_THIRD_INTEREST; + expected_value = expected_value - PRINCIPAL_VALUE_FOR_EACH_PERIOD; + this.loanTransactionHelper.verifyRepaymentScheduleEntryFor(2, expected_value, loanID); + final JournalEntry[] assetAccountSecondEntry = { new JournalEntry(this.REPAYMENT_AMOUNT[2], JournalEntry.TransactionType.DEBIT), + new JournalEntry(SECOND_PRINCIPAL, JournalEntry.TransactionType.CREDIT), }; + this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, this.REPAYMENT_DATE[2], assetAccountSecondEntry); + System.out.println("CHECKING INCOME: ******************************************"); + this.journalEntryHelper.checkJournalEntryForIncomeAccount(incomeAccount, this.REPAYMENT_DATE[2], new JournalEntry( + SECOND_AND_THIRD_INTEREST, JournalEntry.TransactionType.CREDIT)); + System.out.println("Repayment 2 Done ......"); + + // WAIVE INTEREST + System.out.println("Waive Interest ......"); + Integer transactionId = this.loanTransactionHelper.waiveInterestAndReturnTransactionId(this.REPAYMENT_DATE[4], this.AMOUNT_TO_BE_WAIVE.toString(), loanID); + // waive of fees and interest are not considered in cash based accounting, + this.journalEntryHelper.ensureNoAccountingTransactionsWithTransactionId("L"+transactionId); + + + + // REPAYMENT 3 + System.out.println("Repayment 3 ......"); + this.loanTransactionHelper.makeRepayment(this.REPAYMENT_DATE[3], this.REPAYMENT_AMOUNT[3], loanID); + expected_value = expected_value - PRINCIPAL_VALUE_FOR_EACH_PERIOD; + final JournalEntry[] assetAccountThirdEntry = { new JournalEntry(this.REPAYMENT_AMOUNT[3], JournalEntry.TransactionType.DEBIT), + new JournalEntry(this.REPAYMENT_AMOUNT[3], JournalEntry.TransactionType.CREDIT) }; + this.loanTransactionHelper.verifyRepaymentScheduleEntryFor(3, expected_value, loanID); + this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, this.REPAYMENT_DATE[3], assetAccountThirdEntry); + System.out.println("Repayment 3 Done ......"); + + // REPAYMENT 4 + System.out.println("Repayment 4 ......"); + this.loanTransactionHelper.makeRepayment(this.REPAYMENT_DATE[4], this.REPAYMENT_AMOUNT[4], loanID); + expected_value = expected_value - PRINCIPAL_VALUE_FOR_EACH_PERIOD; + this.loanTransactionHelper.verifyRepaymentScheduleEntryFor(4, expected_value, loanID); + final JournalEntry[] assetAccountFourthEntry = { new JournalEntry(this.REPAYMENT_AMOUNT[4], JournalEntry.TransactionType.DEBIT), + new JournalEntry(this.REPAYMENT_AMOUNT[4], JournalEntry.TransactionType.CREDIT) }; + this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, this.REPAYMENT_DATE[4], assetAccountFourthEntry); + System.out.println("Repayment 4 Done ......"); + + // Repayment 5 + System.out.println("Repayment 5 ......"); + final JournalEntry[] assetAccountFifthEntry = { new JournalEntry(this.REPAYMENT_AMOUNT[5], JournalEntry.TransactionType.DEBIT), + new JournalEntry(this.REPAYMENT_AMOUNT[5], JournalEntry.TransactionType.CREDIT) }; + expected_value = expected_value - PRINCIPAL_VALUE_FOR_EACH_PERIOD; + this.loanTransactionHelper.makeRepayment(this.REPAYMENT_DATE[5], this.REPAYMENT_AMOUNT[5], loanID); + this.loanTransactionHelper.verifyRepaymentScheduleEntryFor(5, expected_value, loanID); + this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, this.REPAYMENT_DATE[5], assetAccountFifthEntry); + System.out.println("Repayment 5 Done ......"); + } + + private Integer createLoanProductWithCashBasedAccountingEnabled(final Account... accounts) { + System.out.println("------------------------------CREATING NEW LOAN PRODUCT ---------------------------------------"); + final String loanProductJSON = new LoanProductTestBuilder().withPrincipal(this.LP_PRINCIPAL.toString()).withRepaymentTypeAsMonth() + .withRepaymentAfterEvery(this.LP_REPAYMENT_PERIOD).withNumberOfRepayments(this.LP_REPAYMENTS).withRepaymentTypeAsMonth() + .withinterestRatePerPeriod(this.LP_INTEREST_RATE).withInterestRateFrequencyTypeAsMonths() + .withAmortizationTypeAsEqualPrincipalPayment().withInterestTypeAsFlat().withAccountingRuleAsCashBased(accounts) + .build(null); + return this.loanTransactionHelper.getLoanProductId(loanProductJSON); + } } diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/SchedulerJobsTest.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/SchedulerJobsTest.java index 8f8c1ff13..c03d5ce3f 100644 --- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/SchedulerJobsTest.java +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/SchedulerJobsTest.java @@ -79,7 +79,7 @@ public class SchedulerJobsTest { Assert.assertEquals("Verifying Scheduler Job Updation", active, changes.get("active")); // Executing Scheduler Job - this.schedulerJobHelper.runSchedulerJob(this.requestSpec, this.responseSpecForSchedulerJob, jobId.toString()); + this.schedulerJobHelper.runSchedulerJob(this.requestSpec, jobId.toString()); // Retrieving Scheduler Job by ID schedulerJob = this.schedulerJobHelper.getSchedulerJobById(this.requestSpec, this.responseSpec, jobId.toString()); diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/SchedulerJobsTestResults.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/SchedulerJobsTestResults.java index b2be74179..70796fdb3 100644 --- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/SchedulerJobsTestResults.java +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/SchedulerJobsTestResults.java @@ -115,7 +115,7 @@ public class SchedulerJobsTestResults { HashMap summaryBefore = this.savingsAccountHelper.getSavingsSummary(savingsId); String JobName = "Apply Annual Fee For Savings"; - excuteJob(JobName); + this.schedulerJobHelper.excuteJob(JobName); final HashMap chargeData = ChargesHelper.getChargeById(this.requestSpec, this.responseSpec, annualFeeChargeId); Float chargeAmount = (Float) chargeData.get("amount"); @@ -155,7 +155,7 @@ public class SchedulerJobsTestResults { String JobName = "Post Interest For Savings"; - excuteJob(JobName); + this.schedulerJobHelper.excuteJob(JobName); final HashMap summaryAfter = this.savingsAccountHelper.getSavingsSummary(savingsId); Assert.assertNotSame("Verifying the Balance after running Post Interest for Savings Job", summaryBefore.get("accountBalance"), @@ -215,7 +215,7 @@ public class SchedulerJobsTestResults { final HashMap summaryBefore = this.savingsAccountHelper.getSavingsSummary(savingsId); String JobName = "Transfer Fee For Loans From Savings"; - excuteJob(JobName); + this.schedulerJobHelper.excuteJob(JobName); final HashMap summaryAfter = this.savingsAccountHelper.getSavingsSummary(savingsId); final HashMap chargeData = ChargesHelper.getChargeById(this.requestSpec, this.responseSpec, specifiedDueDateChargeId); @@ -286,7 +286,7 @@ public class SchedulerJobsTestResults { String JobName = "Apply Holidays To Loans"; - excuteJob(JobName); + this.schedulerJobHelper.excuteJob(JobName); final ArrayList repaymentScheduleDataAfterJob = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID); @@ -337,7 +337,7 @@ public class SchedulerJobsTestResults { String JobName = "Pay Due Savings Charges"; - excuteJob(JobName); + this.schedulerJobHelper.excuteJob(JobName); HashMap summaryAfter = this.savingsAccountHelper.getSavingsSummary(savingsId); final HashMap chargeData = ChargesHelper.getChargeById(this.requestSpec, this.responseSpec, specifiedDueDateChargeId); @@ -386,7 +386,7 @@ public class SchedulerJobsTestResults { String JobName = "Update Accounting Running Balances"; - excuteJob(JobName); + this.schedulerJobHelper.excuteJob(JobName); final HashMap runningBalanceAfter = this.accountHelper.getAccountingWithRunningBalanceById(accountID.toString()); final Integer INT_BALANCE = new Integer(MINIMUM_OPENING_BALANCE); @@ -421,7 +421,7 @@ public class SchedulerJobsTestResults { String JobName = "Update Loan Arrears Ageing"; - this.excuteJob(JobName); + this.schedulerJobHelper.excuteJob(JobName); HashMap loanSummaryData = this.loanTransactionHelper.getLoanSummary(this.requestSpec, this.responseSpec, loanID); Float totalLoanArrearsAging = (Float) loanSummaryData.get("principalOverdue") + (Float) loanSummaryData.get("interestOverdue"); @@ -476,7 +476,7 @@ public class SchedulerJobsTestResults { HashMap loanSummary = this.loanTransactionHelper.getLoanSummary(this.requestSpec, this.responseSpec, loanID); String JobName = "Update Loan Paid In Advance"; - excuteJob(JobName); + this.schedulerJobHelper.excuteJob(JobName); // Retrieving Loan Repayment Schedule after the successful // completion of // Update Loan Paid in Advance Scheduler Job @@ -539,7 +539,7 @@ public class SchedulerJobsTestResults { HashMap loanSummaryBefore = this.loanTransactionHelper.getLoanSummary(this.requestSpec, this.responseSpec, loanID); String JobName = "Update loan Summary"; - excuteJob(JobName); + this.schedulerJobHelper.excuteJob(JobName); Float expectedSummaryAfterJob = (Float) loanSummaryBefore.get("totalExpectedRepayment") - (Float) loanSummaryBefore.get("feeChargesPaid"); HashMap loanSummaryAfter = this.loanTransactionHelper.getLoanSummary(this.requestSpec, this.responseSpec, loanID); @@ -611,7 +611,7 @@ public class SchedulerJobsTestResults { Assert.assertNotNull(standingInstructionId); String JobName = "Execute Standing Instruction"; - excuteJob(JobName); + this.schedulerJobHelper.excuteJob(JobName); HashMap fromSavingsSummaryAfter = this.savingsAccountHelper.getSavingsSummary(fromSavingsId); Float fromSavingsBalanceAfter = (Float) fromSavingsSummaryAfter.get("accountBalance"); @@ -662,7 +662,7 @@ public class SchedulerJobsTestResults { this.responseSpec, loanID); String JobName = "Apply penalty to overdue loans"; - excuteJob(JobName); + this.schedulerJobHelper.excuteJob(JobName); final HashMap chargeData = ChargesHelper.getChargeById(this.requestSpec, this.responseSpec, overdueFeeChargeId); @@ -707,7 +707,7 @@ public class SchedulerJobsTestResults { Assert.assertFalse(isNPABefore); // Integer jobId = (Integer) allSchedulerJobsData.get(1).get("jobId"); String JobName = "Update Non Performing Assets"; - excuteJob(JobName); + this.schedulerJobHelper.excuteJob(JobName); final Boolean isNPAAfter = (Boolean) this.loanTransactionHelper.getLoanDetail(requestSpec, responseSpec, loanID, "isNPA"); Assert.assertTrue(isNPAAfter); } @@ -784,7 +784,7 @@ public class SchedulerJobsTestResults { Float interestPosted = (Float) fixedDepositSummary.get("accountBalance") - new Float(FixedDepositAccountHelper.depositAmount); String JobName = "Transfer Interest To Savings"; - excuteJob(JobName); + this.schedulerJobHelper.excuteJob(JobName); fixedDepositSummary = savingsAccountHelper.getSavingsSummary(fixedDepositAccountId); assertEquals("Verifying opening Balance", new Float(FixedDepositAccountHelper.depositAmount), fixedDepositSummary.get("accountBalance")); @@ -794,41 +794,6 @@ public class SchedulerJobsTestResults { validateNumberForEqualExcludePrecission(String.valueOf(balance), String.valueOf(summary.get("accountBalance"))); } - private void excuteJob(String JobName) throws InterruptedException { - ArrayList allSchedulerJobsData = this.schedulerJobHelper.getAllSchedulerJobs(this.requestSpec, this.responseSpec); - Assert.assertNotNull(allSchedulerJobsData); - - for (Integer jobIndex = 0; jobIndex < allSchedulerJobsData.size(); jobIndex++) { - if (allSchedulerJobsData.get(jobIndex).get("displayName").equals(JobName)) { - Integer jobId = (Integer) allSchedulerJobsData.get(jobIndex).get("jobId"); - - // Executing Scheduler Job - this.schedulerJobHelper.runSchedulerJob(this.requestSpec, this.responseSpecForSchedulerJob, jobId.toString()); - - // Retrieving Scheduler Job by ID - HashMap schedulerJob = this.schedulerJobHelper.getSchedulerJobById(this.requestSpec, this.responseSpec, jobId.toString()); - Assert.assertNotNull(schedulerJob); - - // Waiting for Job to complete - while ((Boolean) schedulerJob.get("currentlyRunning") == true) { - Thread.sleep(15000); - schedulerJob = this.schedulerJobHelper.getSchedulerJobById(this.requestSpec, this.responseSpec, jobId.toString()); - Assert.assertNotNull(schedulerJob); - System.out.println("Job is Still Running"); - } - - ArrayList jobHistoryData = this.schedulerJobHelper.getSchedulerJobHistory(this.requestSpec, this.responseSpec, - jobId.toString()); - - // Verifying the Status of the Recently executed Scheduler Job - Assert.assertEquals("Verifying Last Scheduler Job Status", "success", - jobHistoryData.get(jobHistoryData.size() - 1).get("status")); - - break; - } - } - } - private Integer createSavingsProduct(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final String minOpenningBalance) { System.out.println("------------------------------CREATING NEW SAVINGS PRODUCT ---------------------------------------"); diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/SchedulerJobHelper.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/SchedulerJobHelper.java index 70823beb6..f5efb06eb 100644 --- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/SchedulerJobHelper.java +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/SchedulerJobHelper.java @@ -4,11 +4,14 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Random; +import org.junit.Assert; + import com.google.gson.Gson; +import com.jayway.restassured.builder.ResponseSpecBuilder; import com.jayway.restassured.specification.RequestSpecification; import com.jayway.restassured.specification.ResponseSpecification; -@SuppressWarnings({ "unused", "rawtypes" }) +@SuppressWarnings({ "unused", "rawtypes", "unchecked" }) public class SchedulerJobHelper { private final RequestSpecification requestSpec; @@ -42,7 +45,7 @@ public class SchedulerJobHelper { } public static void updateSchedulerStatus(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final String command) { - final String UPDATE_SCHEDULER_STATUS_URL = "/mifosng-provider/api/v1/scheduler?command=" + command; + final String UPDATE_SCHEDULER_STATUS_URL = "/mifosng-provider/api/v1/scheduler?command=" + command +"&tenantIdentifier=default"; System.out.println("------------------------ UPDATING SCHEDULER STATUS -------------------------"); Utils.performServerPost(requestSpec, responseSpec, UPDATE_SCHEDULER_STATUS_URL, runSchedulerJobAsJSON(), null); } @@ -70,10 +73,10 @@ public class SchedulerJobHelper { final HashMap response = Utils.performServerGet(requestSpec, responseSpec, GET_SCHEDULER_STATUS_URL, ""); return (ArrayList) response.get("pageItems"); } - - public static void runSchedulerJob(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, - final String jobId) { - final String RUN_SCHEDULER_JOB_URL = "/mifosng-provider/api/v1/jobs/" + jobId + "?command=executeJob"; + + public static void runSchedulerJob(final RequestSpecification requestSpec, final String jobId) { + final ResponseSpecification responseSpec = new ResponseSpecBuilder().expectStatusCode(202).build(); + final String RUN_SCHEDULER_JOB_URL = "/mifosng-provider/api/v1/jobs/" + jobId + "?command=executeJob&tenantIdentifier=default"; System.out.println("------------------------ RUN SCHEDULER JOB -------------------------"); Utils.performServerPost(requestSpec, responseSpec, RUN_SCHEDULER_JOB_URL, runSchedulerJobAsJSON(), null); } @@ -85,4 +88,37 @@ public class SchedulerJobHelper { return runSchedulerJob; } + public void excuteJob(String JobName) throws InterruptedException { + ArrayList allSchedulerJobsData = getAllSchedulerJobs(this.requestSpec, this.responseSpec); + Assert.assertNotNull(allSchedulerJobsData); + + for (Integer jobIndex = 0; jobIndex < allSchedulerJobsData.size(); jobIndex++) { + if (allSchedulerJobsData.get(jobIndex).get("displayName").equals(JobName)) { + Integer jobId = (Integer) allSchedulerJobsData.get(jobIndex).get("jobId"); + + // Executing Scheduler Job + runSchedulerJob(this.requestSpec, jobId.toString()); + + // Retrieving Scheduler Job by ID + HashMap schedulerJob = getSchedulerJobById(this.requestSpec, this.responseSpec, jobId.toString()); + Assert.assertNotNull(schedulerJob); + + // Waiting for Job to complete + while ((Boolean) schedulerJob.get("currentlyRunning") == true) { + Thread.sleep(15000); + schedulerJob = getSchedulerJobById(this.requestSpec, this.responseSpec, jobId.toString()); + Assert.assertNotNull(schedulerJob); + System.out.println("Job is Still Running"); + } + + ArrayList jobHistoryData = getSchedulerJobHistory(this.requestSpec, this.responseSpec, jobId.toString()); + + // Verifying the Status of the Recently executed Scheduler Job + Assert.assertEquals("Verifying Last Scheduler Job Status", "success", + jobHistoryData.get(jobHistoryData.size() - 1).get("status")); + + break; + } + } + } } \ No newline at end of file diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/accounting/JournalEntryHelper.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/accounting/JournalEntryHelper.java index ea146b825..cc53c02e0 100644 --- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/accounting/JournalEntryHelper.java +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/accounting/JournalEntryHelper.java @@ -2,6 +2,7 @@ package org.mifosplatform.integrationtests.common.accounting; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.HashMap; @@ -38,6 +39,12 @@ public class JournalEntryHelper { checkJournalEntry(liabilityAccount, date, accountEntries); } + public void ensureNoAccountingTransactionsWithTransactionId(final String transactionId) { + ArrayList transactions = getJournalEntriesByTransactionId(transactionId); + assertTrue("Tranasactions are is not empty", transactions.isEmpty()); + + } + private String getEntryValueFromJournalEntry(final ArrayList entryResponse, final int entryNumber) { final HashMap map = (HashMap) entryResponse.get(entryNumber).get("entryType"); return (String) map.get("value"); @@ -62,4 +69,15 @@ public class JournalEntryHelper { + "&orderBy=id&sortOrder=desc&locale=en&dateFormat=dd MMMM yyyy"); } + private ArrayList getJournalEntriesByTransactionId(final String transactionId) { + final String url = createURLForGettingAccountEntriesByTransactionId(transactionId); + final ArrayList response = Utils.performServerGet(this.requestSpec, this.responseSpec, url, "pageItems"); + return response; + } + + private String createURLForGettingAccountEntriesByTransactionId(final String transactionId) { + return new String("/mifosng-provider/api/v1/journalentries?transactionId=" + transactionId + "&tenantIdentifier=default" + + "&orderBy=id&sortOrder=desc&locale=en&dateFormat=dd MMMM yyyy"); + } + } diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/loans/LoanTransactionHelper.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/loans/LoanTransactionHelper.java index 71a198d0d..c99f636e8 100644 --- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/loans/LoanTransactionHelper.java +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/loans/LoanTransactionHelper.java @@ -1,17 +1,22 @@ package org.mifosplatform.integrationtests.common.loans; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.HashMap; +import org.joda.time.LocalDate; import org.mifosplatform.integrationtests.common.Utils; import com.google.gson.Gson; import com.jayway.restassured.specification.RequestSpecification; import com.jayway.restassured.specification.ResponseSpecification; -@SuppressWarnings("rawtypes") +@SuppressWarnings({ "rawtypes", "unchecked", "cast" }) public class LoanTransactionHelper { private final RequestSpecification requestSpec; @@ -103,6 +108,12 @@ public class LoanTransactionHelper { public HashMap waiveInterest(final String date, final String amountToBeWaived, final Integer loanID) { return performLoanTransaction(createLoanTransactionURL(WAIVE_INTEREST_COMMAND, loanID), getWaiveBodyAsJSON(date, amountToBeWaived)); } + + public Integer waiveInterestAndReturnTransactionId(final String date, final String amountToBeWaived, final Integer loanID) { + Integer resourceId = Utils.performServerPost(this.requestSpec, this.responseSpec, createLoanTransactionURL(WAIVE_INTEREST_COMMAND, loanID), + getWaiveBodyAsJSON(date, amountToBeWaived), "resourceId"); + return resourceId; + } public HashMap makeRepayment(final String date, final Float amountToBePaid, final Integer loanID) { return performLoanTransaction(createLoanTransactionURL(MAKE_REPAYMENT_COMMAND, loanID), @@ -320,11 +331,39 @@ public class LoanTransactionHelper { return (HashMap) response.get("status"); } - @SuppressWarnings("unchecked") public void verifyRepaymentScheduleEntryFor(final int repaymentNumber, final float expectedPrincipalOutstanding, final Integer loanID) { System.out.println("---------------------------GETTING LOAN REPAYMENT SCHEDULE--------------------------------"); final ArrayList repaymentPeriods = getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID); assertEquals("Mismatch in Principal Loan Balance Outstanding ", expectedPrincipalOutstanding, repaymentPeriods.get(repaymentNumber) .get("principalLoanBalanceOutstanding")); } + + public void checkAccrualTransactionForRepayment(final String transactionDate, final Float interestAmount, final Integer loanID) { + + ArrayList transactions = (ArrayList) getLoanDetail(this.requestSpec, this.responseSpec, loanID, "transactions"); + boolean isTransactionFound = false; + for (int i = 0; i < transactions.size(); i++) { + HashMap transactionType = (HashMap) transactions.get(i).get("type"); + boolean isAccrualTransaction = (Boolean) transactionType.get("accrual"); + + if (isAccrualTransaction) { + ArrayList accrualEntryDateAsArray = (ArrayList)transactions.get(i).get("date"); + LocalDate accrualEntryDate = new LocalDate(accrualEntryDateAsArray.get(0),accrualEntryDateAsArray.get(1),accrualEntryDateAsArray.get(2)); + + try { + DateFormat df = new SimpleDateFormat("dd MMMM yyyy"); + LocalDate expectedTransactionDate = new LocalDate(df.parse(transactionDate)); + if (expectedTransactionDate.equals(accrualEntryDate)) { + isTransactionFound = true; + assertEquals("Mismatch in transaction amounts", interestAmount, (Float) transactions.get(i).get("amount")); + break; + } + } catch (ParseException e) { + e.printStackTrace(); + } + } + } + assertTrue("No Accrual entries are posted", isTransactionFound); + + } } \ No newline at end of file