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 <shru...@confluxtechnologies.com>
Authored: Wed Jul 12 17:59:18 2017 +0530
Committer: ShruthiRajaram <shru...@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;
+
 
 

Reply via email to