block account/amount/credit/debit

This commit is contained in:
ShruthiRajaram
2017-06-21 13:21:36 +05:30
parent 18e85856fc
commit fe3741c2ce
34 changed files with 1824 additions and 26 deletions
+425 -1
View File
@@ -629,6 +629,54 @@
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>savingsaccounts/{accountId}?command=block</td>
<td><a href="#savingsaccounts_block">Block savings account</a></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>savingsaccounts/{accountId}?command=unblock</td>
<td><a href="#savingsaccounts_unblock">Unblock savings account</a></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>savingsaccounts/{accountId}?command=blockCredit</td>
<td><a href="#savingsaccounts_block_credit">Block Savings Account Credit Transactions</a></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>savingsaccounts/{accountId}?command=unblockCredit</td>
<td><a href="#savingsaccounts_unblock_credit">Unblock Savings Account Credit Transactions</a></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>savingsaccounts/{accountId}?command=blockDebit</td>
<td><a href="#savingsaccounts_block_debit">Block Savings Account Debit Transactions</a></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>savingsaccounts/{accountId}?command=unblockDebit</td>
<td><a href="#savingsaccounts_unblock_debit">Unblock Savings Account Debit Transactions</a></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td><a href="#savingsaccounts_transactions">Savings Transactions</a></td>
<td>savingsaccounts/{accountId}/transactions?command=deposit</td>
@@ -661,6 +709,22 @@
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>savingsaccounts/{accountId}/transactions/{transactionId}?command=holdAmount</td>
<td><a href="#savingsaccounts_hold_amount">Hold Amount</a></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>savingsaccounts/{accountId}/transactions/{transactionId}?command=releaseAmount</td>
<td><a href="#savingsaccounts_release_amount">Release Amount</a></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>savingsaccounts/{accountId}/transactions/template</td>
@@ -26243,7 +26307,248 @@ Request Body:
</code>
</div>
</div>
<a id="savingsaccounts_block" name="savingsaccounts_block" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h2>Block Savings Account</h2>
<p>
Blocks Savings account from all types of credit and debit transactions
</p>
</div>
<div class="method-example">
<code class="method-declaration">POST https://Domain Name/api/v1/savingsaccounts/{savingsId}?command=block</code>
<code class="method-request">POST savingsaccount/1?command=block
Content-Type: application/json
Request Body:
{
}
</code>
<code class="method-response">
{
"officeId":1,
"clientId":1,
"savingsId":1,
"resourceId":1,
"changes":{
"subStatus":{
"id":400,
"code":"SavingsAccountSubStatusEnum.block",
"value":"Block",
"none":false,
"inactive":false,
"dormant":false,
"escheat":false,
"block":true,
"blockCredit":false,
"blockDebit":false
}
}
}
</code>
</div>
</div>
<a id="savingsaccounts_unblock" name="savingsaccounts_unblock" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h2>Unblock Savings Account</h2>
<p>
Unblock a blocked account. On unblocking account, user can perform debit and credit transactions
</p>
</div>
<div class="method-example">
<code class="method-declaration">POST https://Domain Name/api/v1/savingsaccounts/{savingsId}?command=unblock</code>
<code class="method-request">POST savingsaccount/1?command=unblock
Content-Type: application/json
Request Body:
{
}
</code>
<code class="method-response">
{
"officeId":1,
"clientId":1,
"savingsId":1,
"resourceId":1,
"changes":{
"subStatus":{
"id":0,
"code":"SavingsAccountSubStatusEnum.none",
"value":"None",
"none":true,
"inactive":false,
"dormant":false,
"escheat":false,
"block":false,
"blockCredit":false,
"blockDebit":false
}
}
}
</code>
</div>
</div>
<a id="savingsaccounts_block_credit" name="savingsaccounts_block_credit" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h2>Block Savings Account Credit transactions</h2>
<p>
Savings account will be blocked from all types of credit transactions.
</p>
</div>
<div class="method-example">
<code class="method-declaration">POST https://Domain Name/api/v1/savingsaccounts/{savingsId}?command=blockCredit</code>
<code class="method-request">POST savingsaccount/1?command=blockCredit
Content-Type: application/json
Request Body:
{
}
</code>
<code class="method-response">
{
"officeId":1,
"clientId":1,
"savingsId":1,
"resourceId":1,
"changes":{
"subStatus":{
"id":500,
"code":"SavingsAccountSubStatusEnum.blockcredit",
"value":"BlockCredit",
"none":false,
"inactive":false,
"dormant":false,
"escheat":false,
"block":false,
"blockCredit":true,
"blockDebit":false
}
}
}
</code>
</div>
</div>
<a id="savingsaccounts_unblock_credit" name="savingsaccounts_unblock_credit" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h2>Unblock Savings Account Credit transactions</h2>
<p>It unblocks the Saving account's credit operations. Now all types of credits can be transacted to Savings account
</p>
</div>
<div class="method-example">
<code class="method-declaration">POST https://Domain Name/api/v1/savingsaccounts/{savingsId}?command=unblockCredit</code>
<code class="method-request">POST savingsaccount/1?command=unblockCredit
Content-Type: application/json
Request Body:
{
}
</code>
<code class="method-response">
{
"officeId":1,
"clientId":1,
"savingsId":1,
"resourceId":1,
"changes":{
"subStatus":{
"id":0,
"code":"SavingsAccountSubStatusEnum.none",
"value":"None",
"none":true,
"inactive":false,
"dormant":false,
"escheat":false,
"block":false,
"blockCredit":false,
"blockDebit":false
}
}
}
</code>
</div>
</div>
<a id="savingsaccounts_block_debit" name="savingsaccounts_block_debit" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h2>Block Savings Account Debit transactions</h2>
<p> All types of debit operations from Savings account wil be blocked</p>
</div>
<div class="method-example">
<code class="method-declaration">POST https://Domain Name/api/v1/savingsaccounts/{savingsId}?command=blockDebit</code>
<code class="method-request">POST savingsaccount/1?command=blockDebit
Content-Type: application/json
Request Body:
{
}
</code>
<code class="method-response">
{
"officeId":1,
"clientId":1,
"savingsId":1,
"resourceId":1,
"changes":{
"subStatus":{
"id":600,
"code":"SavingsAccountSubStatusEnum.blockdebit",
"value":"BlockDebit",
"none":false,
"inactive":false,
"dormant":false,
"escheat":false,
"block":false,
"blockCredit":false,
"blockDebit":true
}
}
}
</code>
</div>
</div>
<a id="savingsaccounts_unblock_debit" name="savingsaccounts_unblock_debit" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h2>Unblock Savings Account debit transactions</h2>
<p>It unblocks the Saving account's debit operations. Now all types of debits can be transacted from Savings account
</p>
</div>
<div class="method-example">
<code class="method-declaration">POST https://Domain Name/api/v1/savingsaccounts/{savingsId}?command=unblockDebit</code>
<code class="method-request">POST savingsaccount/1?command=unblockDebit
Content-Type: application/json
Request Body:
{
}
</code>
<code class="method-response">
{
"officeId":1,
"clientId":1,
"savingsId":1,
"resourceId":1,
"changes":{
"subStatus":{
"id":0,
"code":"SavingsAccountSubStatusEnum.none",
"value":"None",
"none":true,
"inactive":false,
"dormant":false,
"escheat":false,
"block":false,
"blockCredit":false,
"blockDebit":false
}
}
}
</code>
</div>
</div>
<a id="savingsaccounts_list" name="savingsaccounts_list" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
@@ -26417,7 +26722,8 @@ Request Body:
"nameCode": "currency.USD",
"displayLabel": "US Dollar ($)"
},
"accountBalance": 0
"accountBalance": 0,
"availableBalance": 0
}
}
</code>
@@ -26787,6 +27093,60 @@ No Request Body:
</code>
</div>
</div>
<a id="savingsaccounts_hold_amount" name="savingsaccounts_hold_amount" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h2>Hold Amount</h2>
<p>Hold amount enables the user to hold/block/lien the specified amount from the account</p>
</div>
<div class="method-example">
<code class="method-declaration">POST https://Domain Name/api/v1/savingsaccounts/4/transactions?command=holdAmount</code>
<code class="method-request">POST savingsaccounts/4/transactions?command=holdAmount
Content-Type: application/json
Request Body:
{
transactionDate:"15 June 2017",
transactionAmount:"200",
locale:"en",
dateFormat:"dd MMMM yyyy"
}
</code>
<code class="method-response">
{
"officeId":1,
"clientId":2,
"savingsId":4,
"resourceId":35
}
</code>
</div>
</div>
<a id="savingsaccounts_release_amount" name="savingsaccounts_release_amount" class="old-syle-anchor">&nbsp;</a>
<div class="method-section">
<div class="method-description">
<h2>Release Amount</h2>
<p>Release amount removes the hold/block/lien already placed on an amount in the account. </p>
</div>
<div class="method-example">
<code class="method-declaration">POST https://Domain Name/api/v1/savingsaccounts/4/transactions/35?command=releaseAmount</code>
<code class="method-request">POST savingsaccounts/4/transactions/35?command=releaseAmount
Content-Type: application/json
No Request Body:
{
}
</code>
<code class="method-response">
{
"officeId":1,
"clientId":2,
"savingsId":4,
"resourceId":36
}
</code>
</div>
</div>
<!-- end of savings accounts api -->
<!-- start of Savings charges content-->
@@ -48361,6 +48721,54 @@ No Request Body:
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>savingsaccounts/{accountId}?command=block</td>
<td><a href="#savingsaccounts_block">Block savings account</a></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>savingsaccounts/{accountId}?command=unblock</td>
<td><a href="#savingsaccounts_unblock">UnBlock savings account</a></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>savingsaccounts/{accountId}?command=blockCredit</td>
<td><a href="#savingsaccounts_block_credit">Block Savings Account Credit transactions</a></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>savingsaccounts/{accountId}?command=unblockCredit</td>
<td><a href="#savingsaccounts_unblock_credit">Unblock Savings Account Credit transactions</a></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>savingsaccounts/{accountId}?command=blockDebit</td>
<td><a href="#savingsaccounts_block_debit">Block Savings Account Debit transactions</a></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>savingsaccounts/{accountId}?command=unblockDebit</td>
<td><a href="#savingsaccounts_unblock_debit">Unblock Savings Account Debit transactions</a></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td><a href="#savingsaccounts_transactions">Savings Transactions</a></td>
<td>savingsaccounts/{accountId}/transactions?command=deposit</td>
@@ -48393,6 +48801,22 @@ No Request Body:
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>savingsaccounts/{accountId}/transactions/{transactionId}?command=holdAmount</td>
<td><a href="#savingsaccounts_hold_amount">Hold Amount</a></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>savingsaccounts/{accountId}/transactions/{transactionId}?command=releaseAmount</td>
<td><a href="#savingsaccounts_release_amount">Release Amount</a></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td>savingsaccounts/{accountId}/transactions/template</td>
@@ -2115,4 +2115,115 @@ public class ClientSavingsIntegrationTest {
* assertEquals("Verifying Interest Calculation", new Float("238.3399"),
* savingsInterest); }
*/
@SuppressWarnings("unchecked")
@Test
public void testSavingsAccountBlockStatus() {
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
SavingsAccountHelper savingsAccountHelperValidationError = new SavingsAccountHelper(this.requestSpec,
new ResponseSpecBuilder().build());
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 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);
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);
savingsStatusHashMap = this.savingsAccountHelper.blockSavings(savingsId);
SavingsStatusChecker.verifySavingsSubStatusblock(savingsStatusHashMap);
List<HashMap> error = (List) savingsAccountHelperValidationError.withdrawalFromSavingsAccount(savingsId, "100",
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_ERROR);
assertEquals("error.msg.saving.account.blocked.transaction.not.allowed",
error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
error = (List) savingsAccountHelperValidationError.depositToSavingsAccount(savingsId, "100", SavingsAccountHelper.TRANSACTION_DATE,
CommonConstants.RESPONSE_ERROR);
assertEquals("error.msg.saving.account.blocked.transaction.not.allowed",
error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
savingsStatusHashMap = this.savingsAccountHelper.unblockSavings(savingsId);
SavingsStatusChecker.verifySavingsSubStatusIsNone(savingsStatusHashMap);
Integer depositTransactionId = (Integer) this.savingsAccountHelper.depositToSavingsAccount(savingsId, DEPOSIT_AMOUNT,
SavingsAccountHelper.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"));
savingsStatusHashMap = this.savingsAccountHelper.blockDebit(savingsId);
SavingsStatusChecker.verifySavingsSubStatusIsDebitBlocked(savingsStatusHashMap);
error = (List) savingsAccountHelperValidationError.withdrawalFromSavingsAccount(savingsId, "100",
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_ERROR);
assertEquals("error.msg.savings.account.debit.transaction.not.allowed",
error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
depositTransactionId = (Integer) this.savingsAccountHelper.depositToSavingsAccount(savingsId, DEPOSIT_AMOUNT,
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
depositTransaction = this.savingsAccountHelper.getSavingsTransaction(savingsId, depositTransactionId);
balance += new Float(DEPOSIT_AMOUNT);
assertEquals("Verifying Deposit Amount", new Float(DEPOSIT_AMOUNT), depositTransaction.get("amount"));
savingsStatusHashMap = this.savingsAccountHelper.unblockDebit(savingsId);
SavingsStatusChecker.verifySavingsSubStatusIsNone(savingsStatusHashMap);
Integer withdrawTransactionId = (Integer) this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, WITHDRAW_AMOUNT,
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
HashMap withdrawTransaction = this.savingsAccountHelper.getSavingsTransaction(savingsId, withdrawTransactionId);
balance -= new Float(WITHDRAW_AMOUNT);
assertEquals("Verifying Withdrawal Amount", new Float(WITHDRAW_AMOUNT), withdrawTransaction.get("amount"));
savingsStatusHashMap = this.savingsAccountHelper.blockCredit(savingsId);
SavingsStatusChecker.verifySavingsSubStatusIsCreditBlocked(savingsStatusHashMap);
error = (List) savingsAccountHelperValidationError.depositToSavingsAccount(savingsId, "100", SavingsAccountHelper.TRANSACTION_DATE,
CommonConstants.RESPONSE_ERROR);
assertEquals("error.msg.savings.account.credit.transaction.not.allowed",
error.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
withdrawTransactionId = (Integer) this.savingsAccountHelper.withdrawalFromSavingsAccount(savingsId, WITHDRAW_AMOUNT,
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
withdrawTransaction = this.savingsAccountHelper.getSavingsTransaction(savingsId, withdrawTransactionId);
balance -= new Float(WITHDRAW_AMOUNT);
assertEquals("Verifying Withdrawal Amount", new Float(WITHDRAW_AMOUNT), withdrawTransaction.get("amount"));
savingsStatusHashMap = this.savingsAccountHelper.unblockCredit(savingsId);
SavingsStatusChecker.verifySavingsSubStatusIsNone(savingsStatusHashMap);
depositTransactionId = (Integer) this.savingsAccountHelper.depositToSavingsAccount(savingsId, DEPOSIT_AMOUNT,
SavingsAccountHelper.TRANSACTION_DATE, CommonConstants.RESPONSE_RESOURCE_ID);
depositTransaction = this.savingsAccountHelper.getSavingsTransaction(savingsId, depositTransactionId);
balance += new Float(DEPOSIT_AMOUNT);
assertEquals("Verifying Deposit Amount", new Float(DEPOSIT_AMOUNT), depositTransaction.get("amount"));
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);
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);
withdrawTransaction = this.savingsAccountHelper.getSavingsTransaction(savingsId, withdrawTransactionId);
balance -= new Float("300");
assertEquals("Verifying Withdrawal Amount", new Float("300"), withdrawTransaction.get("amount"));
}
}
@@ -55,6 +55,15 @@ public class SavingsAccountHelper {
private static final String WITHDRAW_SAVINGS_COMMAND = "withdrawal";
private static final String MODIFY_TRASACTION_COMMAND = "modify";
private static final String UNDO_TRASACTION_COMMAND = "undo";
private static final String BLOCK_SAVINGS_COMMAND = "block";
private static final String UNBLOCK_SAVINGS_COMMAND = "unblock";
private static final String BLOCK_DEBITS_SAVINGS_COMMAND = "blockDebit";
private static final String UNBLOCK_DEBITS_SAVINGS_COMMAND = "unblockDebit";
private static final String BLOCK_CREDITS_SAVINGS_COMMAND = "blockCredit";
private static final String UNBLOCK_CREDITS_SAVINGS_COMMAND = "unblockCredit";
private static final String HOLD_AMOUNT_SAVINGS_COMMAND = "holdAmount";
private static final String RELEASE_AMOUNT_SAVINGS_COMMAND = "releaseAmount";
public static final String CREATED_DATE = "08 January 2013";
public static final String CREATED_DATE_PLUS_ONE = "09 January 2013";
@@ -64,6 +73,7 @@ public class SavingsAccountHelper {
public static final String ACCOUNT_TYPE_INDIVIDUAL = "INDIVIDUAL";
public static final String DATE_TIME_FORMAT = "dd MMMM yyyy HH:mm";
private static final Boolean isBlock = false;
public SavingsAccountHelper(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) {
this.requestSpec = requestSpec;
@@ -138,20 +148,20 @@ public class SavingsAccountHelper {
System.out.println("--------------------------------- APPROVING SAVINGS APPLICATION ------------------------------------");
final String savingsOperationURL = createSavingsOperationURL(APPROVE_SAVINGS_COMMAND, savingsID);
if (approvalDate == null || approvalDate == "")
return performSavingApplicationActions(savingsOperationURL, getApproveSavingsAsJSON());
return performSavingApplicationActions(savingsOperationURL, getApproveSavingsAsJsonOnDate(approvalDate));
return performSavingApplicationActions(savingsOperationURL, getApproveSavingsAsJSON(), isBlock);
return performSavingApplicationActions(savingsOperationURL, getApproveSavingsAsJsonOnDate(approvalDate), isBlock);
}
public HashMap undoApproval(final Integer savingsID) {
System.out.println("--------------------------------- UNDO APPROVING SAVINGS APPLICATION -------------------------------");
final String undoBodyJson = "{'note':'UNDO APPROVAL'}";
return performSavingApplicationActions(createSavingsOperationURL(UNDO_APPROVAL_SAVINGS_COMMAND, savingsID), undoBodyJson);
return performSavingApplicationActions(createSavingsOperationURL(UNDO_APPROVAL_SAVINGS_COMMAND, savingsID), undoBodyJson, isBlock);
}
public HashMap rejectApplication(final Integer savingsID) {
System.out.println("--------------------------------- REJECT SAVINGS APPLICATION -------------------------------");
return performSavingApplicationActions(createSavingsOperationURL(REJECT_SAVINGS_COMMAND, savingsID),
getRejectedSavingsAsJSON(CREATED_DATE_PLUS_ONE));
getRejectedSavingsAsJSON(CREATED_DATE_PLUS_ONE), isBlock);
}
public List rejectApplicationWithErrorCode(final Integer savingsId, final String date) {
@@ -163,18 +173,18 @@ public class SavingsAccountHelper {
public HashMap withdrawApplication(final Integer savingsID) {
System.out.println("--------------------------------- Withdraw SAVINGS APPLICATION -------------------------------");
return performSavingApplicationActions(createSavingsOperationURL(WITHDRAWN_BY_CLIENT_SAVINGS_COMMAND, savingsID),
getWithdrawnSavingsAsJSON());
getWithdrawnSavingsAsJSON(), isBlock);
}
public HashMap activateSavings(final Integer savingsID) {
System.out.println("---------------------------------- ACTIVATING SAVINGS APPLICATION ----------------------------------");
return performSavingApplicationActions(createSavingsOperationURL(ACTIVATE_SAVINGS_COMMAND, savingsID), getActivatedSavingsAsJSON());
return performSavingApplicationActions(createSavingsOperationURL(ACTIVATE_SAVINGS_COMMAND, savingsID), getActivatedSavingsAsJSON(), isBlock);
}
public HashMap closeSavingsAccount(final Integer savingsID, String withdrawBalance) {
System.out.println("---------------------------------- CLOSE SAVINGS APPLICATION ----------------------------------");
return performSavingApplicationActions(createSavingsOperationURL(CLOSE_SAVINGS_COMMAND, savingsID),
getCloseAccountJSON(withdrawBalance, LAST_TRANSACTION_DATE));
getCloseAccountJSON(withdrawBalance, LAST_TRANSACTION_DATE), isBlock);
}
public Object deleteSavingsApplication(final Integer savingsId, final String jsonAttributeToGetBack) {
@@ -251,6 +261,60 @@ public class SavingsAccountHelper {
return Utils.performServerDelete(this.requestSpec, this.responseSpec, SAVINGS_ACCOUNT_URL + "/" + savingsId + "/charges/"
+ chargeId + "?" + Utils.TENANT_IDENTIFIER, CommonConstants.RESPONSE_RESOURCE_ID);
}
public HashMap blockSavings(final Integer savingsID) {
System.out.println("---------------------------------- BLOCKING SAVINGS ACCOUNT ----------------------------------");
Boolean isBlock = true;
return performSavingApplicationActions(createSavingsOperationURL(BLOCK_SAVINGS_COMMAND, savingsID),
getActivatedSavingsAsJSON(), isBlock);
}
public HashMap unblockSavings(final Integer savingsID) {
System.out.println("---------------------------------- UNBLOCKING SAVINGS ACCOUNT ----------------------------------");
Boolean isBlock = true;
return performSavingApplicationActions(createSavingsOperationURL(UNBLOCK_SAVINGS_COMMAND, savingsID),
getActivatedSavingsAsJSON(), isBlock);
}
public HashMap blockDebit(final Integer savingsID) {
System.out.println("---------------------------------- BLOCKING DEBIT TRANSACTIONS ----------------------------------");
Boolean isBlock = true;
return performSavingApplicationActions(createSavingsOperationURL(BLOCK_DEBITS_SAVINGS_COMMAND, savingsID),
getActivatedSavingsAsJSON(), isBlock);
}
public HashMap unblockDebit(final Integer savingsID) {
System.out.println("---------------------------------- UNBLOCKING DEBIT TRANSACTIONS ----------------------------------");
Boolean isBlock = true;
return performSavingApplicationActions(createSavingsOperationURL(UNBLOCK_DEBITS_SAVINGS_COMMAND, savingsID),
getActivatedSavingsAsJSON(), isBlock);
}
public HashMap blockCredit(final Integer savingsID) {
System.out.println("---------------------------------- BLOCKING CREDIT TRANSACTIONS ----------------------------------");
Boolean isBlock = true;
return performSavingApplicationActions(createSavingsOperationURL(BLOCK_CREDITS_SAVINGS_COMMAND, savingsID),
getActivatedSavingsAsJSON(), isBlock);
}
public HashMap unblockCredit(final Integer savingsID) {
System.out.println("---------------------------------- UNBLOCKING CREDIT TRANSACTIONS ----------------------------------");
Boolean isBlock = true;
return performSavingApplicationActions(createSavingsOperationURL(UNBLOCK_CREDITS_SAVINGS_COMMAND, savingsID),
getActivatedSavingsAsJSON(), isBlock);
}
public Object holdAmountInSavingsAccount(final Integer savingsID, final String amount, String date, String jsonAttributeToGetback) {
System.out.println("--------------------------------- SAVINGS TRANSACTION HOLD AMOUNT--------------------------------");
return performSavingActions(createSavingsTransactionURL(HOLD_AMOUNT_SAVINGS_COMMAND, savingsID),
getSavingsTransactionJSON(amount, date), jsonAttributeToGetback);
}
public Integer releaseAmount(final Integer savingsId, final Integer transactionId) {
System.out.println("\n--------------------------------- SAVINGS TRANSACTION RELEASE AMOUNT--------------------------------");
return (Integer) performSavingActions(createAdjustTransactionURL(RELEASE_AMOUNT_SAVINGS_COMMAND, savingsId, transactionId),
getSavingsTransactionJSON("1000", LAST_TRANSACTION_DATE), CommonConstants.RESPONSE_RESOURCE_ID);
}
private String getApproveSavingsAsJSON() {
return getApproveSavingsAsJsonOnDate(CREATED_DATE_PLUS_ONE);
@@ -454,12 +518,15 @@ public class SavingsAccountHelper {
return response;
}
private HashMap performSavingApplicationActions(final String postURLForSavingsTransaction, final String jsonToBeSent) {
private HashMap performSavingApplicationActions(final String postURLForSavingsTransaction, final String jsonToBeSent, final Boolean isBlock) {
HashMap status = null;
final HashMap response = Utils.performServerPost(this.requestSpec, this.responseSpec, postURLForSavingsTransaction, jsonToBeSent,
CommonConstants.RESPONSE_CHANGES);
if (response != null) {
status = (HashMap) response.get("status");
if (isBlock != null && isBlock) {
status = (HashMap) response.get("subStatus");
}
}
return status;
}
@@ -510,7 +577,7 @@ public class SavingsAccountHelper {
public HashMap activateSavingsAccount(Integer savingsID, String activationDate) {
return performSavingApplicationActions(createSavingsOperationURL(ACTIVATE_SAVINGS_COMMAND, savingsID),
getAccountActivationJSON(activationDate));
getAccountActivationJSON(activationDate), isBlock);
}
public Object inactivateCharge(final Integer chargeId, final Integer savingsId, final String jsonAttributeToGetBack) {
@@ -113,5 +113,30 @@ public class SavingsStatusChecker {
assertTrue("UNEXPECTED SAVINGS ACCOUNT SUB STATUS", getStatus(savingsStatusHashMap, "none"));
System.out.println("Savings Application Sub Status:" + savingsStatusHashMap + "\n");
}
public static void verifySavingsSubStatusblock(HashMap savingsStatusHashMap) {
System.out.println(
"\n-------------------------------------- VERIFYING SAVINGS ACCOUNT IS BLOCKED ------------------------------------");
assertTrue("block", getStatus(savingsStatusHashMap, "block"));
System.out.println("Savings Application Sub Status:" + savingsStatusHashMap + "\n");
}
public static void verifySavingsSubStatusIsNone(HashMap savingsStatusHashMap) {
System.out.println("\n------------------------- VERIFYING SAVINGS ACCOUNT IS NOT BLOCKED FOR ANY TYPE OF TRANSACTIONS ---------------------------");
assertTrue("none", getStatus(savingsStatusHashMap, "none"));
System.out.println("Savings Application Sub Status:" + savingsStatusHashMap + "\n");
}
public static void verifySavingsSubStatusIsDebitBlocked(HashMap savingsStatusHashMap) {
System.out.println("\n--------------------- VERIFYING SAVINGS APPLICATION IS BLOCKED FOR DEBIT TRANSACTIONS ---------------------");
assertTrue("status is blockDebit", getStatus(savingsStatusHashMap, "blockDebit"));
System.out.println("Savings Application Sub Status:" + savingsStatusHashMap + "\n");
}
public static void verifySavingsSubStatusIsCreditBlocked(HashMap savingsStatusHashMap) {
System.out.println("\n---------------------- VERIFYING SAVINGS APPLICATION IS BLOCKED FOR CREDIT TRANSACTIONS ---------------");
assertTrue("blockCredit ", getStatus(savingsStatusHashMap, "blockCredit"));
System.out.println("Savings Application Sub Status:" + savingsStatusHashMap + "\n");
}
}
@@ -2904,4 +2904,77 @@ public class CommandWrapperBuilder {
this.href = "/smscampaigns/"+resourceId;
return this;
}
public CommandWrapperBuilder holdAmount(final Long accountId) {
this.actionName = "HOLDAMOUNT";
this.entityName = "SAVINGSACCOUNT";
this.savingsId = accountId;
this.entityId = null;
this.href = "/savingsaccounts/" + accountId + "/transactions?command=holdAmount";
return this;
}
public CommandWrapperBuilder releaseAmount(final Long accountId, final Long transactionId) {
this.actionName = "RELEASEAMOUNT";
this.entityName = "SAVINGSACCOUNT";
this.entityId = null;
this.savingsId = accountId;
this.transactionId = transactionId.toString();
this.href = "/savingsaccounts/" + accountId + "/transactions/" + transactionId + "?command=releaseAmount";
return this;
}
public CommandWrapperBuilder blockDebitsFromSavingsAccount(final Long accountId) {
this.actionName = "BLOCKDEBIT";
this.entityName = "SAVINGSACCOUNT";
this.savingsId = accountId;
this.entityId = null;
this.href = "/savingsaccounts/" + accountId + "?command=blockDebit";
return this;
}
public CommandWrapperBuilder unblockDebitsFromSavingsAccount(final Long accountId) {
this.actionName = "UNBLOCKDEBIT";
this.entityName = "SAVINGSACCOUNT";
this.savingsId = accountId;
this.entityId = null;
this.href = "/savingsaccounts/" + accountId + "?command=unblockDebit";
return this;
}
public CommandWrapperBuilder blockCreditsToSavingsAccount(final Long accountId) {
this.actionName = "BLOCKCREDIT";
this.entityName = "SAVINGSACCOUNT";
this.savingsId = accountId;
this.entityId = null;
this.href = "/savingsaccounts/" + accountId + "?command=blockCredit";
return this;
}
public CommandWrapperBuilder unblockCreditsToSavingsAccount(final Long accountId) {
this.actionName = "UNBLOCKCREDIT";
this.entityName = "SAVINGSACCOUNT";
this.savingsId = accountId;
this.entityId = null;
this.href = "/savingsaccounts/" + accountId + "?command=unblockCredit";
return this;
}
public CommandWrapperBuilder blockSavingsAccount(final Long accountId) {
this.actionName = "BLOCK";
this.entityName = "SAVINGSACCOUNT";
this.savingsId = accountId;
this.entityId = null;
this.href = "/savingsaccounts/" + accountId + "?command=block";
return this;
}
public CommandWrapperBuilder unblockSavingsAccount(final Long accountId) {
this.actionName = "UNBLOCK";
this.entityName = "SAVINGSACCOUNT";
this.savingsId = accountId;
this.entityId = null;
this.href = "/savingsaccounts/" + accountId + "?command=unblock";
return this;
}
}
@@ -41,7 +41,9 @@ public enum SavingsAccountTransactionType {
REJECT_TRANSFER(15, "savingsAccountTransactionType.rejectTransfer"), WRITTEN_OFF(16, "savingsAccountTransactionType.writtenoff"), //
OVERDRAFT_INTEREST(17, "savingsAccountTransactionType.overdraftInterest"), //
WITHHOLD_TAX(18, "savingsAccountTransactionType.withholdTax"),
ESCHEAT(19, "savingsAccountTransactionType.escheat");
ESCHEAT(19, "savingsAccountTransactionType.escheat"),
AMOUNT_HOLD(20, "savingsAccountTransactionType.onHold"),
AMOUNT_RELEASE(21, "savingsAccountTransactionType.release");
private final Integer value;
private final String code;
@@ -113,6 +115,12 @@ public enum SavingsAccountTransactionType {
case 19:
savingsAccountTransactionType = SavingsAccountTransactionType.ESCHEAT;
break;
case 20:
savingsAccountTransactionType = SavingsAccountTransactionType.AMOUNT_HOLD;
break;
case 21:
savingsAccountTransactionType = SavingsAccountTransactionType.AMOUNT_RELEASE;
break;
}
return savingsAccountTransactionType;
}
@@ -188,12 +196,20 @@ public enum SavingsAccountTransactionType {
public boolean isEscheat() {
return this.value.equals(SavingsAccountTransactionType.ESCHEAT.getValue());
}
public boolean isAmountOnHold() {
return this.value.equals(SavingsAccountTransactionType.AMOUNT_HOLD.getValue());
}
public boolean isAmountRelease() {
return this.value.equals(SavingsAccountTransactionType.AMOUNT_RELEASE.getValue());
}
public boolean isDebit() {
return isWithdrawal() || isWithdrawalFee() || isAnnualFee() || isPayCharge() || isIncomeFromInterest() || isWithHoldTax() || isEscheat();
return isWithdrawal() || isWithdrawalFee() || isAnnualFee() || isPayCharge() || isIncomeFromInterest() || isWithHoldTax() || isEscheat() || isAmountOnHold();
}
public boolean isCredit() {
return isDeposit() || isInterestPosting() || isDividendPayout();
return isDeposit() || isInterestPosting() || isDividendPayout() || isAmountRelease();
}
}
@@ -50,6 +50,12 @@ public class SavingsApiConstants {
public static final String payChargeTransactionAction = ".paycharge";
public static final String waiveChargeTransactionAction = ".waivecharge";
public static final String updateMaturityDetailsAction = ".updateMaturityDetails";
public static final String blockAction = ".block";
public static final String unblockAction = ".unblock";
public static final String blockCreditsAction = ".blockCredits";
public static final String unblockCreditsAction = ".unblockCredits";
public static final String blockDebitsAction = ".blockDebits";
public static final String unblockDebitsAction = ".unblockDebits";
// command
public static final String COMMAND_UNDO_TRANSACTION = "undo";
@@ -57,6 +63,14 @@ public class SavingsApiConstants {
public static final String COMMAND_WAIVE_CHARGE = "waive";
public static final String COMMAND_PAY_CHARGE = "paycharge";
public static final String COMMAND_INACTIVATE_CHARGE = "inactivate";
public static final String COMMAND_HOLD_AMOUNT = "holdAmount";
public static final String COMMAND_RELEASE_AMOUNT = "releaseAmount";
public static final String COMMAND_UNBLOCK_ACCOUNT= "unblock";
public static final String COMMAND_BLOCK_ACCOUNT = "block";
public static final String COMMAND_BLOCK_CREDIT = "blockCredit";
public static final String COMMAND_BLOCK_DEBIT = "blockDebit";
public static final String COMMAND_UNBLOCK_DEBIT = "unblockDebit";
public static final String COMMAND_UNBLOCK_CREDIT = "unblockCredit";
// general
public static final String localeParamName = "locale";
@@ -69,6 +83,7 @@ public class SavingsApiConstants {
public static final String accountNoParamName = "accountNo";
public static final String externalIdParamName = "externalId";
public static final String statusParamName = "status";
public static final String subStatusParamName = "subStatus";
public static final String clientIdParamName = "clientId";
public static final String groupIdParamName = "groupId";
public static final String productIdParamName = "productId";
@@ -169,4 +184,9 @@ public class SavingsApiConstants {
public static final String daysToEscheatParamName = "daysToEscheat";
public static final String datatables = "datatables";
public static final String ERROR_MSG_SAVINGS_ACCOUNT_NOT_ACTIVE = "not.in.active.state";
public static final Set<String> SAVINGS_ACCOUNT_HOLD_AMOUNT_REQUEST_DATA_PARAMETERS = new HashSet<>(
Arrays.asList(transactionDateParamName, dateFormatParamName, localeParamName, transactionAmountParamName));
}
@@ -145,11 +145,14 @@ public class SavingsAccountTransactionsApiResource {
} else if (is(commandParam, "postInterestAsOn")) {
final CommandWrapper commandRequest = builder.savingsAccountInterestPosting(savingsId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
} else if (is(commandParam, SavingsApiConstants.COMMAND_HOLD_AMOUNT)) {
final CommandWrapper commandRequest = builder.holdAmount(savingsId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
}
if (result == null) {
//
throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "deposit", "withdrawal" });
throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "deposit", "withdrawal", SavingsApiConstants.COMMAND_HOLD_AMOUNT });
}
return this.toApiJsonSerializer.serialize(result);
@@ -183,11 +186,15 @@ public class SavingsAccountTransactionsApiResource {
} else if (is(commandParam, SavingsApiConstants.COMMAND_ADJUST_TRANSACTION)) {
final CommandWrapper commandRequest = builder.adjustSavingsAccountTransaction(savingsId, transactionId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
} else if (is(commandParam,SavingsApiConstants.COMMAND_RELEASE_AMOUNT)) {
final CommandWrapper commandRequest = builder.releaseAmount(savingsId, transactionId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
}
if (result == null) {
//
throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "undo" });
throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { SavingsApiConstants.COMMAND_UNDO_TRANSACTION,
SavingsApiConstants.COMMAND_ADJUST_TRANSACTION, SavingsApiConstants.COMMAND_RELEASE_AMOUNT});
}
return this.toApiJsonSerializer.serialize(result);
@@ -279,13 +279,33 @@ public class SavingsAccountsApiResource {
final CommandWrapper commandRequest = builder.unassignSavingsOfficer(accountId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
return this.toApiJsonSerializer.serialize(result);
} else if (is(commandParam, SavingsApiConstants.COMMAND_BLOCK_DEBIT)) {
final CommandWrapper commandRequest = builder.blockDebitsFromSavingsAccount(accountId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
} else if (is(commandParam, SavingsApiConstants.COMMAND_UNBLOCK_DEBIT)) {
final CommandWrapper commandRequest = builder.unblockDebitsFromSavingsAccount(accountId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
} else if (is(commandParam, SavingsApiConstants.COMMAND_BLOCK_CREDIT)) {
final CommandWrapper commandRequest = builder.blockCreditsToSavingsAccount(accountId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
} else if (is(commandParam, SavingsApiConstants.COMMAND_UNBLOCK_CREDIT)) {
final CommandWrapper commandRequest = builder.unblockCreditsToSavingsAccount(accountId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
} else if (is(commandParam, SavingsApiConstants.COMMAND_BLOCK_ACCOUNT)) {
final CommandWrapper commandRequest = builder.withNoJsonBody().blockSavingsAccount(accountId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
} else if (is(commandParam, SavingsApiConstants.COMMAND_UNBLOCK_ACCOUNT)) {
final CommandWrapper commandRequest = builder.withNoJsonBody().unblockSavingsAccount(accountId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
}
if (result == null) {
//
throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "reject", "withdrawnByApplicant", "approve",
"undoapproval", "activate", "calculateInterest", "postInterest", "close", "assignSavingsOfficer",
"unassignSavingsOfficer" });
"unassignSavingsOfficer", SavingsApiConstants.COMMAND_BLOCK_DEBIT, SavingsApiConstants.COMMAND_UNBLOCK_DEBIT,
SavingsApiConstants.COMMAND_BLOCK_CREDIT, SavingsApiConstants.COMMAND_UNBLOCK_CREDIT,
SavingsApiConstants.COMMAND_BLOCK_ACCOUNT, SavingsApiConstants.COMMAND_UNBLOCK_ACCOUNT });
}
return this.toApiJsonSerializer.serialize(result);
@@ -36,9 +36,15 @@ public class SavingsAccountSubStatusEnumData {
private final boolean dormant;
@SuppressWarnings("unused")
private final boolean escheat;
@SuppressWarnings("unused")
private final boolean block;
@SuppressWarnings("unused")
private final boolean blockCredit;
@SuppressWarnings("unused")
private final boolean blockDebit;
public SavingsAccountSubStatusEnumData(final Long id, final String code, final String value, final boolean none,
final boolean inactive, final boolean dormant, final boolean escheat) {
final boolean inactive, final boolean dormant, final boolean escheat, final boolean block, final boolean blockCredit, final boolean blockDebit) {
this.id = id;
this.code = code;
this.value = value;
@@ -46,6 +52,9 @@ public class SavingsAccountSubStatusEnumData {
this.inactive = inactive;
this.dormant = dormant;
this.escheat = escheat;
this.block = block;
this.blockCredit = blockCredit;
this.blockDebit = blockDebit;
}
public Long id() {
@@ -43,12 +43,13 @@ public class SavingsAccountSummaryData {
private final BigDecimal totalWithholdTax;
private final BigDecimal interestNotPosted;
private final LocalDate lastInterestCalculationDate;
private final BigDecimal availableBalance;
public SavingsAccountSummaryData(final CurrencyData currency, final BigDecimal totalDeposits, final BigDecimal totalWithdrawals,
final BigDecimal totalWithdrawalFees, final BigDecimal totalAnnualFees, final BigDecimal totalInterestEarned,
final BigDecimal totalInterestPosted, final BigDecimal accountBalance, final BigDecimal totalFeeCharge,
final BigDecimal totalPenaltyCharge, final BigDecimal totalOverdraftInterestDerived,final BigDecimal totalWithholdTax,
final BigDecimal interestNotPosted, final LocalDate lastInterestCalculationDate) {
final BigDecimal interestNotPosted, final LocalDate lastInterestCalculationDate, final BigDecimal availableBalance) {
this.currency = currency;
this.totalDeposits = totalDeposits;
this.totalWithdrawals = totalWithdrawals;
@@ -63,5 +64,6 @@ public class SavingsAccountSummaryData {
this.totalWithholdTax = totalWithholdTax;
this.interestNotPosted = interestNotPosted;
this.lastInterestCalculationDate = lastInterestCalculationDate;
this.availableBalance = availableBalance;
}
}
@@ -29,6 +29,8 @@ import static org.apache.fineract.portfolio.savings.SavingsApiConstants.transact
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.transactionAmountParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.transactionDateParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withdrawBalanceParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.SAVINGS_ACCOUNT_HOLD_AMOUNT_REQUEST_DATA_PARAMETERS;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME;
import java.lang.reflect.Type;
import java.math.BigDecimal;
@@ -38,6 +40,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Date;
import org.apache.commons.lang.StringUtils;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
@@ -46,10 +49,16 @@ import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail;
import org.apache.fineract.portfolio.savings.SavingsApiConstants;
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
import org.apache.fineract.portfolio.savings.domain.SavingsAccountTransaction;
import org.apache.fineract.useradministration.domain.AppUser;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.apache.fineract.organisation.monetary.domain.Money;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
@@ -160,6 +169,68 @@ public class SavingsAccountTransactionDataValidator {
}
}
public SavingsAccountTransaction validateHoldAndAssembleForm(final String json, final SavingsAccount account, final AppUser createdUser) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, SAVINGS_ACCOUNT_HOLD_AMOUNT_REQUEST_DATA_PARAMETERS);
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(SAVINGS_ACCOUNT_RESOURCE_NAME);
final JsonElement element = this.fromApiJsonHelper.parse(json);
final BigDecimal amount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(transactionAmountParamName, element);
baseDataValidator.reset().parameter(transactionAmountParamName).value(amount).notNull().positiveAmount();
final LocalDate transactionDate = this.fromApiJsonHelper.extractLocalDateNamed(transactionDateParamName, element);
baseDataValidator.reset().parameter(transactionDateParamName).value(transactionDate).notNull();
boolean isActive = account.isActive();
if (!isActive) {
baseDataValidator.reset().parameter(SavingsApiConstants.statusParamName)
.failWithCodeNoParameterAddedToErrorCode(SavingsApiConstants.ERROR_MSG_SAVINGS_ACCOUNT_NOT_ACTIVE);
}
account.holdFunds(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
if (lastTransactionDate != null && transactionDate.isBefore(lastTransactionDate)) {
baseDataValidator.parameter(SavingsApiConstants.dateParamName).value(lastTransactionDate).failWithCode(
"validation.msg.date.can.not.be.before.last.transaction.date", "Amount can be put on hold only after last transaction");
}
throwExceptionIfValidationWarningsExist(dataValidationErrors);
final PaymentDetail paymentDetails = null;
Date createdDate = DateUtils.getDateOfTenant();
SavingsAccountTransaction transaction = SavingsAccountTransaction.holdAmount(account, account.office(), paymentDetails,
transactionDate, Money.of(account.getCurrency(), amount), createdDate, createdUser);
return transaction;
}
public SavingsAccountTransaction validateReleaseAmountAndAssembleForm(final SavingsAccountTransaction holdTransaction, final AppUser createdUser) {
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
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");
}
throwExceptionIfValidationWarningsExist(dataValidationErrors);
Date createdDate = DateUtils.getDateOfTenant();
LocalDate transactionDate = DateUtils.getLocalDateOfTenant();
SavingsAccountTransaction transaction = SavingsAccountTransaction.releaseAmount(holdTransaction, transactionDate, createdDate,
createdUser);
return transaction;
}
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) {
@@ -44,6 +44,8 @@ public class SavingsAccountTransactionEnumData {
private final boolean overdraftFee = true;
private final boolean withholdTax;
private final boolean escheat;
private final boolean amountHold;
private final boolean amountRelease;
public SavingsAccountTransactionEnumData(final Long id, final String code, final String value) {
this.id = id;
@@ -64,6 +66,8 @@ public class SavingsAccountTransactionEnumData {
this.overdraftInterest = Long.valueOf(SavingsAccountTransactionType.OVERDRAFT_INTEREST.getValue()).equals(this.id);
this.withholdTax = Long.valueOf(SavingsAccountTransactionType.WITHHOLD_TAX.getValue()).equals(this.id);
this.escheat = Long.valueOf(SavingsAccountTransactionType.ESCHEAT.getValue()).equals(this.id);
this.amountHold = Long.valueOf(SavingsAccountTransactionType.AMOUNT_HOLD.getValue()).equals(this.id);
this.amountRelease = Long.valueOf(SavingsAccountTransactionType.AMOUNT_RELEASE.getValue()).equals(this.id);
// this.overdraftFee =
// Long.valueOf(SavingsAccountTransactionType.OVERDRAFT_INTEREST.getValue()).equals(this.id);
}
@@ -139,5 +143,13 @@ public class SavingsAccountTransactionEnumData {
public boolean isEscheat() {
return this.escheat;
}
public boolean isAmountOnHold() {
return this.amountHold;
}
public boolean isAmountRelease() {
return this.amountRelease;
}
}
@@ -100,6 +100,9 @@ import org.apache.fineract.portfolio.savings.SavingsPostingInterestPeriodType;
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionDTO;
import org.apache.fineract.portfolio.savings.domain.interest.PostingPeriod;
import org.apache.fineract.portfolio.savings.exception.InsufficientAccountBalanceException;
import org.apache.fineract.portfolio.savings.exception.SavingsAccountBlockedException;
import org.apache.fineract.portfolio.savings.exception.SavingsAccountCreditsBlockedException;
import org.apache.fineract.portfolio.savings.exception.SavingsAccountDebitsBlockedException;
import org.apache.fineract.portfolio.savings.exception.SavingsAccountTransactionNotFoundException;
import org.apache.fineract.portfolio.savings.exception.SavingsActivityPriorToClientTransferException;
import org.apache.fineract.portfolio.savings.exception.SavingsOfficerAssignmentDateException;
@@ -1053,7 +1056,9 @@ public class SavingsAccount extends AbstractPersistableCustom<Long> {
runningBalance = runningBalance.plus(transaction.getAmount(this.currency));
} else if (transaction.isNotReversed() && transaction.isDebit()) {
runningBalance = runningBalance.minus(transaction.getAmount(this.currency));
} else {
} else if(transaction.isAmountOnHold() && transaction.getReleaseIdOfHoldAmountTransaction() == null){
runningBalance = runningBalance.minus(transaction.getAmount(this.currency));
}else {
continue;
}
@@ -2822,4 +2827,188 @@ public class SavingsAccount extends AbstractPersistableCustom<Long> {
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, transactions);
}
public Map<String, Object> block() {
final Map<String, Object> actualChanges = new LinkedHashMap<>();
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(depositAccountType().resourceName() + SavingsApiConstants.blockAction);
final SavingsAccountStatusType currentStatus = SavingsAccountStatusType.fromInt(this.status);
if (!SavingsAccountStatusType.ACTIVE.hasStateOf(currentStatus)) {
baseDataValidator.reset().parameter(SavingsApiConstants.statusParamName)
.failWithCodeNoParameterAddedToErrorCode(SavingsApiConstants.ERROR_MSG_SAVINGS_ACCOUNT_NOT_ACTIVE);
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
}
this.sub_status = SavingsAccountSubStatusEnum.BLOCK.getValue();
actualChanges.put(SavingsApiConstants.subStatusParamName, SavingsEnumerations.subStatus(this.sub_status));
return actualChanges;
}
public Map<String, Object> unblock() {
final Map<String, Object> actualChanges = new LinkedHashMap<>();
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(depositAccountType().resourceName() + SavingsApiConstants.unblockAction);
final SavingsAccountStatusType currentStatus = SavingsAccountStatusType.fromInt(this.status);
if (!SavingsAccountStatusType.ACTIVE.hasStateOf(currentStatus)) {
baseDataValidator.reset().parameter(SavingsApiConstants.statusParamName)
.failWithCodeNoParameterAddedToErrorCode(SavingsApiConstants.ERROR_MSG_SAVINGS_ACCOUNT_NOT_ACTIVE);
}
final SavingsAccountSubStatusEnum currentSubStatus = SavingsAccountSubStatusEnum.fromInt(this.sub_status);
if (!SavingsAccountSubStatusEnum.BLOCK.hasStateOf(currentSubStatus)) {
baseDataValidator.reset().parameter(SavingsApiConstants.subStatusParamName)
.failWithCodeNoParameterAddedToErrorCode("not.in.blocked.state");
}
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
this.sub_status = SavingsAccountSubStatusEnum.NONE.getValue();
actualChanges.put(SavingsApiConstants.subStatusParamName, SavingsEnumerations.subStatus(this.sub_status));
return actualChanges;
}
public Map<String, Object> blockCredits(Integer currentSubstatus) {
final Map<String, Object> actualChanges = new LinkedHashMap<>();
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(depositAccountType().resourceName() + SavingsApiConstants.blockCreditsAction);
final SavingsAccountStatusType currentStatus = SavingsAccountStatusType.fromInt(this.status);
if (!SavingsAccountStatusType.ACTIVE.hasStateOf(currentStatus)) {
baseDataValidator.reset().parameter(SavingsApiConstants.statusParamName)
.failWithCodeNoParameterAddedToErrorCode(SavingsApiConstants.ERROR_MSG_SAVINGS_ACCOUNT_NOT_ACTIVE);
}
if (SavingsAccountSubStatusEnum.BLOCK.hasStateOf(SavingsAccountSubStatusEnum.fromInt(currentSubstatus))
|| SavingsAccountSubStatusEnum.BLOCK_DEBIT.hasStateOf(SavingsAccountSubStatusEnum.fromInt(currentSubstatus))) {
baseDataValidator.reset().parameter(SavingsApiConstants.subStatusParamName).value(SavingsAccountSubStatusEnum.fromInt(currentSubstatus))
.failWithCodeNoParameterAddedToErrorCode("currently.set");
}
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
this.sub_status = SavingsAccountSubStatusEnum.BLOCK_CREDIT.getValue();
actualChanges.put(SavingsApiConstants.subStatusParamName, SavingsEnumerations.subStatus(this.sub_status));
return actualChanges;
}
public Map<String, Object> unblockCredits() {
final Map<String, Object> actualChanges = new LinkedHashMap<>();
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(depositAccountType().resourceName() + SavingsApiConstants.unblockCreditsAction);
final SavingsAccountStatusType currentStatus = SavingsAccountStatusType.fromInt(this.status);
if (!SavingsAccountStatusType.ACTIVE.hasStateOf(currentStatus)) {
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode(SavingsApiConstants.ERROR_MSG_SAVINGS_ACCOUNT_NOT_ACTIVE);
}
final SavingsAccountSubStatusEnum currentSubStatus = SavingsAccountSubStatusEnum.fromInt(this.sub_status);
if (!SavingsAccountSubStatusEnum.BLOCK_CREDIT.hasStateOf(currentSubStatus)) {
baseDataValidator.reset().parameter(SavingsApiConstants.statusParamName)
.failWithCodeNoParameterAddedToErrorCode("credits.are.not.blocked");
}
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
this.sub_status = SavingsAccountSubStatusEnum.NONE.getValue();
actualChanges.put(SavingsApiConstants.subStatusParamName, SavingsEnumerations.subStatus(this.sub_status));
return actualChanges;
}
public Map<String, Object> blockDebits(Integer currentSubstatus) {
final Map<String, Object> actualChanges = new LinkedHashMap<>();
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(depositAccountType().resourceName() + SavingsApiConstants.blockDebitsAction);
final SavingsAccountStatusType currentStatus = SavingsAccountStatusType.fromInt(this.status);
if (!SavingsAccountStatusType.ACTIVE.hasStateOf(currentStatus)) {
baseDataValidator.reset().parameter(SavingsApiConstants.statusParamName)
.failWithCodeNoParameterAddedToErrorCode(SavingsApiConstants.ERROR_MSG_SAVINGS_ACCOUNT_NOT_ACTIVE);
}
if (SavingsAccountSubStatusEnum.BLOCK.hasStateOf(SavingsAccountSubStatusEnum.fromInt(currentSubstatus))
|| SavingsAccountSubStatusEnum.BLOCK_CREDIT.hasStateOf(SavingsAccountSubStatusEnum.fromInt(currentSubstatus))) {
baseDataValidator.reset().parameter(SavingsApiConstants.subStatusParamName).value(SavingsAccountSubStatusEnum.fromInt(currentSubstatus))
.failWithCodeNoParameterAddedToErrorCode("currently.set");
}
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
this.sub_status = SavingsAccountSubStatusEnum.BLOCK_DEBIT.getValue();
actualChanges.put(SavingsApiConstants.subStatusParamName, SavingsEnumerations.subStatus(this.sub_status));
return actualChanges;
}
public Map<String, Object> unblockDebits() {
final Map<String, Object> actualChanges = new LinkedHashMap<>();
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(depositAccountType().resourceName() + SavingsApiConstants.unblockDebitsAction);
final SavingsAccountStatusType currentStatus = SavingsAccountStatusType.fromInt(this.status);
if (!SavingsAccountStatusType.ACTIVE.hasStateOf(currentStatus)) {
baseDataValidator.reset().parameter(SavingsApiConstants.statusParamName)
.failWithCodeNoParameterAddedToErrorCode(SavingsApiConstants.ERROR_MSG_SAVINGS_ACCOUNT_NOT_ACTIVE);
}
final SavingsAccountSubStatusEnum currentSubStatus = SavingsAccountSubStatusEnum.fromInt(this.sub_status);
if (!SavingsAccountSubStatusEnum.BLOCK_DEBIT.hasStateOf(currentSubStatus)) {
baseDataValidator.reset().parameter(SavingsApiConstants.subStatusParamName)
.failWithCodeNoParameterAddedToErrorCode("debits.are.not.blocked");
}
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
this.sub_status = SavingsAccountSubStatusEnum.NONE.getValue();
actualChanges.put(SavingsApiConstants.subStatusParamName, SavingsEnumerations.subStatus(this.sub_status));
return actualChanges;
}
public Integer getSubStatus() {
return this.sub_status;
}
public void validateForAccountBlock() {
final SavingsAccountSubStatusEnum currentSubStatus = SavingsAccountSubStatusEnum.fromInt(this.getSubStatus());
if (SavingsAccountSubStatusEnum.BLOCK.hasStateOf(currentSubStatus)) { throw new SavingsAccountBlockedException(this.getId()); }
}
public void validateForDebitBlock() {
final SavingsAccountSubStatusEnum currentSubStatus = SavingsAccountSubStatusEnum.fromInt(this.getSubStatus());
if (SavingsAccountSubStatusEnum.BLOCK_DEBIT
.hasStateOf(currentSubStatus)) { throw new SavingsAccountDebitsBlockedException(this.getId()); }
}
public void validateForCreditBlock() {
final SavingsAccountSubStatusEnum currentSubStatus = SavingsAccountSubStatusEnum.fromInt(this.getSubStatus());
if (SavingsAccountSubStatusEnum.BLOCK_CREDIT
.hasStateOf(currentSubStatus)) { throw new SavingsAccountCreditsBlockedException(this.getId()); }
}
public LocalDate retrieveLastTransactionDate() {
final List<SavingsAccountTransaction> transactionsSortedByDate = retreiveListOfTransactions();
SavingsAccountTransaction lastTransaction = transactionsSortedByDate.get(transactionsSortedByDate.size() - 1);
return lastTransaction.transactionLocalDate();
}
}
@@ -86,6 +86,8 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
final SavingsTransactionBooleanValues transactionBooleanValues) {
AppUser user = getAppUserIfPresent();
account.validateForAccountBlock();
account.validateForDebitBlock();
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
.isSavingsInterestPostingAtCurrentPeriodEnd();
final Integer financialYearBeginningMonth = this.configurationDomainService.retrieveFinancialYearBeginningMonth();
@@ -148,6 +150,8 @@ public class SavingsAccountDomainServiceJpa implements SavingsAccountDomainServi
final boolean isAccountTransfer, final boolean isRegularTransaction,
final SavingsAccountTransactionType savingsAccountTransactionType) {
AppUser user = getAppUserIfPresent();
account.validateForAccountBlock();
account.validateForCreditBlock();
final boolean isSavingsInterestPostingAtCurrentPeriodEnd = this.configurationDomainService
.isSavingsInterestPostingAtCurrentPeriodEnd();
final Integer financialYearBeginningMonth = this.configurationDomainService.retrieveFinancialYearBeginningMonth();
@@ -26,7 +26,10 @@ public enum SavingsAccountSubStatusEnum {
NONE(0, "SavingsAccountSubStatusEnum.none"), //
INACTIVE(100, "SavingsAccountSubStatusEnum.inactive"), //
DORMANT(200, "SavingsAccountSubStatusEnum.dormant"),
ESCHEAT(300,"SavingsAccountSubStatusEnum.escheat");
ESCHEAT(300,"SavingsAccountSubStatusEnum.escheat"),
BLOCK(400, "SavingsAccountSubStatusEnum.block"),
BLOCK_CREDIT(500, "SavingsAccountSubStatusEnum.blockCredit"),
BLOCK_DEBIT(600, "SavingsAccountSubStatusEnum.blockDebit");
private final Integer value;
private final String code;
@@ -45,6 +48,15 @@ public enum SavingsAccountSubStatusEnum {
case 300:
enumeration = SavingsAccountSubStatusEnum.ESCHEAT;
break;
case 400:
enumeration = SavingsAccountSubStatusEnum.BLOCK;
break;
case 500:
enumeration = SavingsAccountSubStatusEnum.BLOCK_CREDIT;
break;
case 600:
enumeration = SavingsAccountSubStatusEnum.BLOCK_DEBIT;
break;
}
}
return enumeration;
@@ -82,4 +94,16 @@ public enum SavingsAccountSubStatusEnum {
public boolean isSubStatusEscheat() {
return this.value.equals(SavingsAccountSubStatusEnum.ESCHEAT.getValue());
}
public boolean isSubStatusAccountBlocked() {
return this.value.equals(SavingsAccountSubStatusEnum.BLOCK.getValue());
}
public boolean isSubStatusCreditBlocked() {
return this.value.equals(SavingsAccountSubStatusEnum.BLOCK_CREDIT.getValue());
}
public boolean isSubStatusDebitBlocked() {
return this.value.equals(SavingsAccountSubStatusEnum.BLOCK_DEBIT.getValue());
}
}
@@ -121,6 +121,9 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom<L
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch=FetchType.EAGER)
@JoinColumn(name = "savings_transaction_id", referencedColumnName = "id", nullable = false)
private List<SavingsAccountTransactionTaxDetails> taxDetails = new ArrayList<>();
@Column(name = "release_id_of_hold_amount", length = 20)
private Long releaseIdOfHoldAmountTransaction;
protected SavingsAccountTransaction() {
this.dateOf = null;
@@ -289,6 +292,21 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom<L
this.appUser = appUser;
this.isManualTransaction = isManualTransaction;
}
public static SavingsAccountTransaction holdAmount(final SavingsAccount savingsAccount, final Office office,
final PaymentDetail paymentDetail, final LocalDate date, final Money amount, Date createdDate, final AppUser appUser) {
final boolean isReversed = false;
final boolean isManualTransaction = false;
return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, SavingsAccountTransactionType.AMOUNT_HOLD.getValue(),
date, createdDate, amount, isReversed, appUser, isManualTransaction);
}
public static SavingsAccountTransaction releaseAmount(SavingsAccountTransaction accountTransaction,LocalDate transactionDate, Date createdDate,
final AppUser appUser) {
return new SavingsAccountTransaction(accountTransaction.savingsAccount, accountTransaction.office, accountTransaction.paymentDetail,
SavingsAccountTransactionType.AMOUNT_RELEASE.getValue(),transactionDate , createdDate,
accountTransaction.amount, accountTransaction.reversed, appUser, accountTransaction.isManualTransaction);
}
public LocalDate transactionLocalDate() {
return new LocalDate(this.dateOf);
@@ -640,6 +658,14 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom<L
public boolean isWaiveCharge() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isWaiveCharge();
}
public boolean isAmountOnHold() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isAmountOnHold();
}
public boolean isAmountRelease() {
return SavingsAccountTransactionType.fromInt(this.typeOf).isAmountRelease();
}
private boolean canOverriteSavingAccountRules() {
final SavingsAccountChargePaidBy chargePaidBy = getSavingsAccountChargePaidBy();
@@ -753,4 +779,12 @@ public final class SavingsAccountTransaction extends AbstractPersistableCustom<L
public PaymentDetail getPaymentDetail() {
return this.paymentDetail ;
}
public void updateReleaseId(Long releaseId) {
this.releaseIdOfHoldAmountTransaction = releaseId;
}
public Long getReleaseIdOfHoldAmountTransaction() {
return this.releaseIdOfHoldAmountTransaction;
}
}
@@ -0,0 +1,29 @@
/**
* 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.portfolio.savings.exception;
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
public class SavingsAccountBlockedException extends AbstractPlatformDomainRuleException {
public SavingsAccountBlockedException(final Long accountId) {
super("error.msg.saving.account.blocked.transaction.not.allowed",
"Any transaction to " + accountId + " is not allowed, since the account is blocked", accountId);
}
}
@@ -0,0 +1,29 @@
/**
* 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.portfolio.savings.exception;
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
public class SavingsAccountCreditsBlockedException extends AbstractPlatformDomainRuleException {
public SavingsAccountCreditsBlockedException(final Long accountId) {
super("error.msg.savings.account.credit.transaction.not.allowed",
"Any Credit transactions to " + accountId + " is not allowed, since the account is blocked for credits", accountId);
}
}
@@ -0,0 +1,30 @@
/**
* 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.portfolio.savings.exception;
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
public class SavingsAccountDebitsBlockedException extends AbstractPlatformDomainRuleException {
public SavingsAccountDebitsBlockedException(final Long accountId) {
super("error.msg.savings.account.debit.transaction.not.allowed",
"Any debit transactions from " + accountId + " is not allowed, since the account is blocked for debits", accountId);
}
}
@@ -0,0 +1,47 @@
/**
* 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.portfolio.savings.handler;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@CommandType(entity = "SAVINGSACCOUNT", action = "BLOCKCREDIT")
public class BlockCreditsToSavingsAccountCommandHandler implements NewCommandSourceHandler {
private final SavingsAccountWritePlatformService writePlatformService;
@Autowired
public BlockCreditsToSavingsAccountCommandHandler(final SavingsAccountWritePlatformService savingAccountWritePlatformService) {
this.writePlatformService = savingAccountWritePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(JsonCommand command) {
return this.writePlatformService.blockCredits(command.getSavingsId());
}
}
@@ -0,0 +1,47 @@
/**
* 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.portfolio.savings.handler;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@CommandType(entity = "SAVINGSACCOUNT", action = "BLOCKDEBIT")
public class BlockDebitsFromSavingsAccountCommandHandler implements NewCommandSourceHandler {
private final SavingsAccountWritePlatformService writePlatformService;
@Autowired
public BlockDebitsFromSavingsAccountCommandHandler(final SavingsAccountWritePlatformService savingAccountWritePlatformService) {
this.writePlatformService = savingAccountWritePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(JsonCommand command) {
return this.writePlatformService.blockDebits(command.getSavingsId());
}
}
@@ -0,0 +1,47 @@
/**
* 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.portfolio.savings.handler;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@CommandType(entity = "SAVINGSACCOUNT", action = "BLOCK")
public class BlockSavingsAccountCommandHandler implements NewCommandSourceHandler {
private final SavingsAccountWritePlatformService writePlatformService;
@Autowired
public BlockSavingsAccountCommandHandler(final SavingsAccountWritePlatformService savingAccountWritePlatformService) {
this.writePlatformService = savingAccountWritePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(JsonCommand command) {
return this.writePlatformService.blockAccount(command.getSavingsId());
}
}
@@ -0,0 +1,47 @@
/**
* 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.portfolio.savings.handler;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@CommandType(entity = "SAVINGSACCOUNT", action = "HOLDAMOUNT")
public class HoldAmountSavingsAccountCommandHandler implements NewCommandSourceHandler {
private final SavingsAccountWritePlatformService writePlatformService;
@Autowired
public HoldAmountSavingsAccountCommandHandler(final SavingsAccountWritePlatformService savingAccountWritePlatformService) {
this.writePlatformService = savingAccountWritePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(JsonCommand command) {
return this.writePlatformService.holdAmount(command.getSavingsId(), command);
}
}
@@ -0,0 +1,48 @@
/**
* 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.portfolio.savings.handler;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@CommandType(entity = "SAVINGSACCOUNT", action = "RELEASEAMOUNT")
public class ReleaseAmountSavingsAccountCommandHandler implements NewCommandSourceHandler {
private final SavingsAccountWritePlatformService writePlatformService;
@Autowired
public ReleaseAmountSavingsAccountCommandHandler(final SavingsAccountWritePlatformService savingAccountWritePlatformService) {
this.writePlatformService = savingAccountWritePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(JsonCommand command) {
final Long transactionId = Long.valueOf(command.getTransactionId());
return this.writePlatformService.releaseAmount(command.getSavingsId(), transactionId);
}
}
@@ -0,0 +1,47 @@
/**
* 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.portfolio.savings.handler;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@CommandType(entity = "SAVINGSACCOUNT", action = "UNBLOCKCREDIT")
public class UnblockCreditsToSavingsAccountCommandHandler implements NewCommandSourceHandler {
private final SavingsAccountWritePlatformService writePlatformService;
@Autowired
public UnblockCreditsToSavingsAccountCommandHandler(final SavingsAccountWritePlatformService savingAccountWritePlatformService) {
this.writePlatformService = savingAccountWritePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(JsonCommand command) {
return this.writePlatformService.unblockCredits(command.getSavingsId());
}
}
@@ -0,0 +1,46 @@
/**
* 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.portfolio.savings.handler;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@CommandType(entity = "SAVINGSACCOUNT", action = "UNBLOCKDEBIT")
public class UnblockDebitsFromSavingsAccountCommandHandler implements NewCommandSourceHandler {
private final SavingsAccountWritePlatformService writePlatformService;
@Autowired
public UnblockDebitsFromSavingsAccountCommandHandler(final SavingsAccountWritePlatformService savingAccountWritePlatformService) {
this.writePlatformService = savingAccountWritePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(JsonCommand command) {
return this.writePlatformService.unblockDebits(command.getSavingsId());
}
}
@@ -0,0 +1,46 @@
/**
* 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.portfolio.savings.handler;
import org.apache.fineract.commands.annotation.CommandType;
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@CommandType(entity = "SAVINGSACCOUNT", action = "UNBLOCK")
public class UnblockSavingsAccountCommandHandler implements NewCommandSourceHandler {
private final SavingsAccountWritePlatformService writePlatformService;
@Autowired
public UnblockSavingsAccountCommandHandler(final SavingsAccountWritePlatformService savingAccountWritePlatformService) {
this.writePlatformService = savingAccountWritePlatformService;
}
@Transactional
@Override
public CommandProcessingResult processCommand(JsonCommand command) {
return this.writePlatformService.unblockAccount(command.getSavingsId());
}
}
@@ -738,9 +738,10 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
taxGroupData = TaxGroupData.lookup(taxGroupId, taxGroupName);
}
final BigDecimal availableBalance = null;
final SavingsAccountSummaryData summary = new SavingsAccountSummaryData(currency, totalDeposits, totalWithdrawals,
totalWithdrawalFees, totalAnnualFees, totalInterestEarned, totalInterestPosted, accountBalance, totalFeeCharge,
totalPenaltyCharge, totalOverdraftInterestDerived, totalWithholdTax, null, null);
totalPenaltyCharge, totalOverdraftInterestDerived, totalWithholdTax, null, null, availableBalance);
return DepositAccountData.instance(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName,
fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
@@ -511,6 +511,12 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
"minBalanceForInterestCalculation");
final BigDecimal onHoldFunds = rs.getBigDecimal("onHoldFunds");
BigDecimal availableBalance = accountBalance;
if (availableBalance != null && onHoldFunds != null) {
availableBalance = availableBalance.subtract(onHoldFunds);
}
BigDecimal interestNotPosted = BigDecimal.ZERO;
LocalDate lastInterestCalculationDate = null;
if(totalInterestEarned != null){
@@ -520,7 +526,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
final SavingsAccountSummaryData summary = new SavingsAccountSummaryData(currency, totalDeposits, totalWithdrawals,
totalWithdrawalFees, totalAnnualFees, totalInterestEarned, totalInterestPosted, accountBalance, totalFeeCharge,
totalPenaltyCharge, totalOverdraftInterestDerived, totalWithholdTax, interestNotPosted, lastInterestCalculationDate);
totalPenaltyCharge, totalOverdraftInterestDerived, totalWithholdTax, interestNotPosted, lastInterestCalculationDate, availableBalance);
final boolean withHoldTax = rs.getBoolean("withHoldTax");
final Long taxGroupId = JdbcSupport.getLong(rs, "taxGroupId");
@@ -88,4 +88,20 @@ public interface SavingsAccountWritePlatformService {
CommandProcessingResult postInterest(JsonCommand command);
void postInterest(SavingsAccount account, boolean postInterestAs, LocalDate transactionDate);
CommandProcessingResult blockAccount(Long savingsId);
CommandProcessingResult unblockAccount(Long savingsId);
CommandProcessingResult holdAmount(Long savingsId, JsonCommand command);
CommandProcessingResult blockCredits(Long savingsId);
CommandProcessingResult unblockCredits(Long savingsId);
CommandProcessingResult blockDebits(Long savingsId);
CommandProcessingResult unblockDebits(Long savingsId);
CommandProcessingResult releaseAmount(Long savingsId, Long transactionId);
}
@@ -1339,4 +1339,141 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
map.put(entityEvent, entity);
return map;
}
@Override
public CommandProcessingResult blockAccount(final Long savingsId) {
this.context.authenticatedUser();
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
checkClientOrGroupActive(account);
final Map<String, Object> changes = account.block();
if (!changes.isEmpty()) {
this.savingAccountRepositoryWrapper.save(account);
}
return new CommandProcessingResultBuilder().withEntityId(savingsId).withOfficeId(account.officeId())
.withClientId(account.clientId()).withGroupId(account.groupId()).withSavingsId(savingsId).with(changes).build();
}
@Override
public CommandProcessingResult unblockAccount(final Long savingsId) {
this.context.authenticatedUser();
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
checkClientOrGroupActive(account);
final Map<String, Object> changes = account.unblock();
if (!changes.isEmpty()) {
this.savingAccountRepositoryWrapper.save(account);
}
return new CommandProcessingResultBuilder().withEntityId(savingsId).withOfficeId(account.officeId())
.withClientId(account.clientId()).withGroupId(account.groupId()).withSavingsId(savingsId).with(changes).build();
}
@Transactional
@Override
public CommandProcessingResult holdAmount(final Long savingsId, final JsonCommand command) {
final AppUser submittedBy = this.context.authenticatedUser();
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
checkClientOrGroupActive(account);
SavingsAccountTransaction transacton = this.savingsAccountTransactionDataValidator.validateHoldAndAssembleForm(command.json(),
account, submittedBy);
this.savingsAccountTransactionRepository.save(transacton);
this.savingAccountRepositoryWrapper.saveAndFlush(account);
return new CommandProcessingResultBuilder().withEntityId(transacton.getId()).withOfficeId(account.officeId())
.withClientId(account.clientId()).withGroupId(account.groupId()).withSavingsId(savingsId).build();
}
@Transactional
@Override
public CommandProcessingResult releaseAmount(final Long savingsId, final Long savingsTransactionId) {
final AppUser submittedBy = this.context.authenticatedUser();
SavingsAccountTransaction holdTransaction = this.savingsAccountTransactionRepository
.findOneByIdAndSavingsAccountId(savingsTransactionId, savingsId);
final SavingsAccountTransaction transaction = this.savingsAccountTransactionDataValidator
.validateReleaseAmountAndAssembleForm(holdTransaction, submittedBy);
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
checkClientOrGroupActive(account);
account.releaseFunds(transaction.getAmount());
this.savingsAccountTransactionRepository.save(transaction);
holdTransaction.updateReleaseId(transaction.getId());
this.savingAccountRepositoryWrapper.save(account);
return new CommandProcessingResultBuilder().withEntityId(transaction.getId()).withOfficeId(account.officeId())
.withClientId(account.clientId()).withGroupId(account.groupId()).withSavingsId(account.getId()).build();
}
@Override
public CommandProcessingResult blockCredits(final Long savingsId) {
this.context.authenticatedUser();
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
checkClientOrGroupActive(account);
final Map<String, Object> changes = account.blockCredits(account.getSubStatus());
if (!changes.isEmpty()) {
this.savingAccountRepositoryWrapper.save(account);
}
return new CommandProcessingResultBuilder().withEntityId(savingsId).withOfficeId(account.officeId())
.withClientId(account.clientId()).withGroupId(account.groupId()).withSavingsId(savingsId).with(changes).build();
}
@Override
public CommandProcessingResult unblockCredits(final Long savingsId) {
this.context.authenticatedUser();
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
checkClientOrGroupActive(account);
final Map<String, Object> changes = account.unblockCredits();
if (!changes.isEmpty()) {
this.savingAccountRepositoryWrapper.save(account);
}
return new CommandProcessingResultBuilder().withEntityId(savingsId).withOfficeId(account.officeId())
.withClientId(account.clientId()).withGroupId(account.groupId()).withSavingsId(savingsId).with(changes).build();
}
@Override
public CommandProcessingResult blockDebits(final Long savingsId) {
this.context.authenticatedUser();
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
checkClientOrGroupActive(account);
final Map<String, Object> changes = account.blockDebits(account.getSubStatus());
if (!changes.isEmpty()) {
this.savingAccountRepositoryWrapper.save(account);
}
return new CommandProcessingResultBuilder().withEntityId(savingsId).withOfficeId(account.officeId())
.withClientId(account.clientId()).withGroupId(account.groupId()).withSavingsId(savingsId).with(changes).build();
}
@Override
public CommandProcessingResult unblockDebits(final Long savingsId) {
this.context.authenticatedUser();
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
checkClientOrGroupActive(account);
final Map<String, Object> changes = account.unblockDebits();
if (!changes.isEmpty()) {
this.savingAccountRepositoryWrapper.save(account);
}
return new CommandProcessingResultBuilder().withEntityId(savingsId).withOfficeId(account.officeId())
.withClientId(account.clientId()).withGroupId(account.groupId()).withSavingsId(savingsId).with(changes).build();
}
}
@@ -193,6 +193,14 @@ public class SavingsEnumerations {
optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.ESCHEAT.getValue().longValue(),
SavingsAccountTransactionType.ESCHEAT.getCode(), "Escheat");
break;
case AMOUNT_HOLD:
optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.AMOUNT_HOLD.getValue().longValue(),
SavingsAccountTransactionType.AMOUNT_HOLD.getCode(), "Amount on hold");
break;
case AMOUNT_RELEASE:
optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.AMOUNT_RELEASE.getValue().longValue(),
SavingsAccountTransactionType.AMOUNT_RELEASE.getCode(), "Release Amount");
break;
}
return optionData;
}
@@ -294,22 +302,37 @@ public class SavingsEnumerations {
final boolean inactive = type.isSubStatusInactive();
final boolean dormant = type.isSubStatusDormant();
final boolean escheat = type.isSubStatusEscheat();
final boolean block = type.isSubStatusAccountBlocked();
final boolean blockCredit = type.isSubStatusCreditBlocked();
final boolean blockDebit = type.isSubStatusDebitBlocked();
SavingsAccountSubStatusEnumData optionData = new SavingsAccountSubStatusEnumData(SavingsAccountSubStatusEnum.NONE.getValue().longValue(),
SavingsAccountSubStatusEnum.NONE.getCode(), "None", true, inactive, dormant, escheat);
SavingsAccountSubStatusEnum.NONE.getCode(), "None", true, inactive, dormant, escheat, block, blockCredit, blockDebit);
switch (type) {
case INACTIVE:
optionData = new SavingsAccountSubStatusEnumData(SavingsAccountSubStatusEnum.INACTIVE.getValue().longValue(),
SavingsAccountSubStatusEnum.INACTIVE.getCode(), "Inactive", none, inactive, dormant, escheat);
SavingsAccountSubStatusEnum.INACTIVE.getCode(), "Inactive", none, inactive, dormant, escheat, block, blockCredit, blockDebit);
break;
case DORMANT:
optionData = new SavingsAccountSubStatusEnumData(SavingsAccountSubStatusEnum.DORMANT.getValue().longValue(),
SavingsAccountSubStatusEnum.DORMANT.getCode(), "Dormant", none, inactive, dormant, escheat);
SavingsAccountSubStatusEnum.DORMANT.getCode(), "Dormant", none, inactive, dormant, escheat, block, blockCredit, blockDebit);
break;
case ESCHEAT:
optionData = new SavingsAccountSubStatusEnumData(SavingsAccountSubStatusEnum.ESCHEAT.getValue().longValue(),
SavingsAccountSubStatusEnum.ESCHEAT.getCode(), "Escheat", none, inactive, dormant, escheat);
SavingsAccountSubStatusEnum.ESCHEAT.getCode(), "Escheat", none, inactive, dormant, escheat, block, blockCredit, blockDebit);
break;
case BLOCK:
optionData = new SavingsAccountSubStatusEnumData(SavingsAccountSubStatusEnum.BLOCK.getValue().longValue(),
SavingsAccountSubStatusEnum.BLOCK.getCode(), "Block", none, inactive, dormant, escheat, block, blockCredit, blockDebit);
break;
case BLOCK_CREDIT:
optionData = new SavingsAccountSubStatusEnumData(SavingsAccountSubStatusEnum.BLOCK_CREDIT.getValue().longValue(),
SavingsAccountSubStatusEnum.BLOCK_CREDIT.getCode(), "BlockCredit", none, inactive, dormant, escheat, block, blockCredit, blockDebit);
break;
case BLOCK_DEBIT:
optionData = new SavingsAccountSubStatusEnumData(SavingsAccountSubStatusEnum.BLOCK_DEBIT.getValue().longValue(),
SavingsAccountSubStatusEnum.BLOCK_DEBIT.getCode(), "BlockDebit", none, inactive, dormant, escheat, block, blockCredit, blockDebit);
break;
default:
break;
@@ -0,0 +1,44 @@
--
-- 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.
--
-- permissions
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES
('transaction_savings', 'HOLDAMOUNT_SAVINGSACCOUNT', 'SAVINGSACCOUNT', 'HOLDAMOUNT', 0),
('transaction_savings', 'HOLDAMOUNT_SAVINGSACCOUNT_CHECKER', 'SAVINGSACCOUNT', 'HOLDAMOUNT_CHECKER', 0),
('transaction_savings', 'BLOCKDEBIT_SAVINGSACCOUNT', 'SAVINGSACCOUNT', 'BLOCKDEBIT', 0),
('transaction_savings', 'BLOCKDEBIT_SAVINGSACCOUNT_CHECKER', 'SAVINGSACCOUNT', 'BLOCKDEBIT_CHECKER', 0),
('transaction_savings', 'UNBLOCKDEBIT_SAVINGSACCOUNT', 'SAVINGSACCOUNT', 'UNBLOCKDEBIT', 0),
('transaction_savings', 'UNBLOCKDEBIT_SAVINGSACCOUNT_CHECKER', 'SAVINGSACCOUNT', 'UNBLOCKDEBIT_CHECKER', 0),
('transaction_savings', 'BLOCKCREDIT_SAVINGSACCOUNT', 'SAVINGSACCOUNT', 'BLOCKCREDIT', 0),
('transaction_savings', 'BLOCKCREDIT_SAVINGSACCOUNT_CHECKER', 'SAVINGSACCOUNT', 'BLOCKCREDIT_CHECKER', 0),
('transaction_savings', 'UNBLOCKCREDIT_SAVINGSACCOUNT', 'SAVINGSACCOUNT', 'UNBLOCKCREDIT', 0),
('transaction_savings', 'UNBLOCKCREDIT_SAVINGSACCOUNT_CHECKER', 'SAVINGSACCOUNT', 'UNBLOCKCREDIT_CHECKER', 0),
('transaction_savings', 'BLOCK_SAVINGSACCOUNT', 'SAVINGSACCOUNT', 'BLOCK', 0),
('transaction_savings', 'BLOCK_SAVINGSACCOUNT_CHECKER', 'SAVINGSACCOUNT', 'BLOCK_CHECKER', 0),
('transaction_savings', 'UNBLOCK_SAVINGSACCOUNT', 'SAVINGSACCOUNT', 'UNBLOCK', 0),
('transaction_savings', 'UNBLOCK_SAVINGSACCOUNT_CHECKER', 'SAVINGSACCOUNT', 'UNBLOCK_CHECKER', 0),
('transaction_savings', 'RELEASEAMOUNT_SAVINGSACCOUNT', 'SAVINGSACCOUNT', 'RELEASEAMOUNT', 0),
('transaction_savings', 'RELEASEAMOUNT_SAVINGSACCOUNT_CHECKER', 'SAVINGSACCOUNT', 'RELEASEAMOUNT_CHECKER', 0);
-- modify `m_savings_account_transaction`
ALTER TABLE `m_savings_account_transaction` ADD COLUMN `release_id_of_hold_amount` BIGINT(20) NULL DEFAULT NULL;