fineract-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nazeer1100...@apache.org
Subject [1/2] fineract git commit: FINERACT-482 block account changes
Date Thu, 13 Jul 2017 14:04:37 GMT
Repository: fineract
Updated Branches:
  refs/heads/develop 5b808fecc -> 12f80f4ad


FINERACT-482 block account changes


Project: http://git-wip-us.apache.org/repos/asf/fineract/repo
Commit: http://git-wip-us.apache.org/repos/asf/fineract/commit/7368c3f1
Tree: http://git-wip-us.apache.org/repos/asf/fineract/tree/7368c3f1
Diff: http://git-wip-us.apache.org/repos/asf/fineract/diff/7368c3f1

Branch: refs/heads/develop
Commit: 7368c3f11add84ddf8dcee086eccc7b8f69d518a
Parents: 6946f1c
Author: ShruthiRajaram <shruthi@confluxtechnologies.com>
Authored: Wed Jul 12 17:59:18 2017 +0530
Committer: ShruthiRajaram <shruthi@confluxtechnologies.com>
Committed: Wed Jul 12 17:59:18 2017 +0530

----------------------------------------------------------------------
 .../ClientSavingsIntegrationTest.java           | 12 ++++--
 .../common/savings/SavingsAccountHelper.java    |  1 +
 .../portfolio/savings/SavingsApiConstants.java  |  1 +
 .../savings/api/SavingsApiSetConstants.java     |  2 +-
 .../savings/data/SavingsAccountData.java        | 21 ++++++----
 .../SavingsAccountTransactionDataValidator.java | 38 ++++++++++++------
 .../savings/domain/SavingsAccount.java          | 41 +++++++++++++++-----
 .../domain/SavingsAccountTransaction.java       |  4 ++
 .../SavingsAccountReadPlatformServiceImpl.java  | 15 +++++--
 ...ntWritePlatformServiceJpaRepositoryImpl.java |  5 ++-
 ...0__savings_account_transaction_releaseId.sql |  4 ++
 11 files changed, 106 insertions(+), 38 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/fineract/blob/7368c3f1/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 b279163..1ae2609 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
@@ -28,10 +28,12 @@ import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Calendar;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 
+import org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.apache.fineract.integrationtests.common.ClientHelper;
 import org.apache.fineract.integrationtests.common.CommonConstants;
 import org.apache.fineract.integrationtests.common.SchedulerJobHelper;
