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 cf81e07a8..0b3f75df1 100644 --- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/AccountingScenarioIntegrationTest.java +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/AccountingScenarioIntegrationTest.java @@ -658,6 +658,64 @@ public class AccountingScenarioIntegrationTest { System.out.println("Repayment 5 Done ......"); } + @Test + public void checkPeriodicAccrualAccountingFlow_OVER_PAYMENT() { + 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.executeJob(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; + final float FEE_PORTION = 0.0f; + final float PENALTY_PORTION = 0.0f; + this.loanTransactionHelper.checkAccrualTransactionForRepayment(getDateAsLocalDate(this.REPAYMENT_DATE[1]), FIRST_INTEREST, + FEE_PORTION, PENALTY_PORTION, loanID); + this.loanTransactionHelper.makeRepayment(this.REPAYMENT_DATE[1], 15000f, loanID); + float expected_value = this.LP_PRINCIPAL - PRINCIPAL_VALUE_FOR_EACH_PERIOD; + this.loanTransactionHelper.verifyRepaymentScheduleEntryFor(1, expected_value, loanID); + final JournalEntry[] assetAccountEntry = { new JournalEntry(15000f, JournalEntry.TransactionType.DEBIT), + new JournalEntry(1000f, JournalEntry.TransactionType.CREDIT), new JournalEntry(10000f, JournalEntry.TransactionType.CREDIT) }; + this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, this.REPAYMENT_DATE[1], assetAccountEntry); + this.journalEntryHelper.checkJournalEntryForLiabilityAccount(overpaymentAccount, this.REPAYMENT_DATE[1], new JournalEntry(4000f, + JournalEntry.TransactionType.CREDIT)); + System.out.println("Repayment Done......"); + + } + @Test public void checkPeriodicAccrualAccountingTillCurrentDateFlow() { final Account assetAccount = this.accountHelper.createAssetAccount(); diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientLoanIntegrationTest.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientLoanIntegrationTest.java index d4c29f4de..46e063c76 100644 --- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientLoanIntegrationTest.java +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientLoanIntegrationTest.java @@ -1953,8 +1953,10 @@ public class ClientLoanIntegrationTest { System.out.println("----------Make over payment for repayment 4 ------------"); this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("3220.60"), loanID); this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 January 2012", new JournalEntry( - Float.valueOf("3139.68"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("50.00"), + Float.valueOf("3220.60"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("50.00"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3089.68"), JournalEntry.TransactionType.CREDIT)); + this.journalEntryHelper.checkJournalEntryForLiabilityAccount(overpaymentAccount, "20 January 2012", new JournalEntry(80.92f, + JournalEntry.TransactionType.CREDIT)); loanStatusHashMap = (HashMap) this.loanTransactionHelper.getLoanDetail(this.requestSpec, this.responseSpec, loanID, "status"); LoanStatusChecker.verifyLoanAccountIsOverPaid(loanStatusHashMap); } @@ -2147,8 +2149,10 @@ public class ClientLoanIntegrationTest { System.out.println("----------Make over payment for repayment 4 ------------"); this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("3220.58"), loanID); this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 January 2012", new JournalEntry( - Float.valueOf("3120.58"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("30.90"), + Float.valueOf("3220.58"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("30.90"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3089.68"), JournalEntry.TransactionType.CREDIT)); + this.journalEntryHelper.checkJournalEntryForLiabilityAccount(overpaymentAccount, "20 January 2012", new JournalEntry(100f, + JournalEntry.TransactionType.CREDIT)); loanStatusHashMap = (HashMap) this.loanTransactionHelper.getLoanDetail(this.requestSpec, this.responseSpec, loanID, "status"); LoanStatusChecker.verifyLoanAccountIsOverPaid(loanStatusHashMap); } @@ -2356,8 +2360,10 @@ public class ClientLoanIntegrationTest { System.out.println("----------Make over payment for repayment 4 ------------"); this.loanTransactionHelper.makeRepayment("20 January 2012", Float.valueOf("3221.61"), loanID); this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "20 January 2012", new JournalEntry( - Float.valueOf("3121.19"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("31.51"), + Float.valueOf("3221.61"), JournalEntry.TransactionType.DEBIT), new JournalEntry(Float.valueOf("31.51"), JournalEntry.TransactionType.CREDIT), new JournalEntry(Float.valueOf("3089.68"), JournalEntry.TransactionType.CREDIT)); + this.journalEntryHelper.checkJournalEntryForLiabilityAccount(overpaymentAccount, "20 January 2012", new JournalEntry(100.42f, + JournalEntry.TransactionType.CREDIT)); loanStatusHashMap = (HashMap) this.loanTransactionHelper.getLoanDetail(this.requestSpec, this.responseSpec, loanID, "status"); LoanStatusChecker.verifyLoanAccountIsOverPaid(loanStatusHashMap); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java index 104af8f42..ea6298ec2 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java @@ -174,6 +174,7 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess final BigDecimal interestAmount = loanTransactionDTO.getInterest(); final BigDecimal feesAmount = loanTransactionDTO.getFees(); final BigDecimal penaltiesAmount = loanTransactionDTO.getPenalties(); + final BigDecimal overPaymentAmount = loanTransactionDTO.getOverPayment(); final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId(); final boolean isReversal = loanTransactionDTO.isReversed(); @@ -219,6 +220,12 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess loanProductId, paymentTypeId, loanId, transactionId, transactionDate, penaltiesAmount, isReversal); } } + + if (overPaymentAmount != null && !(overPaymentAmount.compareTo(BigDecimal.ZERO) == 0)) { + totalDebitAmount = totalDebitAmount.add(overPaymentAmount); + this.helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, ACCRUAL_ACCOUNTS_FOR_LOAN.OVERPAYMENT, loanProductId, + paymentTypeId, loanId, transactionId, transactionDate, overPaymentAmount, isReversal); + } /** * Single DEBIT transaction for write-offs or Repayments (and their