FINERACT-33 : savings withhold tax changes
Project: http://git-wip-us.apache.org/repos/asf/incubator-fineract/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-fineract/commit/3015747f Tree: http://git-wip-us.apache.org/repos/asf/incubator-fineract/tree/3015747f Diff: http://git-wip-us.apache.org/repos/asf/incubator-fineract/diff/3015747f Branch: refs/heads/develop Commit: 3015747f3d0ddce9287035ccba6609f497865eaf Parents: 446ff44 Author: pramod <[email protected]> Authored: Mon Apr 11 14:44:59 2016 +0530 Committer: pramod <[email protected]> Committed: Mon Apr 11 14:44:59 2016 +0530 ---------------------------------------------------------------------- .../ClientSavingsIntegrationTest.java | 119 +++++- .../integrationtests/FixedDepositTest.java | 305 ++++++++++++++ .../integrationtests/RecurringDepositTest.java | 404 +++++++++++++++++++ .../common/TaxComponentHelper.java | 64 +++ .../integrationtests/common/TaxGroupHelper.java | 68 ++++ .../common/accounting/JournalEntryHelper.java | 15 +- .../FixedDepositAccountStatusChecker.java | 6 + .../fixeddeposit/FixedDepositProductHelper.java | 17 + .../RecurringDepositAccountStatusChecker.java | 6 + .../RecurringDepositProductHelper.java | 15 + .../common/savings/SavingsAccountHelper.java | 16 +- .../common/savings/SavingsProductHelper.java | 25 +- .../data/SavingsTransactionDTO.java | 8 +- .../journalentry/data/TaxPaymentDTO.java | 47 +++ .../service/AccountingProcessorHelper.java | 223 +++++++--- .../CashBasedAccountingProcessorForSavings.java | 7 + .../commands/service/CommandWrapperBuilder.java | 40 ++ .../charge/api/ChargesApiConstants.java | 1 + .../portfolio/charge/data/ChargeData.java | 60 +-- .../portfolio/charge/domain/Charge.java | 63 ++- ...efinitionCommandFromApiJsonDeserializer.java | 12 +- .../service/ChargeReadPlatformServiceImpl.java | 32 +- ...geWritePlatformServiceJpaRepositoryImpl.java | 39 +- .../LoanChargeReadPlatformServiceImpl.java | 4 +- .../portfolio/savings/DepositsApiConstants.java | 5 +- .../savings/SavingsAccountTransactionType.java | 12 +- .../portfolio/savings/SavingsApiConstants.java | 14 +- .../api/FixedDepositProductsApiResource.java | 12 +- .../RecurringDepositProductsApiResource.java | 11 +- .../savings/api/SavingsAccountsApiResource.java | 16 +- .../savings/api/SavingsProductsApiResource.java | 13 +- .../savings/data/DepositAccountData.java | 17 +- .../data/DepositAccountDataValidator.java | 14 +- .../savings/data/DepositProductData.java | 47 ++- .../data/DepositProductDataValidator.java | 30 ++ .../savings/data/FixedDepositAccountData.java | 25 +- .../savings/data/FixedDepositProductData.java | 38 +- .../data/RecurringDepositAccountData.java | 28 +- .../data/RecurringDepositProductData.java | 38 +- .../savings/data/SavingsAccountData.java | 43 +- .../data/SavingsAccountDataValidator.java | 11 + .../data/SavingsAccountStatusEnumData.java | 5 +- .../savings/data/SavingsAccountSummaryData.java | 4 +- .../data/SavingsAccountTransactionEnumData.java | 6 + .../savings/data/SavingsProductData.java | 52 ++- .../data/SavingsProductDataValidator.java | 43 +- .../savings/domain/DepositAccountAssembler.java | 16 +- .../domain/DepositAccountDomainServiceJpa.java | 49 ++- .../savings/domain/DepositProductAssembler.java | 33 +- .../savings/domain/FixedDepositAccount.java | 23 +- .../savings/domain/FixedDepositProduct.java | 14 +- .../savings/domain/RecurringDepositAccount.java | 19 +- .../savings/domain/RecurringDepositProduct.java | 10 +- .../savings/domain/SavingsAccount.java | 144 ++++++- .../savings/domain/SavingsAccountAssembler.java | 28 +- .../savings/domain/SavingsAccountSummary.java | 13 +- .../domain/SavingsAccountTransaction.java | 68 +++- ...SavingsAccountTransactionSummaryWrapper.java | 15 +- .../SavingsAccountTransactionTaxDetails.java | 63 +++ .../savings/domain/SavingsProduct.java | 98 +++-- .../savings/domain/SavingsProductAssembler.java | 36 +- ...WithHoldTaxSavingsAccountCommandHandler.java | 46 +++ .../DepositAccountReadPlatformServiceImpl.java | 37 +- .../DepositProductReadPlatformServiceImpl.java | 18 +- ...ctWritePlatformServiceJpaRepositoryImpl.java | 21 + ...ctWritePlatformServiceJpaRepositoryImpl.java | 22 + ...ngsAccountChargeReadPlatformServiceImpl.java | 5 +- .../SavingsAccountReadPlatformServiceImpl.java | 58 ++- .../SavingsAccountWritePlatformService.java | 2 + ...ntWritePlatformServiceJpaRepositoryImpl.java | 143 ++++--- .../savings/service/SavingsEnumerations.java | 29 +- .../SavingsProductReadPlatformServiceImpl.java | 98 +++-- ...ctWritePlatformServiceJpaRepositoryImpl.java | 33 +- .../portfolio/tax/api/TaxApiConstants.java | 38 ++ .../tax/api/TaxComponentApiResource.java | 140 +++++++ .../portfolio/tax/api/TaxGroupApiResource.java | 142 +++++++ .../portfolio/tax/data/TaxComponentData.java | 112 +++++ .../tax/data/TaxComponentHistoryData.java | 39 ++ .../portfolio/tax/data/TaxGroupData.java | 63 +++ .../tax/data/TaxGroupMappingsData.java | 40 ++ .../portfolio/tax/domain/TaxComponent.java | 222 ++++++++++ .../tax/domain/TaxComponentHistory.java | 92 +++++ .../tax/domain/TaxComponentRepository.java | 26 ++ .../domain/TaxComponentRepositoryWrapper.java | 43 ++ .../fineract/portfolio/tax/domain/TaxGroup.java | 117 ++++++ .../portfolio/tax/domain/TaxGroupMappings.java | 120 ++++++ .../tax/domain/TaxGroupRepository.java | 26 ++ .../tax/domain/TaxGroupRepositoryWrapper.java | 43 ++ .../TaxComponentNotFoundException.java | 28 ++ .../exception/TaxGroupNotFoundException.java | 28 ++ .../exception/TaxMappingNotFoundException.java | 34 ++ .../CreateTaxComponentCommandHandler.java | 45 +++ .../handler/CreateTaxGroupCommandHandler.java | 45 +++ .../UpdateTaxComponentCommandHandler.java | 45 +++ .../handler/UpdateTaxGroupCommandHandler.java | 45 +++ .../tax/serialization/TaxValidator.java | 365 +++++++++++++++++ .../portfolio/tax/service/TaxAssembler.java | 163 ++++++++ .../tax/service/TaxReadPlatformService.java | 44 ++ .../tax/service/TaxReadPlatformServiceImpl.java | 305 ++++++++++++++ .../portfolio/tax/service/TaxUtils.java | 94 +++++ .../tax/service/TaxWritePlatformService.java | 34 ++ .../service/TaxWritePlatformServiceImpl.java | 111 +++++ .../core_db/V298__savings_interest_tax.sql | 111 +++++ 103 files changed, 5490 insertions(+), 491 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java index 515eb5a..48a186b 100755 --- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/ClientSavingsIntegrationTest.java @@ -26,6 +26,7 @@ import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.HashMap; import java.util.List; @@ -33,6 +34,8 @@ import java.util.Locale; import org.apache.fineract.integrationtests.common.ClientHelper; import org.apache.fineract.integrationtests.common.CommonConstants; +import org.apache.fineract.integrationtests.common.TaxComponentHelper; +import org.apache.fineract.integrationtests.common.TaxGroupHelper; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.charges.ChargesHelper; import org.apache.fineract.integrationtests.common.savings.SavingsAccountHelper; @@ -789,7 +792,106 @@ public class ClientSavingsIntegrationTest { assertEquals("validation.msg.savingsaccount.close.results.in.balance.not.zero", savingsAccountErrorData.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE)); } + + @Test + public void testSavingsAccount_WITH_WITHHOLD_TAX() { + this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); + + final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + Assert.assertNotNull(clientID); + final String minBalanceForInterestCalculation = null; + final String minRequiredBalance = null; + final String enforceMinRequiredBalance = "false"; + final boolean allowOverdraft = false; + final String percentage = "10"; + final Integer taxGroupId = createTaxGroup(percentage); + final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE, + minBalanceForInterestCalculation, minRequiredBalance, enforceMinRequiredBalance, allowOverdraft, String.valueOf(taxGroupId)); + Assert.assertNotNull(savingsProductID); + + final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplication(clientID, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL); + Assert.assertNotNull(savingsProductID); + + HashMap modifications = this.savingsAccountHelper.updateSavingsAccount(clientID, savingsProductID, savingsId, + ACCOUNT_TYPE_INDIVIDUAL); + Assert.assertTrue(modifications.containsKey("submittedOnDate")); + + HashMap savingsStatusHashMap = SavingsStatusChecker.getStatusOfSavings(this.requestSpec, this.responseSpec, savingsId); + SavingsStatusChecker.verifySavingsIsPending(savingsStatusHashMap); + savingsStatusHashMap = this.savingsAccountHelper.approveSavings(savingsId); + SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap); + + savingsStatusHashMap = this.savingsAccountHelper.activateSavings(savingsId); + SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap); + + final HashMap summaryBefore = this.savingsAccountHelper.getSavingsSummary(savingsId); + this.savingsAccountHelper.calculateInterestForSavings(savingsId); + HashMap summary = this.savingsAccountHelper.getSavingsSummary(savingsId); + assertEquals(summaryBefore, summary); + + this.savingsAccountHelper.postInterestForSavings(savingsId); + summary = this.savingsAccountHelper.getSavingsSummary(savingsId); + Assert.assertFalse(summaryBefore.equals(summary)); + Assert.assertNotNull(summary.get("totalWithholdTax")); + Float expected = (Float) summary.get("totalDeposits") + (Float) summary.get("totalInterestPosted") + - (Float) summary.get("totalWithholdTax"); + Float actual = (Float) summary.get("accountBalance"); + Assert.assertEquals(expected, actual, 1); + + } + + @Test + public void testSavingsAccount_WITH_WITHHOLD_TAX_DISABLE_AT_ACCOUNT_LEVEL() { + this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); + + final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + Assert.assertNotNull(clientID); + final String minBalanceForInterestCalculation = null; + final String minRequiredBalance = null; + final String enforceMinRequiredBalance = "false"; + final boolean allowOverdraft = false; + final String percentage = "10"; + final Integer taxGroupId = createTaxGroup(percentage); + final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE, + minBalanceForInterestCalculation, minRequiredBalance, enforceMinRequiredBalance, allowOverdraft, String.valueOf(taxGroupId)); + Assert.assertNotNull(savingsProductID); + + final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplication(clientID, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL); + Assert.assertNotNull(savingsProductID); + + HashMap modifications = this.savingsAccountHelper.updateSavingsAccount(clientID, savingsProductID, savingsId, + ACCOUNT_TYPE_INDIVIDUAL); + Assert.assertTrue(modifications.containsKey("submittedOnDate")); + + HashMap savingsStatusHashMap = SavingsStatusChecker.getStatusOfSavings(this.requestSpec, this.responseSpec, savingsId); + SavingsStatusChecker.verifySavingsIsPending(savingsStatusHashMap); + + savingsStatusHashMap = this.savingsAccountHelper.approveSavings(savingsId); + SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap); + + savingsStatusHashMap = this.savingsAccountHelper.activateSavings(savingsId); + SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap); + + final HashMap summaryBefore = this.savingsAccountHelper.getSavingsSummary(savingsId); + this.savingsAccountHelper.calculateInterestForSavings(savingsId); + HashMap summary = this.savingsAccountHelper.getSavingsSummary(savingsId); + assertEquals(summaryBefore, summary); + + final HashMap changes = this.savingsAccountHelper.updateSavingsAccountWithHoldTaxStatus(savingsId, false); + Assert.assertTrue(changes.containsKey("withHoldTax")); + + this.savingsAccountHelper.postInterestForSavings(savingsId); + summary = this.savingsAccountHelper.getSavingsSummary(savingsId); + Assert.assertFalse(summaryBefore.equals(summary)); + Assert.assertNull(summary.get("totalWithholdTax")); + Float expected = (Float) summary.get("totalDeposits") + (Float) summary.get("totalInterestPosted"); + Float actual = (Float) summary.get("accountBalance"); + Assert.assertEquals(expected, actual, 1); + + } + + private HashMap activateSavingsAccount(final Integer savingsId, final String activationDate) { final HashMap status = this.savingsAccountHelper.activateSavingsAccount(savingsId, activationDate); return status; @@ -798,6 +900,14 @@ public class ClientSavingsIntegrationTest { private Integer createSavingsProduct(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, final String minOpenningBalance, String minBalanceForInterestCalculation, String minRequiredBalance, String enforceMinRequiredBalance, final boolean allowOverdraft) { + final String taxGroupId = null; + return createSavingsProduct(requestSpec, responseSpec, minOpenningBalance, minBalanceForInterestCalculation, minRequiredBalance, + enforceMinRequiredBalance, allowOverdraft, taxGroupId); + } + + private Integer createSavingsProduct(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + final String minOpenningBalance, String minBalanceForInterestCalculation, String minRequiredBalance, + String enforceMinRequiredBalance, final boolean allowOverdraft, final String taxGroupId) { System.out.println("------------------------------CREATING NEW SAVINGS PRODUCT ---------------------------------------"); SavingsProductHelper savingsProductHelper = new SavingsProductHelper(); if (allowOverdraft) { @@ -816,9 +926,16 @@ public class ClientSavingsIntegrationTest { .withMinBalanceForInterestCalculation(minBalanceForInterestCalculation) // .withMinRequiredBalance(minRequiredBalance).withEnforceMinRequiredBalance(enforceMinRequiredBalance) - .withMinimumOpenningBalance(minOpenningBalance).build(); + .withMinimumOpenningBalance(minOpenningBalance).withWithHoldTax(taxGroupId).build(); return SavingsProductHelper.createSavingsProduct(savingsProductJSON, requestSpec, responseSpec); } + + private Integer createTaxGroup(final String percentage){ + final Integer liabilityAccountId = null; + final Integer taxComponentId = TaxComponentHelper.createTaxComponent(this.requestSpec, this.responseSpec, percentage, liabilityAccountId); + return TaxGroupHelper.createTaxGroup(this.requestSpec, this.responseSpec, Arrays.asList(taxComponentId)); + } + /* * private void verifySavingsInterest(final Object savingsInterest) { http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/FixedDepositTest.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/FixedDepositTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/FixedDepositTest.java index fa638bc..d8a0ef6 100644 --- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/FixedDepositTest.java +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/FixedDepositTest.java @@ -27,6 +27,7 @@ import java.text.DecimalFormatSymbols; import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.HashMap; @@ -36,6 +37,9 @@ import java.util.Locale; import org.apache.fineract.accounting.common.AccountingConstants.FINANCIAL_ACTIVITY; import org.apache.fineract.integrationtests.common.ClientHelper; import org.apache.fineract.integrationtests.common.CommonConstants; +import org.apache.fineract.integrationtests.common.SchedulerJobHelper; +import org.apache.fineract.integrationtests.common.TaxComponentHelper; +import org.apache.fineract.integrationtests.common.TaxGroupHelper; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.accounting.Account; import org.apache.fineract.integrationtests.common.accounting.AccountHelper; @@ -240,6 +244,7 @@ public class FixedDepositTest { this.responseSpec, fixedDepositAccountId.toString()); FixedDepositAccountStatusChecker.verifyFixedDepositAccountIsPrematureClosed(fixedDepositAccountStatusHashMap); + /*** * Verify journal entry transactions for preclosure transaction */ @@ -253,6 +258,284 @@ public class FixedDepositTest { } + + @Test + public void testFixedDepositAccountWithPrematureClosureTypeWithdrawal_WITH_HOLD_TAX() { + this.fixedDepositProductHelper = new FixedDepositProductHelper(this.requestSpec, this.responseSpec); + this.accountHelper = new AccountHelper(this.requestSpec, this.responseSpec); + this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); + this.fixedDepositAccountHelper = new FixedDepositAccountHelper(this.requestSpec, this.responseSpec); + + /*** + * Create GL Accounts for product account mapping + */ + final Account assetAccount = this.accountHelper.createAssetAccount(); + final Account incomeAccount = this.accountHelper.createIncomeAccount(); + final Account expenseAccount = this.accountHelper.createExpenseAccount(); + final Account liabilityAccount = this.accountHelper.createLiabilityAccount(); + final Account liabilityAccountForTax = this.accountHelper.createLiabilityAccount(); + + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); + DateFormat monthDayFormat = new SimpleDateFormat("dd MMM", Locale.US); + DateFormat currentDateFormat = new SimpleDateFormat("dd"); + + Calendar todaysDate = Calendar.getInstance(); + todaysDate.add(Calendar.MONTH, -3); + final String VALID_FROM = dateFormat.format(todaysDate.getTime()); + todaysDate.add(Calendar.YEAR, 10); + final String VALID_TO = dateFormat.format(todaysDate.getTime()); + + todaysDate = Calendar.getInstance(); + todaysDate.add(Calendar.MONTH, -1); + final String SUBMITTED_ON_DATE = dateFormat.format(todaysDate.getTime()); + final String APPROVED_ON_DATE = dateFormat.format(todaysDate.getTime()); + final String ACTIVATION_DATE = dateFormat.format(todaysDate.getTime()); + final String MONTH_DAY = monthDayFormat.format(todaysDate.getTime()); + + Integer currentDate = new Integer(currentDateFormat.format(todaysDate.getTime())); + Integer daysInMonth = todaysDate.getActualMaximum(Calendar.DATE); + Integer numberOfDaysLeft = (daysInMonth - currentDate) + 1; + todaysDate.add(Calendar.DATE, numberOfDaysLeft); + final String INTEREST_POSTED_DATE = dateFormat.format(todaysDate.getTime()); + final String CLOSED_ON_DATE = dateFormat.format(Calendar.getInstance().getTime()); + + Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec); + Assert.assertNotNull(clientId); + + /*** + * Create FD product with CashBased accounting enabled + */ + final String accountingRule = CASH_BASED; + final Integer taxGroupId = createTaxGroup("10", liabilityAccountForTax); + Integer fixedDepositProductId = createFixedDepositProductWithWithHoldTax(VALID_FROM, VALID_TO, String.valueOf(taxGroupId), + accountingRule, assetAccount, liabilityAccount, incomeAccount, expenseAccount); + Assert.assertNotNull(fixedDepositProductId); + + /*** + * Apply for FD account with created product and verify status + */ + Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), + SUBMITTED_ON_DATE, WHOLE_TERM); + Assert.assertNotNull(fixedDepositAccountId); + + HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec, + this.responseSpec, fixedDepositAccountId.toString()); + FixedDepositAccountStatusChecker.verifyFixedDepositIsPending(fixedDepositAccountStatusHashMap); + + /*** + * Approve the FD account and verify whether account is approved + */ + fixedDepositAccountStatusHashMap = this.fixedDepositAccountHelper.approveFixedDeposit(fixedDepositAccountId, APPROVED_ON_DATE); + FixedDepositAccountStatusChecker.verifyFixedDepositIsApproved(fixedDepositAccountStatusHashMap); + + /*** + * Activate the FD Account and verify whether account is activated + */ + fixedDepositAccountStatusHashMap = this.fixedDepositAccountHelper.activateFixedDeposit(fixedDepositAccountId, ACTIVATION_DATE); + FixedDepositAccountStatusChecker.verifyFixedDepositIsActive(fixedDepositAccountStatusHashMap); + + HashMap accountSummary = this.fixedDepositAccountHelper.getFixedDepositSummary(fixedDepositAccountId); + + Float depositAmount = (Float) accountSummary.get("totalDeposits"); + + /*** + * Verify journal entries posted for initial deposit transaction which + * happened at activation time + */ + final JournalEntry[] assetAccountInitialEntry = { new JournalEntry(depositAmount, JournalEntry.TransactionType.DEBIT) }; + final JournalEntry[] liablilityAccountInitialEntry = { new JournalEntry(depositAmount, JournalEntry.TransactionType.CREDIT) }; + this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, ACTIVATION_DATE, assetAccountInitialEntry); + this.journalEntryHelper.checkJournalEntryForLiabilityAccount(liabilityAccount, ACTIVATION_DATE, liablilityAccountInitialEntry); + + /*** + * Update interest earned of FD account + */ + fixedDepositAccountId = this.fixedDepositAccountHelper.calculateInterestForFixedDeposit(fixedDepositAccountId); + Assert.assertNotNull(fixedDepositAccountId); + + /*** + * Post interest and verify the account summary + */ + Integer transactionIdForPostInterest = this.fixedDepositAccountHelper.postInterestForFixedDeposit(fixedDepositAccountId); + Assert.assertNotNull(transactionIdForPostInterest); + + accountSummary = this.fixedDepositAccountHelper.getFixedDepositSummary(fixedDepositAccountId); + Float totalInterestPosted = (Float) accountSummary.get("totalInterestPosted"); + Assert.assertNull(accountSummary.get("totalWithholdTax")); + + /*** + * Verify journal entries transactions for interest posting transaction + */ + final JournalEntry[] expenseAccountEntry = { new JournalEntry(totalInterestPosted, JournalEntry.TransactionType.DEBIT) }; + final JournalEntry[] liablilityAccountEntry = { new JournalEntry(totalInterestPosted, JournalEntry.TransactionType.CREDIT) }; + this.journalEntryHelper.checkJournalEntryForAssetAccount(expenseAccount, INTEREST_POSTED_DATE, expenseAccountEntry); + this.journalEntryHelper.checkJournalEntryForLiabilityAccount(liabilityAccount, INTEREST_POSTED_DATE, liablilityAccountEntry); + + /*** + * Preclose the FD account verify whether account is preClosed + */ + HashMap fixedDepositPrematureData = this.fixedDepositAccountHelper.calculatePrematureAmountForFixedDeposit(fixedDepositAccountId, + CLOSED_ON_DATE); + + Integer prematureClosureTransactionId = (Integer) this.fixedDepositAccountHelper.prematureCloseForFixedDeposit( + fixedDepositAccountId, CLOSED_ON_DATE, CLOSURE_TYPE_WITHDRAW_DEPOSIT, null, CommonConstants.RESPONSE_RESOURCE_ID); + Assert.assertNotNull(prematureClosureTransactionId); + + fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec, + this.responseSpec, fixedDepositAccountId.toString()); + FixedDepositAccountStatusChecker.verifyFixedDepositAccountIsPrematureClosed(fixedDepositAccountStatusHashMap); + + /*** + * Verify journal entry transactions for preclosure transaction + */ + HashMap accountDetails = this.fixedDepositAccountHelper.getFixedDepositAccountById(this.requestSpec, this.responseSpec, + fixedDepositAccountId); + Float maturityAmount = Float.valueOf(accountDetails.get("maturityAmount").toString()); + + HashMap summary = (HashMap) accountDetails.get("summary"); + Assert.assertNotNull(summary.get("totalWithholdTax")); + Float withHoldTax = (Float) summary.get("totalWithholdTax"); + + this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, CLOSED_ON_DATE, new JournalEntry(maturityAmount, + JournalEntry.TransactionType.CREDIT)); + this.journalEntryHelper.checkJournalEntryForLiabilityAccount(liabilityAccount, CLOSED_ON_DATE, new JournalEntry(maturityAmount, + JournalEntry.TransactionType.DEBIT)); + this.journalEntryHelper.checkJournalEntryForLiabilityAccount(liabilityAccountForTax, CLOSED_ON_DATE, new JournalEntry(withHoldTax, + JournalEntry.TransactionType.CREDIT)); + + } + + + @Test + public void testFixedDepositAccountClosureTypeWithdrawal_WITH_HOLD_TAX() throws InterruptedException { + this.fixedDepositProductHelper = new FixedDepositProductHelper(this.requestSpec, this.responseSpec); + this.accountHelper = new AccountHelper(this.requestSpec, this.responseSpec); + this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); + this.fixedDepositAccountHelper = new FixedDepositAccountHelper(this.requestSpec, this.responseSpec); + + /*** + * Create GL Accounts for product account mapping + */ + final Account assetAccount = this.accountHelper.createAssetAccount(); + final Account incomeAccount = this.accountHelper.createIncomeAccount(); + final Account expenseAccount = this.accountHelper.createExpenseAccount(); + final Account liabilityAccount = this.accountHelper.createLiabilityAccount(); + final Account liabilityAccountForTax = this.accountHelper.createLiabilityAccount(); + + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); + DateFormat monthDayFormat = new SimpleDateFormat("dd MMM", Locale.US); + DateFormat currentDateFormat = new SimpleDateFormat("dd"); + + Calendar todaysDate = Calendar.getInstance(); + todaysDate.add(Calendar.MONTH, -20); + final String VALID_FROM = dateFormat.format(todaysDate.getTime()); + todaysDate.add(Calendar.YEAR, 10); + final String VALID_TO = dateFormat.format(todaysDate.getTime()); + + todaysDate = Calendar.getInstance(); + todaysDate.add(Calendar.MONTH, -20); + final String SUBMITTED_ON_DATE = dateFormat.format(todaysDate.getTime()); + final String APPROVED_ON_DATE = dateFormat.format(todaysDate.getTime()); + final String ACTIVATION_DATE = dateFormat.format(todaysDate.getTime()); + final String MONTH_DAY = monthDayFormat.format(todaysDate.getTime()); + + Integer currentDate = new Integer(currentDateFormat.format(todaysDate.getTime())); + Integer daysInMonth = todaysDate.getActualMaximum(Calendar.DATE); + Integer numberOfDaysLeft = (daysInMonth - currentDate) + 1; + todaysDate.add(Calendar.DATE, numberOfDaysLeft); + Calendar closedOn = Calendar.getInstance(); + closedOn.add(Calendar.MONTH, -6); + final String CLOSED_ON_DATE = dateFormat.format(closedOn.getTime()); + + Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec); + Assert.assertNotNull(clientId); + + /*** + * Create FD product with CashBased accounting enabled + */ + final String accountingRule = CASH_BASED; + final Integer taxGroupId = createTaxGroup("10", liabilityAccountForTax); + Integer fixedDepositProductId = createFixedDepositProductWithWithHoldTax(VALID_FROM, VALID_TO, String.valueOf(taxGroupId), + accountingRule, assetAccount, liabilityAccount, incomeAccount, expenseAccount); + Assert.assertNotNull(fixedDepositProductId); + + /*** + * Apply for FD account with created product and verify status + */ + Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), + SUBMITTED_ON_DATE, WHOLE_TERM); + Assert.assertNotNull(fixedDepositAccountId); + + HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec, + this.responseSpec, fixedDepositAccountId.toString()); + FixedDepositAccountStatusChecker.verifyFixedDepositIsPending(fixedDepositAccountStatusHashMap); + + /*** + * Approve the FD account and verify whether account is approved + */ + fixedDepositAccountStatusHashMap = this.fixedDepositAccountHelper.approveFixedDeposit(fixedDepositAccountId, APPROVED_ON_DATE); + FixedDepositAccountStatusChecker.verifyFixedDepositIsApproved(fixedDepositAccountStatusHashMap); + + /*** + * Activate the FD Account and verify whether account is activated + */ + fixedDepositAccountStatusHashMap = this.fixedDepositAccountHelper.activateFixedDeposit(fixedDepositAccountId, ACTIVATION_DATE); + FixedDepositAccountStatusChecker.verifyFixedDepositIsActive(fixedDepositAccountStatusHashMap); + + HashMap accountSummary = this.fixedDepositAccountHelper.getFixedDepositSummary(fixedDepositAccountId); + + Float depositAmount = (Float) accountSummary.get("totalDeposits"); + + /*** + * Verify journal entries posted for initial deposit transaction which + * happened at activation time + */ + final JournalEntry[] assetAccountInitialEntry = { new JournalEntry(depositAmount, JournalEntry.TransactionType.DEBIT) }; + final JournalEntry[] liablilityAccountInitialEntry = { new JournalEntry(depositAmount, JournalEntry.TransactionType.CREDIT) }; + this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, ACTIVATION_DATE, assetAccountInitialEntry); + this.journalEntryHelper.checkJournalEntryForLiabilityAccount(liabilityAccount, ACTIVATION_DATE, liablilityAccountInitialEntry); + + /*** + * Update interest earned of FD account + */ + fixedDepositAccountId = this.fixedDepositAccountHelper.calculateInterestForFixedDeposit(fixedDepositAccountId); + Assert.assertNotNull(fixedDepositAccountId); + + /*** + * Post interest and verify the account summary + */ + Integer transactionIdForPostInterest = this.fixedDepositAccountHelper.postInterestForFixedDeposit(fixedDepositAccountId); + Assert.assertNotNull(transactionIdForPostInterest); + + accountSummary = this.fixedDepositAccountHelper.getFixedDepositSummary(fixedDepositAccountId); + Float totalInterestPosted = (Float) accountSummary.get("totalInterestPosted"); + Assert.assertNull(accountSummary.get("totalWithholdTax")); + + /*** + * FD account verify whether account is matured + */ + + SchedulerJobHelper schedulerJobHelper = new SchedulerJobHelper(requestSpec, responseSpec); + String JobName = "Update Deposit Accounts Maturity details"; + schedulerJobHelper.executeJob(JobName); + + HashMap accountDetails = this.fixedDepositAccountHelper.getFixedDepositAccountById(this.requestSpec, this.responseSpec, + fixedDepositAccountId); + + HashMap summary = (HashMap) accountDetails.get("summary"); + Assert.assertNotNull(summary.get("totalWithholdTax")); + Float withHoldTax = (Float) summary.get("totalWithholdTax"); + this.journalEntryHelper.checkJournalEntryForLiabilityAccount(liabilityAccountForTax, CLOSED_ON_DATE, new JournalEntry(withHoldTax, + JournalEntry.TransactionType.CREDIT)); + + + fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec, + this.responseSpec, fixedDepositAccountId.toString()); + FixedDepositAccountStatusChecker.verifyFixedDepositAccountIsMatured(fixedDepositAccountStatusHashMap); + + } + + @Test public void testFixedDepositAccountWithPeriodInterestRateChart() { final String chartToUse = "period"; @@ -2139,6 +2422,22 @@ public class FixedDepositTest { return FixedDepositProductHelper.createFixedDepositProduct(fixedDepositProductJSON, requestSpec, responseSpec); } + + private Integer createFixedDepositProductWithWithHoldTax(final String validFrom, final String validTo, final String taxGroupId, + final String accountingRule, Account... accounts) { + System.out.println("------------------------------CREATING NEW FIXED DEPOSIT PRODUCT ---------------------------------------"); + FixedDepositProductHelper fixedDepositProductHelper = new FixedDepositProductHelper(this.requestSpec, this.responseSpec); + if (accountingRule.equals(CASH_BASED)) { + fixedDepositProductHelper = fixedDepositProductHelper.withAccountingRuleAsCashBased(accounts); + } else if (accountingRule.equals(NONE)) { + fixedDepositProductHelper = fixedDepositProductHelper.withAccountingRuleAsNone(); + } + final String fixedDepositProductJSON = fixedDepositProductHelper.withPeriodRangeChart() // + .withWithHoldTax(taxGroupId)// + .build(validFrom, validTo); + return FixedDepositProductHelper.createFixedDepositProduct(fixedDepositProductJSON, requestSpec, responseSpec); + } + private Integer createFixedDepositProduct(final String validFrom, final String validTo, final String accountingRule, final String chartToBePicked, Account... accounts) { System.out.println("------------------------------CREATING NEW FIXED DEPOSIT PRODUCT ---------------------------------------"); @@ -2262,6 +2561,12 @@ public class FixedDepositTest { Assert.assertEquals(financialActivityId, ((HashMap) mappingDetails.get("financialActivityData")).get("id")); Assert.assertEquals(glAccount.getAccountID(), ((HashMap) mappingDetails.get("glAccountData")).get("id")); } + + private Integer createTaxGroup(final String percentage, final Account liabilityAccountForTax){ + final Integer liabilityAccountId = liabilityAccountForTax.getAccountID(); + final Integer taxComponentId = TaxComponentHelper.createTaxComponent(this.requestSpec, this.responseSpec, percentage, liabilityAccountId); + return TaxGroupHelper.createTaxGroup(this.requestSpec, this.responseSpec, Arrays.asList(taxComponentId)); + } /** * Delete the Liability transfer account http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/RecurringDepositTest.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/RecurringDepositTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/RecurringDepositTest.java index 1d52aec..5ae093e 100644 --- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/RecurringDepositTest.java +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/RecurringDepositTest.java @@ -25,6 +25,7 @@ import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.HashMap; import java.util.List; @@ -35,6 +36,9 @@ import net.sf.ehcache.transaction.xa.EhcacheXAException; import org.apache.fineract.accounting.common.AccountingConstants.FINANCIAL_ACTIVITY; import org.apache.fineract.integrationtests.common.ClientHelper; import org.apache.fineract.integrationtests.common.CommonConstants; +import org.apache.fineract.integrationtests.common.SchedulerJobHelper; +import org.apache.fineract.integrationtests.common.TaxComponentHelper; +import org.apache.fineract.integrationtests.common.TaxGroupHelper; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.accounting.Account; import org.apache.fineract.integrationtests.common.accounting.AccountHelper; @@ -472,6 +476,384 @@ public class RecurringDepositTest { } + @Test + public void testRecurringDepositAccountWithPrematureClosureTypeTransferToSavings_WITH_HOLD_TAX() { + this.recurringDepositProductHelper = new RecurringDepositProductHelper(this.requestSpec, this.responseSpec); + this.accountHelper = new AccountHelper(this.requestSpec, this.responseSpec); + this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); + this.recurringDepositAccountHelper = new RecurringDepositAccountHelper(this.requestSpec, this.responseSpec); + + + /*** + * Create GL Accounts for product account mapping + */ + final Account assetAccount = this.accountHelper.createAssetAccount(); + final Account incomeAccount = this.accountHelper.createIncomeAccount(); + final Account expenseAccount = this.accountHelper.createExpenseAccount(); + final Account liabilityAccount = this.accountHelper.createLiabilityAccount(); + final Account liabilityAccountForTax = this.accountHelper.createLiabilityAccount(); + + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); + DateFormat monthDayFormat = new SimpleDateFormat("dd MMM", Locale.US); + DateFormat currentDateFormat = new SimpleDateFormat("dd"); + + Calendar todaysDate = Calendar.getInstance(); + todaysDate.add(Calendar.MONTH, -3); + final String VALID_FROM = dateFormat.format(todaysDate.getTime()); + todaysDate.add(Calendar.YEAR, 10); + final String VALID_TO = dateFormat.format(todaysDate.getTime()); + + todaysDate = Calendar.getInstance(); + todaysDate.add(Calendar.MONTH, -1); + final String SUBMITTED_ON_DATE = dateFormat.format(todaysDate.getTime()); + final String APPROVED_ON_DATE = dateFormat.format(todaysDate.getTime()); + final String ACTIVATION_DATE = dateFormat.format(todaysDate.getTime()); + final String EXPECTED_FIRST_DEPOSIT_ON_DATE = dateFormat.format(todaysDate.getTime()); + final String MONTH_DAY = monthDayFormat.format(todaysDate.getTime()); + + Integer currentDate = new Integer(currentDateFormat.format(todaysDate.getTime())); + Integer daysInMonth = todaysDate.getActualMaximum(Calendar.DATE); + Integer numberOfDaysLeft = (daysInMonth - currentDate) + 1; + todaysDate.add(Calendar.DATE, numberOfDaysLeft); + final String INTEREST_POSTED_DATE = dateFormat.format(todaysDate.getTime()); + final String CLOSED_ON_DATE = dateFormat.format(Calendar.getInstance().getTime()); + + /*** + * Create client for applying Deposit and Savings accounts + */ + Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec); + Assert.assertNotNull(clientId); + + /*** + * Create Savings product with CashBased accounting enabled + */ + final String accountingRule = CASH_BASED; + final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE, accountingRule, + assetAccount, liabilityAccount, incomeAccount, expenseAccount); + Assert.assertNotNull(savingsProductID); + + /*** + * Create Savings account and verify status is pending + */ + final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplication(clientId, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL); + Assert.assertNotNull(savingsProductID); + + HashMap savingsStatusHashMap = SavingsStatusChecker.getStatusOfSavings(this.requestSpec, this.responseSpec, savingsId); + SavingsStatusChecker.verifySavingsIsPending(savingsStatusHashMap); + + /*** + * Approve the savings account and verify account is approved + */ + savingsStatusHashMap = this.savingsAccountHelper.approveSavings(savingsId); + SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap); + + /*** + * Activate the savings account and verify account is activated + */ + savingsStatusHashMap = this.savingsAccountHelper.activateSavings(savingsId); + SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap); + + /*** + * Create RD product with CashBased accounting enabled + */ + final Integer taxGroupId = createTaxGroup("10", liabilityAccountForTax); + Integer recurringDepositProductId = createRecurringDepositProductWithWithHoldTax(VALID_FROM, VALID_TO,String.valueOf(taxGroupId), accountingRule, assetAccount, + liabilityAccount, incomeAccount, expenseAccount); + Assert.assertNotNull(recurringDepositProductId); + + /*** + * Apply for RD account with created product and verify status + */ + Integer recurringDepositAccountId = applyForRecurringDepositApplication(clientId.toString(), recurringDepositProductId.toString(), + VALID_FROM, VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM, EXPECTED_FIRST_DEPOSIT_ON_DATE); + Assert.assertNotNull(recurringDepositAccountId); + + HashMap recurringDepositAccountStatusHashMap = RecurringDepositAccountStatusChecker.getStatusOfRecurringDepositAccount( + this.requestSpec, this.responseSpec, recurringDepositAccountId.toString()); + RecurringDepositAccountStatusChecker.verifyRecurringDepositIsPending(recurringDepositAccountStatusHashMap); + + /*** + * Approve the RD account and verify whether account is approved + */ + recurringDepositAccountStatusHashMap = this.recurringDepositAccountHelper.approveRecurringDeposit(recurringDepositAccountId, + APPROVED_ON_DATE); + RecurringDepositAccountStatusChecker.verifyRecurringDepositIsApproved(recurringDepositAccountStatusHashMap); + + /*** + * Activate the RD Account and verify whether account is activated + */ + recurringDepositAccountStatusHashMap = this.recurringDepositAccountHelper.activateRecurringDeposit(recurringDepositAccountId, + ACTIVATION_DATE); + RecurringDepositAccountStatusChecker.verifyRecurringDepositIsActive(recurringDepositAccountStatusHashMap); + + HashMap recurringDepositAccountData = this.recurringDepositAccountHelper.getRecurringDepositAccountById(this.requestSpec, + this.responseSpec, recurringDepositAccountId); + Float depositAmount = (Float) recurringDepositAccountData.get("mandatoryRecommendedDepositAmount"); + + /*** + * Perform Deposit transaction and verify journal entries are posted for + * the transaction + */ + Integer depositTransactionId = this.recurringDepositAccountHelper.depositToRecurringDepositAccount(recurringDepositAccountId, + depositAmount, EXPECTED_FIRST_DEPOSIT_ON_DATE); + Assert.assertNotNull(depositTransactionId); + + this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, EXPECTED_FIRST_DEPOSIT_ON_DATE, new JournalEntry( + depositAmount, JournalEntry.TransactionType.DEBIT)); + this.journalEntryHelper.checkJournalEntryForLiabilityAccount(liabilityAccount, EXPECTED_FIRST_DEPOSIT_ON_DATE, new JournalEntry( + depositAmount, JournalEntry.TransactionType.CREDIT)); + + /*** + * Update interest earned field for RD account + */ + recurringDepositAccountId = this.recurringDepositAccountHelper.calculateInterestForRecurringDeposit(recurringDepositAccountId); + Assert.assertNotNull(recurringDepositAccountId); + + /*** + * Post interest and verify journal entries + */ + Integer transactionIdForPostInterest = this.recurringDepositAccountHelper + .postInterestForRecurringDeposit(recurringDepositAccountId); + Assert.assertNotNull(transactionIdForPostInterest); + + + HashMap accountSummary = this.recurringDepositAccountHelper.getRecurringDepositSummary(recurringDepositAccountId); + Float totalInterestPosted = (Float) accountSummary.get("totalInterestPosted"); + Assert.assertNull(accountSummary.get("totalWithholdTax")); + + + final JournalEntry[] expenseAccountEntry = { new JournalEntry(totalInterestPosted, JournalEntry.TransactionType.DEBIT) }; + final JournalEntry[] liablilityAccountEntry = { new JournalEntry(totalInterestPosted, JournalEntry.TransactionType.CREDIT) }; + this.journalEntryHelper.checkJournalEntryForAssetAccount(expenseAccount, INTEREST_POSTED_DATE, expenseAccountEntry); + this.journalEntryHelper.checkJournalEntryForLiabilityAccount(liabilityAccount, INTEREST_POSTED_DATE, liablilityAccountEntry); + + /*** + * Get saving account balance before preClosing RD account + */ + HashMap savingsSummaryBefore = this.savingsAccountHelper.getSavingsSummary(savingsId); + Float balanceBefore = (Float) savingsSummaryBefore.get("accountBalance"); + + HashMap recurringDepositPrematureData = this.recurringDepositAccountHelper.calculatePrematureAmountForRecurringDeposit( + recurringDepositAccountId, CLOSED_ON_DATE); + + /*** + * Retrieve mapped financial account for liability transfer + */ + Account financialAccount = getMappedLiabilityFinancialAccount(); + + /*** + * Preclose the RD account verify whether account is preClosed + */ + Integer prematureClosureTransactionId = (Integer) this.recurringDepositAccountHelper.prematureCloseForRecurringDeposit( + recurringDepositAccountId, CLOSED_ON_DATE, CLOSURE_TYPE_TRANSFER_TO_SAVINGS, savingsId, + CommonConstants.RESPONSE_RESOURCE_ID); + Assert.assertNotNull(prematureClosureTransactionId); + + recurringDepositAccountStatusHashMap = RecurringDepositAccountStatusChecker.getStatusOfRecurringDepositAccount(this.requestSpec, + this.responseSpec, recurringDepositAccountId.toString()); + RecurringDepositAccountStatusChecker.verifyRecurringDepositAccountIsPrematureClosed(recurringDepositAccountStatusHashMap); + + recurringDepositAccountData = this.recurringDepositAccountHelper.getRecurringDepositAccountById(this.requestSpec, + this.responseSpec, recurringDepositAccountId); + Float maturityAmount = Float.valueOf(recurringDepositAccountData.get("maturityAmount").toString()); + /*** + * Verify journal entry transactions for preclosure transaction As this + * transaction is an account transfer you should get financial account + * mapping details and verify amounts + */ + this.journalEntryHelper.checkJournalEntryForLiabilityAccount(liabilityAccount, CLOSED_ON_DATE, new JournalEntry(maturityAmount, + JournalEntry.TransactionType.CREDIT), new JournalEntry(maturityAmount, JournalEntry.TransactionType.DEBIT)); + + this.journalEntryHelper.checkJournalEntryForLiabilityAccount(financialAccount, CLOSED_ON_DATE, new JournalEntry(maturityAmount, + JournalEntry.TransactionType.DEBIT), new JournalEntry(maturityAmount, JournalEntry.TransactionType.CREDIT)); + /*** + * Verify rd account maturity amount and savings account balance + */ + HashMap recurringDepositData = this.recurringDepositAccountHelper.getRecurringDepositAccountById(this.requestSpec, + this.responseSpec, recurringDepositAccountId); + Float prematurityAmount = (Float) recurringDepositData.get("maturityAmount"); + HashMap summary = (HashMap) recurringDepositData.get("summary"); + Assert.assertNotNull(summary.get("totalWithholdTax")); + Float withHoldTax = (Float) summary.get("totalWithholdTax"); + this.journalEntryHelper.checkJournalEntryForLiabilityAccount(liabilityAccountForTax, CLOSED_ON_DATE, new JournalEntry(withHoldTax, + JournalEntry.TransactionType.CREDIT)); + + HashMap savingsSummaryAfter = this.savingsAccountHelper.getSavingsSummary(savingsId); + Float balanceAfter = (Float) savingsSummaryAfter.get("accountBalance"); + Float expectedSavingsBalance = balanceBefore + prematurityAmount; + + DecimalFormat decimalFormat = new DecimalFormat("", new DecimalFormatSymbols(Locale.US)); + decimalFormat.applyPattern("."); + + Assert.assertEquals("Verifying Savings Account Balance after Premature Closure", decimalFormat.format(expectedSavingsBalance), + decimalFormat.format(balanceAfter)); + + } + + + + @Test + public void testRecurringDepositAccountWithClosureTypeTransferToSavings_WITH_HOLD_TAX() throws InterruptedException { + this.recurringDepositProductHelper = new RecurringDepositProductHelper(this.requestSpec, this.responseSpec); + this.accountHelper = new AccountHelper(this.requestSpec, this.responseSpec); + this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); + this.recurringDepositAccountHelper = new RecurringDepositAccountHelper(this.requestSpec, this.responseSpec); + + + /*** + * Create GL Accounts for product account mapping + */ + final Account assetAccount = this.accountHelper.createAssetAccount(); + final Account incomeAccount = this.accountHelper.createIncomeAccount(); + final Account expenseAccount = this.accountHelper.createExpenseAccount(); + final Account liabilityAccount = this.accountHelper.createLiabilityAccount(); + final Account liabilityAccountForTax = this.accountHelper.createLiabilityAccount(); + + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy", Locale.US); + DateFormat monthDayFormat = new SimpleDateFormat("dd MMM", Locale.US); + DateFormat currentDateFormat = new SimpleDateFormat("dd"); + + Calendar todaysDate = Calendar.getInstance(); + todaysDate.add(Calendar.MONTH, -20); + final String VALID_FROM = dateFormat.format(todaysDate.getTime()); + todaysDate.add(Calendar.YEAR, 10); + final String VALID_TO = dateFormat.format(todaysDate.getTime()); + + todaysDate = Calendar.getInstance(); + todaysDate.add(Calendar.MONTH, -20); + final String SUBMITTED_ON_DATE = dateFormat.format(todaysDate.getTime()); + final String APPROVED_ON_DATE = dateFormat.format(todaysDate.getTime()); + final String ACTIVATION_DATE = dateFormat.format(todaysDate.getTime()); + final String EXPECTED_FIRST_DEPOSIT_ON_DATE = dateFormat.format(todaysDate.getTime()); + final String MONTH_DAY = monthDayFormat.format(todaysDate.getTime()); + + Integer currentDate = new Integer(currentDateFormat.format(todaysDate.getTime())); + Integer daysInMonth = todaysDate.getActualMaximum(Calendar.DATE); + Integer numberOfDaysLeft = (daysInMonth - currentDate) + 1; + todaysDate.add(Calendar.DATE, numberOfDaysLeft); + final String INTEREST_POSTED_DATE = dateFormat.format(todaysDate.getTime()); + Calendar closedOn = Calendar.getInstance(); + closedOn.add(Calendar.MONTH, -6); + final String CLOSED_ON_DATE = dateFormat.format(closedOn.getTime()); + + /*** + * Create client for applying Deposit and Savings accounts + */ + Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec); + Assert.assertNotNull(clientId); + + /*** + * Create Savings product with CashBased accounting enabled + */ + final String accountingRule = CASH_BASED; + final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE, accountingRule, + assetAccount, liabilityAccount, incomeAccount, expenseAccount); + Assert.assertNotNull(savingsProductID); + + /*** + * Create Savings account and verify status is pending + */ + final Integer savingsId = this.savingsAccountHelper.applyForSavingsApplication(clientId, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL); + Assert.assertNotNull(savingsProductID); + + HashMap savingsStatusHashMap = SavingsStatusChecker.getStatusOfSavings(this.requestSpec, this.responseSpec, savingsId); + SavingsStatusChecker.verifySavingsIsPending(savingsStatusHashMap); + + /*** + * Approve the savings account and verify account is approved + */ + savingsStatusHashMap = this.savingsAccountHelper.approveSavings(savingsId); + SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap); + + /*** + * Activate the savings account and verify account is activated + */ + savingsStatusHashMap = this.savingsAccountHelper.activateSavings(savingsId); + SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap); + + /*** + * Create RD product with CashBased accounting enabled + */ + final Integer taxGroupId = createTaxGroup("10", liabilityAccountForTax); + Integer recurringDepositProductId = createRecurringDepositProductWithWithHoldTax(VALID_FROM, VALID_TO,String.valueOf(taxGroupId), accountingRule, assetAccount, + liabilityAccount, incomeAccount, expenseAccount); + Assert.assertNotNull(recurringDepositProductId); + + /*** + * Apply for RD account with created product and verify status + */ + Integer recurringDepositAccountId = applyForRecurringDepositApplication(clientId.toString(), recurringDepositProductId.toString(), + VALID_FROM, VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM, EXPECTED_FIRST_DEPOSIT_ON_DATE); + Assert.assertNotNull(recurringDepositAccountId); + + HashMap recurringDepositAccountStatusHashMap = RecurringDepositAccountStatusChecker.getStatusOfRecurringDepositAccount( + this.requestSpec, this.responseSpec, recurringDepositAccountId.toString()); + RecurringDepositAccountStatusChecker.verifyRecurringDepositIsPending(recurringDepositAccountStatusHashMap); + + /*** + * Approve the RD account and verify whether account is approved + */ + recurringDepositAccountStatusHashMap = this.recurringDepositAccountHelper.approveRecurringDeposit(recurringDepositAccountId, + APPROVED_ON_DATE); + RecurringDepositAccountStatusChecker.verifyRecurringDepositIsApproved(recurringDepositAccountStatusHashMap); + + /*** + * Activate the RD Account and verify whether account is activated + */ + recurringDepositAccountStatusHashMap = this.recurringDepositAccountHelper.activateRecurringDeposit(recurringDepositAccountId, + ACTIVATION_DATE); + RecurringDepositAccountStatusChecker.verifyRecurringDepositIsActive(recurringDepositAccountStatusHashMap); + + HashMap recurringDepositAccountData = this.recurringDepositAccountHelper.getRecurringDepositAccountById(this.requestSpec, + this.responseSpec, recurringDepositAccountId); + Float depositAmount = (Float) recurringDepositAccountData.get("mandatoryRecommendedDepositAmount"); + + /*** + * Perform Deposit transaction and verify journal entries are posted for + * the transaction + */ + todaysDate = Calendar.getInstance(); + todaysDate.add(Calendar.MONTH, -20); + + for (int i = 0; i < 14; i++) { + Integer depositTransactionId = this.recurringDepositAccountHelper.depositToRecurringDepositAccount(recurringDepositAccountId, + depositAmount, dateFormat.format(todaysDate.getTime())); + Assert.assertNotNull(depositTransactionId); + + this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, dateFormat.format(todaysDate.getTime()), new JournalEntry( + depositAmount, JournalEntry.TransactionType.DEBIT)); + this.journalEntryHelper.checkJournalEntryForLiabilityAccount(liabilityAccount, dateFormat.format(todaysDate.getTime()), + new JournalEntry(depositAmount, JournalEntry.TransactionType.CREDIT)); + todaysDate.add(Calendar.MONTH, 1); + } + + /*** + * FD account verify whether account is matured + */ + + SchedulerJobHelper schedulerJobHelper = new SchedulerJobHelper(requestSpec, responseSpec); + String JobName = "Update Deposit Accounts Maturity details"; + schedulerJobHelper.executeJob(JobName); + + HashMap accountDetails = this.recurringDepositAccountHelper.getRecurringDepositAccountById(this.requestSpec, this.responseSpec, + recurringDepositAccountId); + + HashMap summary = (HashMap) accountDetails.get("summary"); + Assert.assertNotNull(summary.get("totalWithholdTax")); + Float withHoldTax = (Float) summary.get("totalWithholdTax"); + this.journalEntryHelper.checkJournalEntryForLiabilityAccount(liabilityAccountForTax, CLOSED_ON_DATE, new JournalEntry(withHoldTax, + JournalEntry.TransactionType.CREDIT)); + + + recurringDepositAccountStatusHashMap = RecurringDepositAccountStatusChecker.getStatusOfRecurringDepositAccount(this.requestSpec, + this.responseSpec, recurringDepositAccountId.toString()); + RecurringDepositAccountStatusChecker.verifyRecurringDepositAccountIsMatured(recurringDepositAccountStatusHashMap); + + + } + + + /*** * Test case for Recurring Deposit Account premature closure with * transaction type ReInvest and Cash Based accounting enabled @@ -2671,6 +3053,21 @@ public class RecurringDepositTest { final String recurringDepositProductJSON = recurringDepositProductHelper.withPeriodRangeChart().build(validFrom, validTo); return RecurringDepositProductHelper.createRecurringDepositProduct(recurringDepositProductJSON, requestSpec, responseSpec); } + + private Integer createRecurringDepositProductWithWithHoldTax(final String validFrom, final String validTo,final String taxGroupId, final String accountingRule, + Account... accounts) { + System.out.println("------------------------------CREATING NEW RECURRING DEPOSIT PRODUCT ---------------------------------------"); + RecurringDepositProductHelper recurringDepositProductHelper = new RecurringDepositProductHelper(this.requestSpec, this.responseSpec); + if (accountingRule.equals(CASH_BASED)) { + recurringDepositProductHelper = recurringDepositProductHelper.withAccountingRuleAsCashBased(accounts); + } else if (accountingRule.equals(NONE)) { + recurringDepositProductHelper = recurringDepositProductHelper.withAccountingRuleAsNone(); + } + final String recurringDepositProductJSON = recurringDepositProductHelper.withPeriodRangeChart() + .withWithHoldTax(taxGroupId)// + .build(validFrom, validTo); + return RecurringDepositProductHelper.createRecurringDepositProduct(recurringDepositProductJSON, requestSpec, responseSpec); + } private Integer createRecurringDepositProduct(final String validFrom, final String validTo, final String accountingRule, final String chartToBePicked, Account... accounts) { @@ -2793,6 +3190,13 @@ public class RecurringDepositTest { Assert.assertEquals(financialActivityId, ((HashMap) mappingDetails.get("financialActivityData")).get("id")); Assert.assertEquals(glAccount.getAccountID(), ((HashMap) mappingDetails.get("glAccountData")).get("id")); } + + private Integer createTaxGroup(final String percentage, final Account liabilityAccountForTax){ + final Integer liabilityAccountId = liabilityAccountForTax.getAccountID(); + final Integer taxComponentId = TaxComponentHelper.createTaxComponent(this.requestSpec, this.responseSpec, percentage, liabilityAccountId); + return TaxGroupHelper.createTaxGroup(this.requestSpec, this.responseSpec, Arrays.asList(taxComponentId)); + } + /** * Delete the Liability transfer account http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/TaxComponentHelper.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/TaxComponentHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/TaxComponentHelper.java new file mode 100644 index 0000000..80c3690 --- /dev/null +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/TaxComponentHelper.java @@ -0,0 +1,64 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.fineract.integrationtests.common; + +import java.util.HashMap; + +import org.apache.fineract.integrationtests.common.accounting.Account; + +import com.google.gson.Gson; +import com.jayway.restassured.specification.RequestSpecification; +import com.jayway.restassured.specification.ResponseSpecification; + +public class TaxComponentHelper { + + private static final String CREATE_TAX_COMPONENT_URL = "/fineract-provider/api/v1/taxes/component?" + Utils.TENANT_IDENTIFIER; + + public static Integer createTaxComponent(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + final String percentage, final Integer liabilityAccountId) { + System.out.println("---------------------------------CREATING A TAX COMPONENT---------------------------------------------"); + return Utils.performServerPost(requestSpec, responseSpec, CREATE_TAX_COMPONENT_URL, + getTaxComponentAsJSON(percentage, liabilityAccountId), "resourceId"); + } + + public static String getTaxComponentAsJSON(final String percentage, final Integer creditAccountId) { + final HashMap<String, String> map = getBasicTaxComponentMap(percentage); + if (creditAccountId != null) { + map.put("creditAccountType", Account.AccountType.LIABILITY.toString()); + map.put("creditAcountId", String.valueOf(creditAccountId)); + } + System.out.println("map : " + map); + return new Gson().toJson(map); + } + + public static HashMap<String, String> getBasicTaxComponentMap(final String percentage) { + final HashMap<String, String> map = new HashMap<>(); + map.put("name", randomNameGenerator("Tax_component_Name_", 5)); + map.put("dateFormat", "dd MMMM yyyy"); + map.put("locale", "en"); + map.put("percentage", percentage); + map.put("startDate", "01 January 2013"); + return map; + } + + public static String randomNameGenerator(final String prefix, final int lenOfRandomSuffix) { + return Utils.randomStringGenerator(prefix, lenOfRandomSuffix); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/TaxGroupHelper.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/TaxGroupHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/TaxGroupHelper.java new file mode 100644 index 0000000..f0faa0f --- /dev/null +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/TaxGroupHelper.java @@ -0,0 +1,68 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.fineract.integrationtests.common; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; + +import com.google.gson.Gson; +import com.jayway.restassured.specification.RequestSpecification; +import com.jayway.restassured.specification.ResponseSpecification; + +public class TaxGroupHelper { + + private static final String CREATE_TAX_COMPONENT_URL = "/fineract-provider/api/v1/taxes/group?" + Utils.TENANT_IDENTIFIER; + + public static Integer createTaxGroup(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + final Collection<Integer> taxComponentIds) { + System.out.println("---------------------------------CREATING A TAX GROUP---------------------------------------------"); + return Utils.performServerPost(requestSpec, responseSpec, CREATE_TAX_COMPONENT_URL, getTaxGroupAsJSON(taxComponentIds), "resourceId"); + } + + public static String getTaxGroupAsJSON(final Collection<Integer> taxComponentIds) { + final HashMap<String, Object> map = new HashMap<>(); + map.put("name", randomNameGenerator("Tax_component_Name_", 5)); + map.put("dateFormat", "dd MMMM yyyy"); + map.put("locale", "en"); + map.put("taxComponents", getTaxGroupComponents(taxComponentIds)); + return new Gson().toJson(map); + } + + public static List<HashMap<String, String>> getTaxGroupComponents(final Collection<Integer> taxComponentIds) { + List<HashMap<String, String>> taxGroupComponents = new ArrayList<>(); + for (Integer taxComponentId : taxComponentIds) { + taxGroupComponents.add(getTaxComponentMap(taxComponentId)); + } + return taxGroupComponents; + } + + public static HashMap<String, String> getTaxComponentMap(final Integer taxComponentId) { + final HashMap<String, String> map = new HashMap<>(); + map.put("taxComponentId", String.valueOf(taxComponentId)); + map.put("startDate", "01 January 2013"); + return map; + } + + public static String randomNameGenerator(final String prefix, final int lenOfRandomSuffix) { + return Utils.randomStringGenerator(prefix, lenOfRandomSuffix); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/accounting/JournalEntryHelper.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/accounting/JournalEntryHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/accounting/JournalEntryHelper.java index b549763..6bd4579 100644 --- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/accounting/JournalEntryHelper.java +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/accounting/JournalEntryHelper.java @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.HashMap; import org.apache.fineract.integrationtests.common.Utils; +import org.junit.Assert; import com.jayway.restassured.specification.RequestSpecification; import com.jayway.restassured.specification.ResponseSpecification; @@ -81,9 +82,17 @@ public class JournalEntryHelper { private void checkJournalEntry(final Integer officeId, final Account account, final String date, final JournalEntry... accountEntries) { final String url = createURLForGettingAccountEntries(account, date, officeId); final ArrayList<HashMap> response = Utils.performServerGet(this.requestSpec, this.responseSpec, url, "pageItems"); - for (int i = 0; i < accountEntries.length; i++) { - assertThat(getEntryValueFromJournalEntry(response, i), equalTo(accountEntries[i].getTransactionType())); - assertThat(getTransactionAmountFromJournalEntry(response, i), equalTo(accountEntries[i].getTransactionAmount())); + + for (JournalEntry entry : accountEntries) { + boolean matchFound = false; + for (HashMap map : response) { + final HashMap entryType = (HashMap) map.get("entryType"); + if (entry.getTransactionType().equals(entryType.get("value")) && entry.getTransactionAmount().equals(map.get("amount"))) { + matchFound = true; + break; + } + } + Assert.assertTrue("Journal Entry not found", matchFound); } } http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/fixeddeposit/FixedDepositAccountStatusChecker.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/fixeddeposit/FixedDepositAccountStatusChecker.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/fixeddeposit/FixedDepositAccountStatusChecker.java index fca5cec..c276af5 100644 --- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/fixeddeposit/FixedDepositAccountStatusChecker.java +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/fixeddeposit/FixedDepositAccountStatusChecker.java @@ -87,6 +87,12 @@ public class FixedDepositAccountStatusChecker { assertTrue("ERROR IN PREMATURELY CLOSING THE FIXED DEPOSIT ACCOUNT", getStatus(fixedDepositStatusHashMap, "prematureClosed")); System.out.println(fixedDepositStatusHashMap); } + + public static void verifyFixedDepositAccountIsMatured(HashMap fixedDepositStatusHashMap) { + System.out.println("--------------------- VERIFYING FIXED DEPOSIT APPLICATION IS MATURED ---------------------"); + assertTrue("ERROR IN MATURITY JOB OF THE FIXED DEPOSIT ACCOUNT", getStatus(fixedDepositStatusHashMap, "matured")); + System.out.println(fixedDepositStatusHashMap); + } private static boolean getStatus(final HashMap fixedDepositStatusMap, final String fixedDepositStatusString) { return (Boolean) fixedDepositStatusMap.get(fixedDepositStatusString); http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/fixeddeposit/FixedDepositProductHelper.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/fixeddeposit/FixedDepositProductHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/fixeddeposit/FixedDepositProductHelper.java index b20b6f9..f2bb04d 100644 --- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/fixeddeposit/FixedDepositProductHelper.java +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/fixeddeposit/FixedDepositProductHelper.java @@ -74,6 +74,7 @@ public class FixedDepositProductHelper { private static final String ACCRUAL_UPFRONT = "4"; private static final String WHOLE_TERM = "1"; private static final String TILL_PREMATURE_WITHDRAWAL = "2"; + private String name = Utils.randomNameGenerator("FIXED_DEPOSIT_PRODUCT_", 6); private String shortName = Utils.randomNameGenerator("", 4); @@ -99,6 +100,8 @@ public class FixedDepositProductHelper { private Account[] accountList = null; private List<HashMap<String, String>> chartSlabs = null; private boolean isPrimaryGroupingByAmount = false; + private Boolean withHoldTax = false; + private String taxGroupId = null; public String build(final String validFrom, final String validTo) { final HashMap<String, Object> map = new HashMap<>(); @@ -139,6 +142,11 @@ public class FixedDepositProductHelper { map.put("inMultiplesOfDepositTermTypeId", this.inMultiplesOfDepositTermTypeId); map.put("preClosurePenalInterest", this.preClosurePenalInterest); map.put("preClosurePenalInterestOnTypeId", this.preClosurePenalInterestOnTypeId); + map.put("withHoldTax", this.withHoldTax.toString()); + if (withHoldTax) { + map.put("taxGroupId", taxGroupId); + } + if (this.accountingRule.equals(CASH_BASED)) { @@ -381,6 +389,15 @@ public class FixedDepositProductHelper { this.chartSlabs = constructChartSlabWithAmountAndPeriodRange(); return this; } + + public FixedDepositProductHelper withWithHoldTax(final String taxGroupId) { + if (taxGroupId != null) { + this.withHoldTax = true; + this.taxGroupId = taxGroupId; + } + return this; + } + private Map<String, String> getAccountMappingForCashBased() { final Map<String, String> map = new HashMap<>(); http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/recurringdeposit/RecurringDepositAccountStatusChecker.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/recurringdeposit/RecurringDepositAccountStatusChecker.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/recurringdeposit/RecurringDepositAccountStatusChecker.java index 95cd69e..ae8a5a5 100644 --- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/recurringdeposit/RecurringDepositAccountStatusChecker.java +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/recurringdeposit/RecurringDepositAccountStatusChecker.java @@ -89,6 +89,12 @@ public class RecurringDepositAccountStatusChecker { getStatus(recurringDepositStatusHashMap, "prematureClosed")); System.out.println(recurringDepositStatusHashMap); } + + public static void verifyRecurringDepositAccountIsMatured(HashMap recurringDepositStatusHashMap) { + System.out.println("--------------------- VERIFYING RECURRING DEPOSIT APPLICATION IS MATURED ---------------------"); + assertTrue("ERROR IN MATURITY JOB OF THE RECURRING DEPOSIT ACCOUNT", getStatus(recurringDepositStatusHashMap, "matured")); + System.out.println(recurringDepositStatusHashMap); + } private static boolean getStatus(final HashMap recurringDepositStatusMap, final String recurringDepositStatusString) { return (Boolean) recurringDepositStatusMap.get(recurringDepositStatusString); http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/recurringdeposit/RecurringDepositProductHelper.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/recurringdeposit/RecurringDepositProductHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/recurringdeposit/RecurringDepositProductHelper.java index 16dc1d2..9114d6b 100644 --- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/recurringdeposit/RecurringDepositProductHelper.java +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/recurringdeposit/RecurringDepositProductHelper.java @@ -98,6 +98,8 @@ public class RecurringDepositProductHelper { private Account[] accountList = null; private List<HashMap<String, String>> chartSlabs = null; private boolean isPrimaryGroupingByAmount = false; + private Boolean withHoldTax = false; + private String taxGroupId = null; public String build(final String validFrom, final String validTo) { final HashMap<String, Object> map = new HashMap<>(); @@ -144,6 +146,10 @@ public class RecurringDepositProductHelper { map.put("depositAmount", this.depositAmount); map.put("minDepositAmount", this.minDepositAmount); map.put("maxDepositAmount", this.maxDepositAmount); + map.put("withHoldTax", this.withHoldTax.toString()); + if (withHoldTax) { + map.put("taxGroupId", taxGroupId); + } if (this.accountingRule.equals(CASH_BASED)) { map.putAll(getAccountMappingForCashBased()); @@ -184,6 +190,15 @@ public class RecurringDepositProductHelper { this.chartSlabs = constructChartSlabWithAmountAndPeriodRange(); return this; } + + public RecurringDepositProductHelper withWithHoldTax(final String taxGroupId) { + if (taxGroupId != null) { + this.withHoldTax = true; + this.taxGroupId = taxGroupId; + } + return this; + } + private Map<String, String> getAccountMappingForCashBased() { final Map<String, String> map = new HashMap<>(); http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsAccountHelper.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsAccountHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsAccountHelper.java index e78a9cd..7624738 100644 --- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsAccountHelper.java +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsAccountHelper.java @@ -48,6 +48,7 @@ public class SavingsAccountHelper { private static final String CALCULATE_INTEREST_SAVINGS_COMMAND = "calculateInterest"; private static final String POST_INTEREST_SAVINGS_COMMAND = "postInterest"; private static final String CLOSE_SAVINGS_COMMAND = "close"; + private static final String UPDATE_WITHHOLD_TAX_STATUS = "updateWithHoldTax"; private static final String DEPOSIT_SAVINGS_COMMAND = "deposit"; private static final String WITHDRAW_SAVINGS_COMMAND = "withdrawal"; @@ -96,6 +97,15 @@ public class SavingsAccountHelper { + Utils.TENANT_IDENTIFIER, savingsApplicationJSON, CommonConstants.RESPONSE_CHANGES); } + public HashMap updateSavingsAccountWithHoldTaxStatus(final Integer savingsId, final boolean value) { + final HashMap<String, Object> map = new HashMap<>(); + map.put("withHoldTax", value); + String json = new Gson().toJson(map); + + return Utils.performServerPut(this.requestSpec, this.responseSpec, SAVINGS_ACCOUNT_URL + "/" + savingsId + "?command=" + + UPDATE_WITHHOLD_TAX_STATUS + "&" + Utils.TENANT_IDENTIFIER, json, CommonConstants.RESPONSE_CHANGES); + } + public HashMap approveSavings(final Integer savingsID) { return approveSavingsOnDate(savingsID, null); } @@ -341,9 +351,9 @@ public class SavingsAccountHelper { final ArrayList<HashMap> response = Utils.performServerGet(requestSpec, responseSpec, URL, jSONAttribute); return response; } - - public Object getSavingsAccountDetail(final Integer savingsID, final String jsonAttribute){ - final String URL = SAVINGS_ACCOUNT_URL + "/" + savingsID + "?associations=all&" + Utils.TENANT_IDENTIFIER; + + public Object getSavingsAccountDetail(final Integer savingsID, final String jsonAttribute) { + final String URL = SAVINGS_ACCOUNT_URL + "/" + savingsID + "?associations=all&" + Utils.TENANT_IDENTIFIER; return Utils.performServerGet(requestSpec, responseSpec, URL, jsonAttribute); } http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/3015747f/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsProductHelper.java ---------------------------------------------------------------------- diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsProductHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsProductHelper.java index d7a3912..0eca50b 100644 --- a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsProductHelper.java +++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/savings/SavingsProductHelper.java @@ -83,9 +83,11 @@ public class SavingsProductHelper { private Account[] accountList = null; private String minBalanceForInterestCalculation = null; private String allowOverdraft = "false"; - private String overdraftLimit = null; + private String overdraftLimit = null; private String minRequiredBalance = null; private String enforceMinRequiredBalance = "false"; + private Boolean withHoldTax = false; + private String taxGroupId = null; public String build() { final HashMap<String, String> map = new HashMap<>(); @@ -121,7 +123,10 @@ public class SavingsProductHelper { map.put("overdraftLimit", this.overdraftLimit); map.put("minRequiredBalance", this.minRequiredBalance); map.put("enforceMinRequiredBalance", this.enforceMinRequiredBalance); - + map.put("withHoldTax", this.withHoldTax.toString()); + if (withHoldTax) { + map.put("taxGroupId", taxGroupId); + } if (this.accountingRule.equals(CASH_BASED)) { map.putAll(getAccountMappingForCashBased()); } @@ -144,7 +149,7 @@ public class SavingsProductHelper { this.minRequiredOpeningBalance = minBalance; return this; } - + public SavingsProductHelper withInterestCompoundingPeriodTypeAsMonthly() { this.interestCompoundingPeriodType = MONTHLY; return this; @@ -154,7 +159,7 @@ public class SavingsProductHelper { this.interestPostingPeriodType = MONTHLY; return this; } - + public SavingsProductHelper withMinBalanceForInterestCalculation(final String amount) { this.minBalanceForInterestCalculation = amount; return this; @@ -190,12 +195,12 @@ public class SavingsProductHelper { this.accountList = account_list; return this; } - + public SavingsProductHelper withMinRequiredBalance(String minBalance) { this.minRequiredBalance = minBalance; return this; } - + public SavingsProductHelper withEnforceMinRequiredBalance(String enforceMinRequiredBalance) { this.enforceMinRequiredBalance = enforceMinRequiredBalance; return this; @@ -207,6 +212,14 @@ public class SavingsProductHelper { return this; } + public SavingsProductHelper withWithHoldTax(final String taxGroupId) { + if (taxGroupId != null) { + this.withHoldTax = true; + this.taxGroupId = taxGroupId; + } + return this; + } + private Map<String, String> getAccountMappingForCashBased() { final Map<String, String> map = new HashMap<>(); if (accountList != null) {