@@ -2214,13 +2216,17 @@ public class ClientSavingsIntegrationTest {
         Integer holdTransactionId = (Integer) this.savingsAccountHelper.holdAmountInSavingsAccount(savingsId,
String.valueOf(balance - 100),
                 SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
         error = (List) savingsAccountHelperValidationError.withdrawalFromSavingsAccount(savingsId,
"300",
-                SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_ERROR);
+                SavingsAccountHelper.TRANSACTION_DATE_PLUS_ONE, CommonConstants.RESPONSE_ERROR);
         assertEquals("error.msg.savingsaccount.transaction.insufficient.account.balance",
                 error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
 
         Integer releaseTransactionId = this.savingsAccountHelper.releaseAmount(savingsId,
holdTransactionId);
-        withdrawTransactionId = (Integer) this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId,
"300",
-                SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
+        Date today = DateUtils.getDateOfTenant();
+        String todayDate = today.toString();
+        SimpleDateFormat dt1 = new SimpleDateFormat("dd MMM yyyy");
+        todayDate = dt1.format(today).toString();
+        withdrawTransactionId = (Integer) this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId,
"300", todayDate,
+                CommonConstants.RESPONSE_RESOURCE_ID);
         withdrawTransaction = this.savingsAccountHelper.getSavingsTransaction(savingsId,
withdrawTransactionId);
         balance -= new Float("300");
         assertEquals("Verifying Withdrawal Amount", new Float("300"), withdrawTransaction.get("amount"));

http://git-wip-us.apache.org/repos/asf/fineract/blob/7368c3f1/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 c2cd4f9..d0752a3 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
@@ -69,6 +69,7 @@ public class SavingsAccountHelper {
     public static final String CREATED_DATE_PLUS_ONE = "09 January 2013";
     public static final String CREATED_DATE_MINUS_ONE = "07 January 2013";
     public static final String TRANSACTION_DATE = "01 March 2013";
+    public static final String TRANSACTION_DATE_PLUS_ONE = "02 March 2013";
     public static final String LAST_TRANSACTION_DATE = "01 March 2013";
     public static final String ACCOUNT_TYPE_INDIVIDUAL = "INDIVIDUAL";
 

http://git-wip-us.apache.org/repos/asf/fineract/blob/7368c3f1/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/SavingsApiConstants.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/SavingsApiConstants.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/SavingsApiConstants.java
index 1b8aa53..a2826ab 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/SavingsApiConstants.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/SavingsApiConstants.java
@@ -133,6 +133,7 @@ public class SavingsApiConstants {
     public static final String minBalanceForInterestCalculationParamName = "minBalanceForInterestCalculation";
     public static final String withdrawBalanceParamName = "withdrawBalance";
     public static final String onHoldFundsParamName = "onHoldFunds";
+    public static final String savingsAmountOnHold = "savingsAmountOnHold";
     public static final String withHoldTaxParamName = "withHoldTax";
     public static final String taxGroupIdParamName = "taxGroupId";
 

http://git-wip-us.apache.org/repos/asf/fineract/blob/7368c3f1/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsApiSetConstants.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsApiSetConstants.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsApiSetConstants.java
index 70ac7b4..36d319a 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsApiSetConstants.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsApiSetConstants.java
@@ -65,7 +65,7 @@ public class SavingsApiSetConstants extends SavingsApiConstants {
 			"interestCalculationTypeOptions", "interestCalculationDaysInYearTypeOptions",
 			"lockinPeriodFrequencyTypeOptions", "withdrawalFeeTypeOptions", "withdrawalFee", "annualFee",
 			onHoldFundsParamName, nominalAnnualInterestRateOverdraftParamName,
-			minOverdraftForInterestCalculationParamName, datatables));
+			minOverdraftForInterestCalculationParamName, datatables, savingsAmountOnHold));
 
 	protected static final Set<String> SAVINGS_TRANSACTION_RESPONSE_DATA_PARAMETERS =
