From d19ab1c8e4cb2c85d1da5bc01bdce266d47970ec Mon Sep 17 00:00:00 2001 From: Pramod Nuthakki Date: Wed, 24 Sep 2014 14:57:37 +0530 Subject: [PATCH] MIFOSX-1554 : added min balance check only for withdrawal transactions --- .../ClientSavingsIntegrationTest.java | 93 ++++++++++++++++--- .../savings/domain/SavingsAccount.java | 5 +- .../domain/SavingsAccountAssembler.java | 11 ++- 3 files changed, 93 insertions(+), 16 deletions(-) diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientSavingsIntegrationTest.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientSavingsIntegrationTest.java index 2b551fce4..575237b30 100755 --- a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientSavingsIntegrationTest.java +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ClientSavingsIntegrationTest.java @@ -185,10 +185,75 @@ public class ClientSavingsIntegrationTest { savingsAccountErrorData.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE)); withdrawBalance = "true"; - savingsStatusHashMap = this.savingsAccountHelper.closeSavingsAccount(savingsId, withdrawBalance); + savingsStatusHashMap = this.savingsAccountHelper.closeSavingsAccount(savingsId, withdrawBalance); SavingsStatusChecker.verifySavingsAccountIsClosed(savingsStatusHashMap); } + @SuppressWarnings("unchecked") + @Test + public void testSavingsAccount_WITH_ENFORCE_MIN_BALANCE() { + this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec); + final ResponseSpecification errorResponse = new ResponseSpecBuilder().expectStatusCode(403).build(); + final SavingsAccountHelper validationErrorHelper = new SavingsAccountHelper(this.requestSpec, errorResponse); + + final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec); + Assert.assertNotNull(clientID); + final String minBalanceForInterestCalculation = null; + final String minRequiredBalance = "1500.0"; + final String enforceMinRequiredBalance = "true"; + final boolean allowOverdraft = false; + final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, MINIMUM_OPENING_BALANCE, + minBalanceForInterestCalculation, minRequiredBalance, enforceMinRequiredBalance, allowOverdraft); + Assert.assertNotNull(savingsProductID); + + 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); + + final Integer savingsActivationChargeId = ChargesHelper.createCharges(this.requestSpec, this.responseSpec, + ChargesHelper.getSavingsActivationFeeJSON()); + Assert.assertNotNull(savingsActivationChargeId); + + this.savingsAccountHelper.addChargesForSavings(savingsId, savingsActivationChargeId); + + savingsStatusHashMap = this.savingsAccountHelper.approveSavings(savingsId); + SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap); + + savingsStatusHashMap = this.savingsAccountHelper.activateSavings(savingsId); + SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap); + + HashMap summary = this.savingsAccountHelper.getSavingsSummary(savingsId); + Float balance = new Float(MINIMUM_OPENING_BALANCE); + Float chargeAmt = 100f; + balance -= chargeAmt; + assertEquals("Verifying opening Balance", balance, summary.get("accountBalance")); + + DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy"); + Calendar todaysDate = Calendar.getInstance(); + final String TRANSACTION_DATE = dateFormat.format(todaysDate.getTime()); + final String withdrawAmt = "800"; + ArrayList savingsAccountErrorData = (ArrayList) validationErrorHelper.withdrawalFromSavingsAccount(savingsId, + withdrawAmt, TRANSACTION_DATE, CommonConstants.RESPONSE_ERROR); + assertEquals("error.msg.savingsaccount.transaction.insufficient.account.balance", + savingsAccountErrorData.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE)); + + Integer depositTransactionId = (Integer) this.savingsAccountHelper.depositToSavingsAccount(savingsId, DEPOSIT_AMOUNT, + TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID); + HashMap depositTransaction = this.savingsAccountHelper.getSavingsTransaction(savingsId, depositTransactionId); + balance += new Float(DEPOSIT_AMOUNT); + assertEquals("Verifying Deposit Amount", new Float(DEPOSIT_AMOUNT), depositTransaction.get("amount")); + assertEquals("Verifying Balance after Deposit", balance, depositTransaction.get("runningBalance")); + + Integer withdrawTransactionId = (Integer) this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, withdrawAmt, + TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID); + HashMap withdrawTransaction = this.savingsAccountHelper.getSavingsTransaction(savingsId, withdrawTransactionId); + balance -= new Float(withdrawAmt); + assertEquals("Verifying Withdrawal Amount", new Float(withdrawAmt), withdrawTransaction.get("amount")); + assertEquals("Verifying Balance after Withdrawal", balance, withdrawTransaction.get("runningBalance")); + } + @SuppressWarnings("unchecked") @Test public void testSavingsAccount_DELETE_APPLICATION() { @@ -521,7 +586,7 @@ public class ClientSavingsIntegrationTest { this.savingsAccountHelper.addChargesForSavings(savingsId, weeklyFeeId); charges = this.savingsAccountHelper.getSavingsCharges(savingsId); Assert.assertEquals(3, charges.size()); - + savingsChargeForPay = charges.get(2); final Integer weeklySavingsFeeId = (Integer) savingsChargeForPay.get("id"); @@ -529,7 +594,7 @@ public class ClientSavingsIntegrationTest { CommonConstants.RESPONSE_ERROR); assertEquals("validation.msg.savingsaccountcharge.inactivation.of.charge.not.allowed.when.charge.is.due", savingsAccountErrorData .get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE)); - + cal = Calendar.getInstance(); dates = (List) savingsChargeForPay.get("dueDate"); cal.set(Calendar.YEAR, (Integer) dates.get(0)); @@ -686,7 +751,7 @@ public class ClientSavingsIntegrationTest { interestPosted = new Float(decimalFormat.format(interestPosted)); actualInterestPosted = new Float(decimalFormat.format(actualInterestPosted)); assertEquals("Verifying interest posted", interestPosted, actualInterestPosted); - + todaysDate = Calendar.getInstance(); final String CLOSEDON_DATE = dateFormat.format(todaysDate.getTime()); String withdrawBalance = "false"; @@ -710,14 +775,18 @@ public class ClientSavingsIntegrationTest { final String overDraftLimit = "2000.0"; savingsProductHelper = savingsProductHelper.withOverDraft(overDraftLimit); } - - final String savingsProductJSON = savingsProductHelper // - .withInterestCompoundingPeriodTypeAsDaily() // - .withInterestPostingPeriodTypeAsMonthly() // - .withInterestCalculationPeriodTypeAsDailyBalance() // - .withMinBalanceForInterestCalculation(minBalanceForInterestCalculation)// - .withMinRequiredBalance(minRequiredBalance) - .withEnforceMinRequiredBalance(enforceMinRequiredBalance) + + final String savingsProductJSON = savingsProductHelper + // + .withInterestCompoundingPeriodTypeAsDaily() + // + .withInterestPostingPeriodTypeAsMonthly() + // + .withInterestCalculationPeriodTypeAsDailyBalance() + // + .withMinBalanceForInterestCalculation(minBalanceForInterestCalculation) + // + .withMinRequiredBalance(minRequiredBalance).withEnforceMinRequiredBalance(enforceMinRequiredBalance) .withMinimumOpenningBalance(minOpenningBalance).build(); return SavingsProductHelper.createSavingsProduct(savingsProductJSON, requestSpec, responseSpec); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java index 76c104f30..b36157080 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java @@ -845,18 +845,19 @@ public class SavingsAccount extends AbstractPersistable { public void validateAccountBalanceDoesNotBecomeNegative(final BigDecimal transactionAmount, final boolean isWithdrawBalance) { final List transactionsSortedByDate = retreiveListOfTransactions(); Money runningBalance = Money.zero(this.currency); - for (final SavingsAccountTransaction transaction : transactionsSortedByDate) { if (transaction.isNotReversed() && transaction.isCredit()) { runningBalance = runningBalance.plus(transaction.getAmount(this.currency)); } else if (transaction.isNotReversed() && transaction.isDebit()) { runningBalance = runningBalance.minus(transaction.getAmount(this.currency)); + } else { + continue; } final BigDecimal withdrawalFee = null; // deal with potential minRequiredBalance and // enforceMinRequiredBalance - if (!isWithdrawBalance && this.minRequiredBalance != null && this.enforceMinRequiredBalance) { + if (!isWithdrawBalance && this.minRequiredBalance != null && this.enforceMinRequiredBalance && transaction.isWithdrawal()) { if (runningBalance.minus(this.minRequiredBalance).isLessThanZero()) { throw new InsufficientAccountBalanceException( "transactionAmount", getAccountBalance(), withdrawalFee, transactionAmount); } } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountAssembler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountAssembler.java index 2d858d051..a314afe50 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountAssembler.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountAssembler.java @@ -226,9 +226,16 @@ public class SavingsAccountAssembler { boolean enforceMinRequiredBalance = false; if (command.parameterExists(enforceMinRequiredBalanceParamName)) { enforceMinRequiredBalance = command.booleanPrimitiveValueOfParameterNamed(enforceMinRequiredBalanceParamName); + } else { + enforceMinRequiredBalance = product.isMinRequiredBalanceEnforced(); + } + + BigDecimal minRequiredBalance = null; + if (command.parameterExists(overdraftLimitParamName)) { + minRequiredBalance = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(minRequiredBalanceParamName); + } else { + minRequiredBalance = product.minRequiredBalance(); } - - final BigDecimal minRequiredBalance = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(minRequiredBalanceParamName); final SavingsAccount account = SavingsAccount.createNewApplicationForSubmittal(client, group, product, fieldOfficer, accountNo, externalId, accountType, submittedOnDate, submittedBy, interestRate, interestCompoundingPeriodType,