new HashSet<>(
 			Arrays.asList(idParamName, "accountId", accountNoParamName, "currency", "amount", dateParamName,

http://git-wip-us.apache.org/repos/asf/fineract/blob/7368c3f1/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountData.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountData.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountData.java
index d06bbe9..32a0630 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountData.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountData.java
@@ -76,6 +76,7 @@ public class SavingsAccountData {
     private final Integer daysToInactive;
     private final Integer daysToDormancy;
     private final Integer daysToEscheat;
+    private final BigDecimal savingsAmountOnHold;
 
     // associations
     private final SavingsAccountSummaryData summary;
@@ -118,7 +119,7 @@ public class SavingsAccountData {
             final BigDecimal onHoldFunds, final BigDecimal nominalAnnualInterestRateOverdraft,
             final BigDecimal minOverdraftForInterestCalculation, final boolean withHoldTax,
final TaxGroupData taxGroup, 
             final LocalDate lastActiveTransactionDate, final boolean isDormancyTrackingActive,
final Integer daysToInactive, 
-            final Integer daysToDormancy, final Integer daysToEscheat) {
+            final Integer daysToDormancy, final Integer daysToEscheat, final BigDecimal savingsAmountOnHold)
{
 
         final Collection<SavingsProductData> productOptions = null;
         final Collection<StaffData> fieldOfficerOptions = null;
@@ -142,7 +143,7 @@ public class SavingsAccountData {
                 lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions,
allowOverdraft, overdraftLimit,
                 minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation,
onHoldFunds,
                 nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax,
taxGroup, 
-                lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy,
daysToEscheat);
+                lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy,
daysToEscheat, savingsAmountOnHold);
     }
 
     public static SavingsAccountData lookup(final Long accountId, final String accountNo,
final EnumOptionData depositType) {
@@ -204,6 +205,7 @@ public class SavingsAccountData {
         final Integer daysToInactive = null;
         final Integer daysToDormancy = null;
         final Integer daysToEscheat = null;
+        final BigDecimal savingsAmountOnHold = null;
 
         return new SavingsAccountData(accountId, accountNo, depositType, externalId, groupId,
groupName, clientId, clientName, productId,
                 productName, fieldOfficerId, fieldOfficerName, status, subStatus, timeline,
currency, nominalAnnualInterestRate,
@@ -214,7 +216,7 @@ public class SavingsAccountData {
                 lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions,
allowOverdraft, overdraftLimit,
                 minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation,
onHoldFunds,
                 nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax,
taxGroup, 
-                lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy,
daysToEscheat);
+                lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy,
daysToEscheat, savingsAmountOnHold);
     }
 
     public static SavingsAccountData lookupWithProductDetails(final Long accountId, final
String accountNo,
@@ -274,6 +276,7 @@ public class SavingsAccountData {
         final Integer daysToInactive = null;
         final Integer daysToDormancy = null;
         final Integer daysToEscheat = null;
+		final BigDecimal savingsAmountOnHold = null;
 
         return new SavingsAccountData(accountId, accountNo, depositType, externalId, groupId,
groupName, clientId, clientName, productId,
                 productName, fieldOfficerId, fieldOfficerName, status, subStatus, timeline,
currency, nominalAnnualInterestRate,
@@ -284,7 +287,7 @@ public class SavingsAccountData {
                 lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions,
allowOverdraft, overdraftLimit,
                 minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation,
onHoldFunds,
                 nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax,
taxGroup, 
-                lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy,
daysToEscheat);
+                lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy,
daysToEscheat, savingsAmountOnHold);
     }
 
     public static SavingsAccountData withTemplateOptions(final SavingsAccountData account,
final SavingsAccountData template,
@@ -320,7 +323,7 @@ public class SavingsAccountData {
                 account.minBalanceForInterestCalculation, account.onHoldFunds, account.nominalAnnualInterestRateOverdraft,
                 account.minOverdraftForInterestCalculation, account.withHoldTax, account.taxGroup,

                 account.lastActiveTransactionDate, account.isDormancyTrackingActive, account.daysToInactive,

-                account.daysToDormancy, account.daysToEscheat);
+                account.daysToDormancy, account.daysToEscheat, account.savingsAmountOnHold);
     }
 
     public static SavingsAccountData withTemplateOptions(final SavingsAccountData account,
@@ -345,7 +348,7 @@ public class SavingsAccountData {
                 account.overdraftLimit, account.minRequiredBalance, account.enforceMinRequiredBalance,
                 account.minBalanceForInterestCalculation, account.onHoldFunds, account.nominalAnnualInterestRateOverdraft,
                 account.minOverdraftForInterestCalculation, account.withHoldTax, account.taxGroup,
account.lastActiveTransactionDate, 
-                account.isDormancyTrackingActive, account.daysToInactive, account.daysToDormancy,
account.daysToEscheat);
+                account.isDormancyTrackingActive, account.daysToInactive, account.daysToDormancy,
account.daysToEscheat, account.savingsAmountOnHold);
     }
 
     public static SavingsAccountData withClientTemplate(final Long clientId, final String
clientName, final Long groupId,
@@ -407,6 +410,7 @@ public class SavingsAccountData {
         final Integer daysToInactive = null;
         final Integer daysToDormancy = null;
         final Integer daysToEscheat = null;
+		final BigDecimal savingsAmountOnHold = null;
 
         return new SavingsAccountData(id, accountNo, depositType, externalId, groupId, groupName,
clientId, clientName, productId,
                 productName, fieldOfficerId, fieldOfficerName, status, subStatus, timeline,
currency, nominalAnnualInterestRate,
@@ -417,7 +421,7 @@ public class SavingsAccountData {
                 lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions,
allowOverdraft, overdraftLimit,
                 minRequiredBalance, enforceMinRequiredBalance, minBalanceForInterestCalculation,
onHoldFunds,
                 nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax,
taxGroup, 
-                lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy,
daysToEscheat);
+                lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy,
daysToEscheat, savingsAmountOnHold);
     }
 
     private SavingsAccountData(final Long id, final String accountNo, final EnumOptionData
depositType, final String externalId,
@@ -441,7 +445,7 @@ public class SavingsAccountData {
             final BigDecimal onHoldFunds, final BigDecimal nominalAnnualInterestRateOverdraft,
             final BigDecimal minOverdraftForInterestCalculation, final boolean withHoldTax,
final TaxGroupData taxGroup, 
             final LocalDate lastActiveTransactionDate, final boolean isDormancyTrackingActive,
final Integer daysToInactive, 
-            final Integer daysToDormancy, final Integer daysToEscheat) {
+            final Integer daysToDormancy, final Integer daysToEscheat, final BigDecimal savingsAmountOnHold)
{
         this.id = id;
         this.accountNo = accountNo;
         this.depositType = depositType;
@@ -507,6 +511,7 @@ public class SavingsAccountData {
         this.daysToInactive = daysToInactive;
         this.daysToDormancy = daysToDormancy;
         this.daysToEscheat = daysToEscheat;
+        this.savingsAmountOnHold = savingsAmountOnHold;
     }
 
     private SavingsAccountChargeData getWithdrawalFee() {

http://git-wip-us.apache.org/repos/asf/fineract/blob/7368c3f1/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountTransactionDataValidator.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountTransactionDataValidator.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountTransactionDataValidator.java
index fcd7a88..02ae102 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountTransactionDataValidator.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountTransactionDataValidator.java
@@ -121,7 +121,7 @@ public class SavingsAccountTransactionDataValidator {
         throwExceptionIfValidationWarningsExist(dataValidationErrors);
     }
 
-    public void validateClosing(final JsonCommand command) {
+    public void validateClosing(final JsonCommand command, final SavingsAccount account)
{
         final String json = command.json();
 
         if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
@@ -144,6 +144,11 @@ public class SavingsAccountTransactionDataValidator {
             baseDataValidator.reset().parameter(withdrawBalanceParamName).value(withdrawBalance).isOneOfTheseValues(true,
false);
         }
 
+		if (account.getSavingsHoldAmount().compareTo(BigDecimal.ZERO) == 1) {
+			baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(
+					"amount.is.on.hold.release.the.amount.to.continue", account.getId());
+		}
+                      
         validatePaymentTypeDetails(baseDataValidator, element);
 
         throwExceptionIfValidationWarningsExist(dataValidationErrors);
@@ -192,10 +197,9 @@ public class SavingsAccountTransactionDataValidator {
             baseDataValidator.reset().parameter(SavingsApiConstants.statusParamName)
                     .failWithCodeNoParameterAddedToErrorCode(SavingsApiConstants.ERROR_MSG_SAVINGS_ACCOUNT_NOT_ACTIVE);
         }
-        account.holdFunds(amount);
-        if (account.getWithdrawableBalance().compareTo(BigDecimal.ZERO) == -1) {
+        account.holdAmount(amount);
+        if (account.getWithdrawableBalance().compareTo(BigDecimal.ZERO)==-1){
             baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("insufficient
balance", account.getId());
-            baseDataValidator.failWithCode("validation.msg.savingsaccount.insufficient balance",
"Insufficient balance");
         }
         LocalDate lastTransactionDate = account.retrieveLastTransactionDate();
         // compare two dates now
@@ -206,7 +210,8 @@ public class SavingsAccountTransactionDataValidator {
 
         throwExceptionIfValidationWarningsExist(dataValidationErrors);
         final PaymentDetail paymentDetails = null;
-        Date createdDate = DateUtils.getDateOfTenant();
+        Date createdDate = new Date();
+        
         SavingsAccountTransaction transaction = SavingsAccountTransaction.holdAmount(account,
account.office(), paymentDetails,
                 transactionDate, Money.of(account.getCurrency(), amount), createdDate, createdUser);
         return transaction;
@@ -217,15 +222,24 @@ public class SavingsAccountTransactionDataValidator {
         final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
                 .resource(SAVINGS_ACCOUNT_RESOURCE_NAME);
 
-        if (holdTransaction == null) {
-            baseDataValidator.failWithCode("validation.msg.validation.errors.exist", "Transaction
not found");
-        } else if (holdTransaction.getReleaseIdOfHoldAmountTransaction() != null) {
-            baseDataValidator.parameter(SavingsApiConstants.amountParamName).value(holdTransaction.getAmount()).failWithCode("validation.msg.amount.is.not.on.hold",
-                    "Transaction amount is not on hold");
-        }
+		if (holdTransaction == null) {
+			baseDataValidator.failWithCode("validation.msg.validation.errors.exist", "Transaction
not found");
+		} else if (holdTransaction.getReleaseIdOfHoldAmountTransaction() != null) {
+			baseDataValidator.parameter(SavingsApiConstants.amountParamName).value(holdTransaction.getAmount())
+					.failWithCode("validation.msg.amount.is.not.on.hold", "Transaction amount is not on
hold");
+		}
+
+		if (holdTransaction != null) {
+			boolean isActive = holdTransaction.getSavingsAccount().isActive();
+			if (!isActive) {
+				baseDataValidator.reset().parameter(SavingsApiConstants.statusParamName)
+						.failWithCodeNoParameterAddedToErrorCode(
+								SavingsApiConstants.ERROR_MSG_SAVINGS_ACCOUNT_NOT_ACTIVE);
+			}
+		}
 
         throwExceptionIfValidationWarningsExist(dataValidationErrors);
-        Date createdDate = DateUtils.getDateOfTenant();
+        Date createdDate = new Date();
         LocalDate transactionDate = DateUtils.getLocalDateOfTenant();
         SavingsAccountTransaction transaction = SavingsAccountTransaction.releaseAmount(holdTransaction,
transactionDate, createdDate,
                 createdUser);

http://git-wip-us.apache.org/repos/asf/fineract/blob/7368c3f1/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java
index f904b09..0acd096 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java
@@ -325,6 +325,8 @@ public class SavingsAccount extends AbstractPersistableCustom<Long>
{
     @JoinColumn(name = "tax_group_id")
     private TaxGroup taxGroup;
 
+    @Column(name = "total_savings_amount_on_hold", scale = 6, precision = 19, nullable =
true)
+    private BigDecimal savingsOnHoldAmount;
     protected SavingsAccount() {
         //
     }
@@ -1051,19 +1053,16 @@ public class SavingsAccount extends AbstractPersistableCustom<Long>
{
         Money runningBalance = Money.zero(this.currency);
         Money minRequiredBalance = minRequiredBalanceDerived(getCurrency());
         LocalDate lastSavingsDate = null;
+        final BigDecimal withdrawalFee = null;
         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 if(transaction.isAmountOnHold() && transaction.getReleaseIdOfHoldAmountTransaction()
== null){
-                runningBalance = runningBalance.minus(transaction.getAmount(this.currency));
             }else {
                 continue;
             }
 
-            final BigDecimal withdrawalFee = null;
-
             /*
              * Loop through the onHold funds and see if we need to deduct or add
              * to minimum required balance and the point in time the transaction
@@ -1093,6 +1092,12 @@ public class SavingsAccount extends AbstractPersistableCustom<Long>
{
             lastSavingsDate = transaction.transactionLocalDate();
 
         }
+		if (this.getSavingsHoldAmount().compareTo(BigDecimal.ZERO) == 1) {
+			if (runningBalance.minus(this.getSavingsHoldAmount()).isLessThanZero()) {
+				throw new InsufficientAccountBalanceException("transactionAmount", getAccountBalance(),
withdrawalFee,
+						transactionAmount);
+			}
+		}
     }
 
     public void validateAccountBalanceDoesNotBecomeNegative(final String transactionAction,
@@ -2753,7 +2758,7 @@ public class SavingsAccount extends AbstractPersistableCustom<Long>
{
     }
 
     public BigDecimal getWithdrawableBalance() {
-        return getAccountBalance().subtract(minRequiredBalanceDerived(getCurrency()).getAmount()).subtract(this.getOnHoldFunds());
+        return getAccountBalance().subtract(minRequiredBalanceDerived(getCurrency()).getAmount()).subtract(this.getOnHoldFunds()).subtract(this.getSavingsHoldAmount());
     }
 
     public TaxGroup getTaxGroup() {
@@ -3006,9 +3011,27 @@ public class SavingsAccount extends AbstractPersistableCustom<Long>
{
 
     public LocalDate retrieveLastTransactionDate() {
         final List<SavingsAccountTransaction> transactionsSortedByDate = retreiveListOfTransactions();
-        SavingsAccountTransaction lastTransaction = transactionsSortedByDate.get(transactionsSortedByDate.size()
- 1);
-        return lastTransaction.transactionLocalDate();
+        SavingsAccountTransaction lastTransaction = null;
+        if (transactionsSortedByDate.size() > 0) {
+            lastTransaction = transactionsSortedByDate.get(transactionsSortedByDate.size()
- 1);
+        }
+        LocalDate lastransactionDate = null;
+        if (lastTransaction != null) {
+            lastransactionDate = lastTransaction.transactionLocalDate();
+        }
+        return lastransactionDate;
     }
-    
-    
+
+    public BigDecimal getSavingsHoldAmount() {
+        return this.savingsOnHoldAmount == null ? BigDecimal.ZERO : this.savingsOnHoldAmount;
+    }
+
+    public void holdAmount(BigDecimal amount) {
+        this.savingsOnHoldAmount = getSavingsHoldAmount().add(amount);
+    }
+
+    public void releaseAmount(BigDecimal amount) {
+        this.savingsOnHoldAmount = getSavingsHoldAmount().subtract(amount);
+    }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/fineract/blob/7368c3f1/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java
index 12de527..cf5ae03 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountTransaction.java
@@ -787,4 +787,8 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom<L
     public Long getReleaseIdOfHoldAmountTransaction() {
         return this.releaseIdOfHoldAmountTransaction;
     }
+    
+	public boolean isAmountOnHoldNotReleased() {
+		return (isAmountOnHold() && getReleaseIdOfHoldAmountTransaction() == null);
+	}	    
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/fineract/blob/7368c3f1/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java
index 1b68e3f..a9704eb 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java
@@ -304,6 +304,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
             sqlBuilder.append("sa.withhold_tax as withHoldTax, ");
             sqlBuilder.append("sa.total_withhold_tax_derived as totalWithholdTax, ");
             sqlBuilder.append("sa.last_interest_calculation_date as lastInterestCalculationDate,
");
+            sqlBuilder.append("sa.total_savings_amount_on_hold as onHoldAmount, ");
             sqlBuilder.append("tg.id as taxGroupId, tg.name as taxGroupName, ");
             sqlBuilder.append("(select IFNULL(max(sat.transaction_date),sa.activatedon_date)
");
             sqlBuilder.append("from m_savings_account_transaction as sat ");
@@ -511,12 +512,19 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
                     "minBalanceForInterestCalculation");
             final BigDecimal onHoldFunds = rs.getBigDecimal("onHoldFunds");
             
+            final BigDecimal onHoldAmount = rs.getBigDecimal("onHoldAmount");
+            
             BigDecimal availableBalance = accountBalance;
             if (availableBalance != null && onHoldFunds != null) {
 
                 availableBalance = availableBalance.subtract(onHoldFunds);
             }
             
+            if (availableBalance != null && onHoldAmount != null) {
+
+                availableBalance = availableBalance.subtract(onHoldAmount);
+            }
+            
             BigDecimal interestNotPosted = BigDecimal.ZERO;
             LocalDate lastInterestCalculationDate = null;
             if(totalInterestEarned != null){
@@ -542,7 +550,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
                     interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
lockinPeriodFrequencyType, withdrawalFeeForTransfers,
                     summary, allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance,
                     minBalanceForInterestCalculation, onHoldFunds, nominalAnnualInterestRateOverdraft,
minOverdraftForInterestCalculation, withHoldTax, 
-                    taxGroupData, lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive,
daysToDormancy, daysToEscheat);
+                    taxGroupData, lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive,
daysToDormancy, daysToEscheat, onHoldAmount);
         }
     }
 
@@ -1074,7 +1082,8 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
             // final LocalDate annualFeeNextDueDate = null;
             final SavingsAccountSummaryData summary = null;
             final BigDecimal onHoldFunds = null;
-            
+            final BigDecimal savingsAmountOnHold  = null;
+
             final SavingsAccountSubStatusEnumData subStatus = null;
             final LocalDate lastActiveTransactionDate = null;
             final boolean isDormancyTrackingActive = false;
@@ -1090,7 +1099,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
                     interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
lockinPeriodFrequencyType, withdrawalFeeForTransfers,
                     summary, allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance,
                     minBalanceForInterestCalculation, onHoldFunds, nominalAnnualInterestRateOverdraft,
minOverdraftForInterestCalculation, withHoldTax, 
-                    taxGroupData, lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive,
daysToDormancy, daysToEscheat);
+                    taxGroupData, lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive,
daysToDormancy, daysToEscheat, savingsAmountOnHold);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/fineract/blob/7368c3f1/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
index f9e52b2..03409ed 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
@@ -612,8 +612,9 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements
Savi
     public CommandProcessingResult close(final Long savingsId, final JsonCommand command)
{
         final AppUser user = this.context.authenticatedUser();
         
-        this.savingsAccountTransactionDataValidator.validateClosing(command);
         final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
+        this.savingsAccountTransactionDataValidator.validateClosing(command, account);
+        
         final boolean isLinkedWithAnyActiveLoan = this.accountAssociationsReadPlatformService.isLinkedWithAnyActiveAccount(savingsId);
 
         if (isLinkedWithAnyActiveLoan) {
@@ -1403,7 +1404,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements
Savi
                 .validateReleaseAmountAndAssembleForm(holdTransaction, submittedBy);
         final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
         checkClientOrGroupActive(account);
-        account.releaseFunds(transaction.getAmount());
+        account.releaseAmount(transaction.getAmount());
 
         this.savingsAccountTransactionRepository.save(transaction);
         holdTransaction.updateReleaseId(transaction.getId());

http://git-wip-us.apache.org/repos/asf/fineract/blob/7368c3f1/fineract-provider/src/main/resources/sql/migrations/core_db/V330__savings_account_transaction_releaseId.sql
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V330__savings_account_transaction_releaseId.sql
b/fineract-provider/src/main/resources/sql/migrations/core_db/V330__savings_account_transaction_releaseId.sql
index cf9e24c..c20ea9f 100644
--- a/fineract-provider/src/main/resources/sql/migrations/core_db/V330__savings_account_transaction_releaseId.sql
+++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V330__savings_account_transaction_releaseId.sql
@@ -40,5 +40,9 @@ INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`,
`c
 
 ALTER TABLE `m_savings_account_transaction` ADD COLUMN `release_id_of_hold_amount` BIGINT(20)
NULL DEFAULT NULL;
 
+--  modify `m_savings_account` 
+
+ALTER TABLE `m_savings_account` ADD COLUMN `total_savings_amount_on_hold` DECIMAL(19,6) NULL
DEFAULT NULL;
+
 
 


Mime
View raw message