Customer Self Service : APIs for Third Party Beneficiary management and Third 
Party Account Transfers


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

Branch: refs/heads/develop
Commit: 2bd3b0625a182a9e4b300f096c45a2585445e556
Parents: 9d4d901
Author: Adi Narayana Raju <[email protected]>
Authored: Wed May 4 13:00:41 2016 +0530
Committer: Adi Narayana Raju <[email protected]>
Committed: Wed May 4 13:01:25 2016 +0530

----------------------------------------------------------------------
 api-docs/apiLive.htm                            |  379 +++++-
 .../commands/service/CommandWrapperBuilder.java |   25 +
 .../domain/ConfigurationDomainService.java      |    4 +
 .../domain/ConfigurationDomainServiceJpa.java   |   16 +
 .../service/TenantDatabaseUpgradeService.java   |    2 +-
 ...arWritePlatformServiceJpaRepositoryImpl.java |    4 +-
 .../AccountTransfersReadPlatformService.java    |    5 +
 ...AccountTransfersReadPlatformServiceImpl.java | 1120 ++++++++++--------
 .../loanaccount/domain/LoanRepository.java      |    6 +-
 .../domain/SavingsAccountRepository.java        |    3 +
 .../api/SelfAccountTransferApiResource.java     |   95 +-
 .../api/SelfBeneficiariesTPTApiConstants.java   |   53 +
 .../api/SelfBeneficiariesTPTApiResource.java    |  161 +++
 .../account/data/SelfAccountTemplateData.java   |    9 +
 .../account/data/SelfAccountTransferData.java   |    9 +-
 .../data/SelfAccountTransferDataValidator.java  |   49 +-
 .../account/data/SelfBeneficiariesTPTData.java  |   69 ++
 .../data/SelfBeneficiariesTPTDataValidator.java |  165 +++
 .../account/domain/SelfBeneficiariesTPT.java    |  136 +++
 .../domain/SelfBeneficiariesTPTRepository.java  |   28 +
 ...neficiaryTransferLimitExceededException.java |   30 +
 ...TransactionAmountLimitExceededException.java |   31 +
 .../InvalidAccountInformationException.java     |   32 +
 .../exception/InvalidBeneficiaryException.java  |   29 +
 .../AddSelfBeneficiariesTPTCommandHandler.java  |   46 +
 ...eleteSelfBeneficiariesTPTCommandHandler.java |   46 +
 ...pdateSelfBeneficiariesTPTCommandHandler.java |   46 +
 ...SelfBeneficiariesTPTReadPlatformService.java |   36 +
 ...BeneficiariesTPTReadPlatformServiceImpl.java |  222 ++++
 ...elfBeneficiariesTPTWritePlatformService.java |   32 +
 ...eneficiariesTPTWritePlatformServiceImpl.java |  212 ++++
 ...tomer_self_service_third_party_transfers.sql |   24 +
 32 files changed, 2620 insertions(+), 504 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/api-docs/apiLive.htm
----------------------------------------------------------------------
diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm
index c2fa328..3139b1a 100644
--- a/api-docs/apiLive.htm
+++ b/api-docs/apiLive.htm
@@ -3312,6 +3312,38 @@
                                                                <td></td>
                                                                <td></td>
                                                        </tr>
+                                                       <tr>
+                                                               <td><a 
href="#selfbentemplate">Beneficiary for Third Party Transfer</a></td>
+                                                               
<td>/self/beneficiaries/tpt/template</td>
+                                                               <td></td>
+                                                               <td><a 
href="#selfbentemplate">Beneficiary TPT Template</a></td>
+                                                               <td></td>
+                                                               <td></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td></td>
+                                                               
<td>/self/beneficiaries/tpt</td>
+                                                               <td><a 
href="#selfaddtpt">Add TPT Beneficiary</a></td>
+                                                               <td><a 
href="#selfgettpt">Get TPT Beneficiary List</a></td>
+                                                               <td><a 
href="#selfputtpt">Update TPT Beneficiary</a></td>
+                                                               <td><a 
href="#selfdeletetpt">Delete TPT Beneficiary</a></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td><a 
href="#selftpttransfertemplate">Third Party Account Transfers</a></td>
+                                                               
<td>self/accounttransfers/template?type="tpt"</td>
+                                                               <td></td>
+                                                               <td><a 
href="#selftpttransfertemplate">Third Party Account Transfer Template</a></td>
+                                                               <td></td>
+                                                               <td></td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td></td>
+                                                               
<td>self/accounttransfers?type="tpt"</td>
+                                                               <td><a 
href="#selftpttransfer">Third Party Account Transfer</a></td>
+                                                               <td></td>
+                                                               <td></td>
+                                                               <td></td>
+                                                       </tr>
                                                </table>
                                        </div>
                                </div>
@@ -42193,7 +42225,35 @@ GET 
https://DomainName/api/v1/self/savingsaccounts/{accountId}/charges/{savingsA
                </code>
                        <code class="method-response">
 {
-  "accountOptions": [
+  "fromAccountOptions": [
+       {
+               "accountId": 1,
+               "accountNo": "00000001",
+               "accountType": {
+                       "id": 2,
+                       "code": "accountType.savings",
+                       "value": "Savings Account"
+               },
+               "clientId": 1,
+               "clientName": "ABC",
+               "officeId": 1,
+               "officeName": "HEAD OFFICE"
+       },
+       {
+               "accountId": 5,
+               "accountNo": "00000005",
+               "accountType": {
+                       "id": 1,
+                       "code": "accountType.loan",
+                       "value": "Loan Account"
+               },
+               "clientId": 2,
+               "clientName": "XYZ",
+               "officeId": 3,
+               "officeName": "REGIONAL OFFICE"
+       }
+  ],
+ "toAccountOptions": [
        {
                "accountId": 1,
                "accountNo": "00000001",
@@ -42221,6 +42281,7 @@ GET 
https://DomainName/api/v1/self/savingsaccounts/{accountId}/charges/{savingsA
                "officeName": "REGIONAL OFFICE"
        }
   ]
+
 }
                        </code>
            </div>
@@ -42262,6 +42323,322 @@ No Request Body:
            </div>
        </div>
 
+       <a id="selfbentemplate" name="selfbentemplate" 
class="old-syle-anchor">&nbsp;</a>
+       <div class="method-section">
+           <div class="method-description">
+               <h2>Beneficiary Third Party Transfer Template</h2>
+               <p>Returns Account Type enumerations. Self User is expected to 
know office name and account number to be able to add beneficiary.</p>
+               <p>Example Requests:</p>
+               <div class=apiClick>/self/beneficiaries/tpt/template</div>
+           </div>
+           <div class="method-example">
+               <code class="method-declaration">GET 
https://DomainName/api/v1/self/beneficiaries/tpt/template
+               </code>
+                       <code class="method-response">
+    {
+        "accountTypeOptions":
+        [
+            {
+                "id": 2,
+                "code": "accountType.savings",
+                "value": "Savings Account"
+            },
+            {
+                "id": 1,
+                "code": "accountType.loan",
+                "value": "Loan Account"
+            }
+        ]
+    }
+                       </code>
+           </div>
+       </div>
+
+       <a id="selfaddtpt" name="selfaddtpt" class="old-syle-anchor">&nbsp;</a>
+       <div class="method-section">
+           <div class="method-description">
+               <h2>Add TPT Beneficiary</h2>
+               <p>Api to add third party beneficiary linked to current 
user.</p>
+               <p>Parameter Definitions</p>
+               <p>name : Nick name for beneficiary, should be unique for an 
self service user</p>
+               <p>officeName : Office Name of beneficiary(not id)</p>
+               <p>accountNumber : Account Number of beneficiary(not id)</p>
+               <p>transferLimit : Each transfer initiated to this account will 
not exceed this amount</p>
+               <p>Example Requests:</p>
+               <div class=apiClick>/self/beneficiaries/tpt</div>
+                       <table class=matrixHeading>
+                                               <tr class="matrixHeadingBG">
+                                                       <td><div 
class="fineractHeading2">Mandatory Fields</div></td>
+                                               </tr>
+                                               <tr class=alt>
+                                                       <td>name, officeName, 
accountNumber, accountType</td>
+                                               </tr>
+                                       </table>
+                                       <br/>
+                                       <table class=matrixHeading>
+                                               <tr class="matrixHeadingBG">
+                                                       <td><div 
class="fineractHeading2">Optional Fields</div></td>
+                                               </tr>
+                                               <tr class=alt>
+                                                       <td>transferLimit
+                                                       </td>
+                                               </tr>
+                                       </table>
+           </div>
+               
+           <div class="method-example">
+               <code class="method-declaration">POST 
https://DomainName/api/v1/self/beneficiaries/tpt
+               </code>
+                                       <code class="method-request">
+POST self/beneficiaries/tpt
+Content-Type: application/json
+Request Body:
+{
+    "locale": "en_GB",
+       "name": "beneficiary nick name",
+       "officeName": "HEAD OFFICE",
+       "accountNumber": "0000001",
+       "accountType": 1,
+       "transferLimit": 1000
+    
+}
+                                       </code>
+                                       <code class="method-response">
+{
+  "resourceId": 5
+}
+                       </code>
+           </div>
+       </div>
+
+       <a id="selfgettpt" name="selfgettpt" class="old-syle-anchor">&nbsp;</a>
+       <div class="method-section">
+           <div class="method-description">
+               <h2>Get All TPT Beneficiary</h2>
+               <p>Api to get all third party beneficiary linked to current 
user.</p>
+               <p>Example Requests:</p>
+               <div class=apiClick>/self/beneficiaries/tpt</div>
+           </div>
+               
+           <div class="method-example">
+               <code class="method-declaration">GET 
https://DomainName/api/v1/self/beneficiaries/tpt
+               </code>
+                                       <code class="method-request">
+GET self/beneficiaries/tpt
+Content-Type: application/json
+                                       </code>
+                                       <code class="method-response">
+{
+[
+  {
+    "id": 1,
+    "name": "Client2Savings",
+    "officeName": "Test Office",
+    "clientName": "FN2 LN2",
+    "accountType": {
+      "id": 2,
+      "code": "accountType.savings",
+      "value": "Savings Account"
+    },
+    "accountNumber": "000000002",
+    "transferLimit": 0
+  },
+  {
+    "id": 4,
+    "name": "Client2Loan",
+    "officeName": "Test Office",
+    "clientName": "FN2 LN2",
+    "accountType": {
+      "id": 1,
+      "code": "accountType.loan",
+      "value": "Loan Account"
+    },
+    "accountNumber": "000000002",
+    "transferLimit": 1000
+  }]
+}
+                       </code>
+           </div>
+       </div>
+
+       <a id="selfputtpt" name="selfputtpt" class="old-syle-anchor">&nbsp;</a>
+       <div class="method-section">
+           <div class="method-description">
+               <h2>Update TPT Beneficiary</h2>
+               <p>Api to update third party beneficiary linked to current 
user.</p>
+               <p>Example Requests:</p>
+               <div 
class=apiClick>/self/beneficiaries/tpt/{beneficiaryId}</div>
+                                       <br/>
+                                       <table class=matrixHeading>
+                                               <tr class="matrixHeadingBG">
+                                                       <td><div 
class="fineractHeading2">Optional Fields</div></td>
+                                               </tr>
+                                               <tr class=alt>
+                                                       <td>name, transferLimit
+                                                       </td>
+                                               </tr>
+                                       </table>
+           </div>
+               
+           <div class="method-example">
+               <code class="method-declaration">PUT 
https://DomainName/api/v1/self/beneficiaries/tpt/{beneficiaryId}
+               </code>
+                                       <code class="method-request">
+PUT self/beneficiaries/tpt/5
+Content-Type: application/json
+Request Body:
+{
+       "name": "beneficiary nick name",
+       "transferLimit": 1000
+    
+}
+                                       </code>
+                                       <code class="method-response">
+{
+  "resourceId": 5,
+  "changes": {
+    "transferLimit": 1000,
+    "name": "Client22"
+  }
+}
+                       </code>
+           </div>
+       </div>
+
+       <a id="selfdeletetpt" name="selfdeletetpt" 
class="old-syle-anchor">&nbsp;</a>
+       <div class="method-section">
+           <div class="method-description">
+               <h2>Delete TPT Beneficiary</h2>
+               <p>Api to delete third party beneficiary linked to current 
user.</p>
+               <p>Example Requests:</p>
+               <div 
class=apiClick>/self/beneficiaries/tpt/{beneficiaryId}</div>
+           </div>
+               
+           <div class="method-example">
+               <code class="method-declaration">DELETE 
https://DomainName/api/v1/self/beneficiaries/tpt/{beneficiaryId}
+               </code>
+                                       <code class="method-request">
+DELETE self/beneficiaries/tpt/5
+Content-Type: application/json
+                                       </code>
+                                       <code class="method-response">
+{
+  "resourceId": 5
+}
+                       </code>
+           </div>
+       </div>
+
+       <a id="selftpttransfertemplate" name="selftpttransfertemplate" 
class="old-syle-anchor">&nbsp;</a>
+       <div class="method-section">
+           <div class="method-description">
+               <h2>Third Party Account Transfer Template</h2>
+               <p>Returns list of loan/savings accounts that can be used for 
third party account transfer</p>
+               <p>Example Requests:</p>
+               <div 
class=apiClick>self/accounttransfers/template?type="tpt"</div>
+           </div>
+           <div class="method-example">
+               <code class="method-declaration">GET 
https://DomainName/api/v1/self/accounttransfers/template?type="tpt";
+               </code>
+                       <code class="method-response">
+{
+  "fromAccountOptions": [
+       {
+               "accountId": 1,
+               "accountNo": "00000001",
+               "accountType": {
+                       "id": 2,
+                       "code": "accountType.savings",
+                       "value": "Savings Account"
+               },
+               "clientId": 1,
+               "clientName": "ABC",
+               "officeId": 1,
+               "officeName": "HEAD OFFICE"
+       },
+       {
+               "accountId": 5,
+               "accountNo": "00000005",
+               "accountType": {
+                       "id": 1,
+                       "code": "accountType.loan",
+                       "value": "Loan Account"
+               },
+               "clientId": 2,
+               "clientName": "XYZ",
+               "officeId": 3,
+               "officeName": "REGIONAL OFFICE"
+       }
+  ],
+ "toAccountOptions": [
+       {
+               "accountId": 2,
+               "accountNo": "00000002",
+               "accountType": {
+                       "id": 2,
+                       "code": "accountType.savings",
+                       "value": "Savings Account"
+               },
+               "clientId": 2,
+               "clientName": "ABC",
+               "officeId": 1,
+               "officeName": "HEAD OFFICE"
+       },
+       {
+               "accountId": 6,
+               "accountNo": "00000006",
+               "accountType": {
+                       "id": 1,
+                       "code": "accountType.loan",
+                       "value": "Loan Account"
+               },
+               "clientId": 3,
+               "clientName": "XYZ",
+               "officeId": 4,
+               "officeName": "REGIONAL OFFICE"
+       }
+  ]
+
+}
+                       </code>
+           </div>
+       </div>
+
+       <a id="selftpttransfer" name="selftpttransfer" 
class="old-syle-anchor">&nbsp;</a>
+       <div class="method-section">
+           <div class="method-description">
+               <h2>Third Party Account Transfer</h2>
+               <p>Ability to create new third party transfer of monetary funds 
from one account to another.</p>
+           </div>
+           <div class="method-example">
+               <code class="method-declaration">POST 
https://DomainName/api/v1/self/accounttransfers?type="tpt";</code>
+               <code class="method-request">POST 
self/accounttransfers?type="tpt"
+Content-Type: application/json
+No Request Body:
+{
+"fromOfficeId": 1,
+"fromClientId": 1,
+"fromAccountType": 2,
+"fromAccountId": 1,
+"toOfficeId": 1,
+"toClientId": 2,
+"toAccountType": 2,
+"toAccountId": 2,
+"dateFormat": "dd MMMM yyyy",
+"locale": "en",
+"transferDate": "01 August 2011",
+"transferAmount": "112.45",
+"transferDescription": "A description of the transfer"
+}
+               </code>
+               <code class="method-response">
+{
+  "savingsId": 1,
+  "resourceId": 1
+}
+               </code>
+           </div>
+       </div>
                        <!-- end of Customer Self Service APIs-->
         </div>
                <!-- main-content-wrapper -->

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
 
b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
index bd13574..5751e0e 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
@@ -2702,4 +2702,29 @@ public class CommandWrapperBuilder {
         this.href = "/savingsaccounts/" + accountId + 
"?commad=updateTaxWithHoldTax";
         return this;
     }
+
+       public CommandWrapperBuilder addSelfServiceBeneficiaryTPT() {
+        this.actionName = "CREATE";
+        this.entityName = "SSBENEFICIARYTPT";
+        this.entityId = null;
+        this.href = "/self/beneficiaries/tpt";
+        return this;
+       }
+
+       public CommandWrapperBuilder updateSelfServiceBeneficiaryTPT(final Long 
beneficiaryId) {
+        this.actionName = "UPDATE";
+        this.entityName = "SSBENEFICIARYTPT";
+        this.entityId = beneficiaryId;
+        this.href = "/self/beneficiaries/tpt/"+beneficiaryId;
+        return this;
+       }
+
+       public CommandWrapperBuilder deleteSelfServiceBeneficiaryTPT(final Long 
beneficiaryId) {
+        this.actionName = "DELETE";
+        this.entityName = "SSBENEFICIARYTPT";
+        this.entityId = beneficiaryId;
+        this.href = "/self/beneficiaries/tpt/"+beneficiaryId;
+        return this;
+       }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java
index 75aefb2..58494c2 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java
@@ -79,4 +79,8 @@ public interface ConfigurationDomainService {
     
     boolean isChangeEmiIfRepaymentDateSameAsDisbursementDateEnabled();
     
+    boolean isDailyTPTLimitEnabled();
+    
+    Long getDailyTPTLimit();
+    
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java
index 356d098..67ebdc5 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java
@@ -19,6 +19,7 @@
 package org.apache.fineract.infrastructure.configuration.domain;
 
 import java.util.Date;
+
 import org.apache.commons.lang.StringUtils;
 import org.apache.fineract.infrastructure.cache.domain.CacheType;
 import org.apache.fineract.infrastructure.cache.domain.PlatformCache;
@@ -209,6 +210,7 @@ public class ConfigurationDomainServiceJpa implements 
ConfigurationDomainService
         return defaultValue;
     }
 
+    @Override
     public boolean isBackdatePenaltiesEnabled() {
         final String propertyName = "backdate-penalties-enabled";
         final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
@@ -263,5 +265,19 @@ public class ConfigurationDomainServiceJpa implements 
ConfigurationDomainService
         return property.isEnabled();
     }
 
+       @Override
+       public boolean isDailyTPTLimitEnabled() {
+        final String propertyName = "daily-tpt-limit";
+        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        return property.isEnabled();
+       }
+
+       @Override
+       public Long getDailyTPTLimit() {
+        final String propertyName = "daily-tpt-limit";
+        final GlobalConfigurationProperty property = 
this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+        return property.getValue();
+       }
+
   
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/TenantDatabaseUpgradeService.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/TenantDatabaseUpgradeService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/TenantDatabaseUpgradeService.java
index 8bf9199..740dcb5 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/TenantDatabaseUpgradeService.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/TenantDatabaseUpgradeService.java
@@ -74,7 +74,7 @@ public class TenantDatabaseUpgradeService {
                     flyway.migrate();
                 } catch (FlywayException e) {
                     String betterMessage = e.getMessage() + "; for Tenant DB 
URL: " + connectionProtocol + ", username: "
-                            + connection.getSchemaPassword();
+                            + connection.getSchemaUsername();
                     throw new FlywayException(betterMessage, e.getCause());
                 }
             }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/SchedularWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/SchedularWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/SchedularWritePlatformServiceJpaRepositoryImpl.java
index f4ac6ac..7e5d5de 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/SchedularWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/SchedularWritePlatformServiceJpaRepositoryImpl.java
@@ -136,11 +136,11 @@ public class 
SchedularWritePlatformServiceJpaRepositoryImpl implements Schedular
         boolean isStopExecution = false;
         final ScheduledJobDetail scheduledJobDetail = 
this.scheduledJobDetailsRepository.findByJobKeyWithLock(jobKey);
         if (scheduledJobDetail.isCurrentlyRunning()
-                || (triggerType == SchedulerServiceConstants.TRIGGER_TYPE_CRON 
&& (scheduledJobDetail.getNextRunTime().after(new Date())))) {
+                || 
(triggerType.equals(SchedulerServiceConstants.TRIGGER_TYPE_CRON) && 
(scheduledJobDetail.getNextRunTime().after(new Date())))) {
             isStopExecution = true;
         }
         final SchedulerDetail schedulerDetail = retriveSchedulerDetail();
-        if (triggerType == SchedulerServiceConstants.TRIGGER_TYPE_CRON && 
schedulerDetail.isSuspended()) {
+        if (triggerType.equals(SchedulerServiceConstants.TRIGGER_TYPE_CRON) && 
schedulerDetail.isSuspended()) {
             scheduledJobDetail.updateTriggerMisfired(true);
             isStopExecution = true;
         } else if (!isStopExecution) {

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformService.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformService.java
index c053b01..0434261 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformService.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformService.java
@@ -18,12 +18,14 @@
  */
 package org.apache.fineract.portfolio.account.service;
 
+import java.math.BigDecimal;
 import java.util.Collection;
 
 import org.apache.fineract.infrastructure.core.service.Page;
 import org.apache.fineract.infrastructure.core.service.SearchParameters;
 import org.apache.fineract.portfolio.account.PortfolioAccountType;
 import org.apache.fineract.portfolio.account.data.AccountTransferData;
+import org.joda.time.LocalDate;
 
 public interface AccountTransfersReadPlatformService {
 
@@ -42,4 +44,7 @@ public interface AccountTransfersReadPlatformService {
     
     AccountTransferData retrieveRefundByTransferTemplate(Long fromOfficeId, 
Long fromClientId, Long fromAccountId, Integer fromAccountType,
             Long toOfficeId, Long toClientId, Long toAccountId, Integer 
toAccountType);
+
+       BigDecimal getTotalTransactionAmount(Long accountId, Integer 
accountType,
+                       LocalDate transactionDate);
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformServiceImpl.java
index 9dbe4c9..08af091 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformServiceImpl.java
@@ -45,6 +45,8 @@ import 
org.apache.fineract.portfolio.account.exception.AccountTransferNotFoundEx
 import org.apache.fineract.portfolio.client.data.ClientData;
 import org.apache.fineract.portfolio.client.service.ClientReadPlatformService;
 import org.joda.time.LocalDate;
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.DateTimeFormatter;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.dao.EmptyResultDataAccessException;
 import org.springframework.jdbc.core.JdbcTemplate;
@@ -53,485 +55,643 @@ import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
 @Service
-public class AccountTransfersReadPlatformServiceImpl implements 
AccountTransfersReadPlatformService {
-
-    private final JdbcTemplate jdbcTemplate;
-    private final ClientReadPlatformService clientReadPlatformService;
-    private final OfficeReadPlatformService officeReadPlatformService;
-    private final PortfolioAccountReadPlatformService 
portfolioAccountReadPlatformService;
-
-    // mapper
-    private final AccountTransfersMapper accountTransfersMapper;
-
-    // pagination
-    private final PaginationHelper<AccountTransferData> paginationHelper = new 
PaginationHelper<>();
-
-    @Autowired
-    public AccountTransfersReadPlatformServiceImpl(final RoutingDataSource 
dataSource,
-            final ClientReadPlatformService clientReadPlatformService, final 
OfficeReadPlatformService officeReadPlatformService,
-            final PortfolioAccountReadPlatformService 
portfolioAccountReadPlatformService) {
-        this.jdbcTemplate = new JdbcTemplate(dataSource);
-        this.clientReadPlatformService = clientReadPlatformService;
-        this.officeReadPlatformService = officeReadPlatformService;
-        this.portfolioAccountReadPlatformService = 
portfolioAccountReadPlatformService;
-
-        this.accountTransfersMapper = new AccountTransfersMapper();
-    }
-
-    @Override
-    public AccountTransferData retrieveTemplate(final Long fromOfficeId, final 
Long fromClientId, final Long fromAccountId,
-            final Integer fromAccountType, final Long toOfficeId, final Long 
toClientId, final Long toAccountId, final Integer toAccountType) {
-
-        final EnumOptionData loanAccountType = 
AccountTransferEnumerations.accountType(PortfolioAccountType.LOAN);
-        final EnumOptionData savingsAccountType = 
AccountTransferEnumerations.accountType(PortfolioAccountType.SAVINGS);
-
-        final Integer mostRelevantFromAccountType = fromAccountType;
-        final Collection<EnumOptionData> fromAccountTypeOptions = 
Arrays.asList(savingsAccountType, loanAccountType);
-        final Collection<EnumOptionData> toAccountTypeOptions;
-        if (mostRelevantFromAccountType != null && mostRelevantFromAccountType 
== 1) {
-            // overpaid loan amt transfer to savings account
-            toAccountTypeOptions = Arrays.asList(savingsAccountType);
-        } else {
-            toAccountTypeOptions = Arrays.asList(loanAccountType, 
savingsAccountType);
-        }
-        final Integer mostRelevantToAccountType = toAccountType;
-
-        final EnumOptionData fromAccountTypeData = 
AccountTransferEnumerations.accountType(mostRelevantFromAccountType);
-        final EnumOptionData toAccountTypeData = 
AccountTransferEnumerations.accountType(mostRelevantToAccountType);
-
-        // from settings
-        OfficeData fromOffice = null;
-        ClientData fromClient = null;
-        PortfolioAccountData fromAccount = null;
-
-        OfficeData toOffice = null;
-        ClientData toClient = null;
-        PortfolioAccountData toAccount = null;
-
-        // template
-        Collection<PortfolioAccountData> fromAccountOptions = null;
-        Collection<PortfolioAccountData> toAccountOptions = null;
-
-        Long mostRelevantFromOfficeId = fromOfficeId;
-        Long mostRelevantFromClientId = fromClientId;
-
-        Long mostRelevantToOfficeId = toOfficeId;
-        Long mostRelevantToClientId = toClientId;
-
-        if (fromAccountId != null) {
-            Integer accountType;
-            if (mostRelevantFromAccountType == 1) {
-                accountType = PortfolioAccountType.LOAN.getValue();
-            } else {
-                accountType = PortfolioAccountType.SAVINGS.getValue();
-            }
-            fromAccount = 
this.portfolioAccountReadPlatformService.retrieveOne(fromAccountId, 
accountType);
-
-            // override provided fromClient with client of account
-            mostRelevantFromClientId = fromAccount.clientId();
-        }
-
-        if (mostRelevantFromClientId != null) {
-            fromClient = 
this.clientReadPlatformService.retrieveOne(mostRelevantFromClientId);
-            mostRelevantFromOfficeId = fromClient.officeId();
-            long[] loanStatus = null;
-            if (mostRelevantFromAccountType == 1) {
-                loanStatus = new long[] { 300, 700 };
-            }
-            PortfolioAccountDTO portfolioAccountDTO = new 
PortfolioAccountDTO(mostRelevantFromAccountType, mostRelevantFromClientId,
-                    loanStatus);
-            fromAccountOptions = 
this.portfolioAccountReadPlatformService.retrieveAllForLookup(portfolioAccountDTO);
-        }
-
-        Collection<OfficeData> fromOfficeOptions = null;
-        Collection<ClientData> fromClientOptions = null;
-        if (mostRelevantFromOfficeId != null) {
-            fromOffice = 
this.officeReadPlatformService.retrieveOffice(mostRelevantFromOfficeId);
-            fromOfficeOptions = 
this.officeReadPlatformService.retrieveAllOfficesForDropdown();
-            fromClientOptions = 
this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantFromOfficeId);
-        }
-
-        // defaults
-        final LocalDate transferDate = DateUtils.getLocalDateOfTenant();
-        Collection<OfficeData> toOfficeOptions = fromOfficeOptions;
-        Collection<ClientData> toClientOptions = null;
-
-        if (toAccountId != null && fromAccount != null) {
-            toAccount = 
this.portfolioAccountReadPlatformService.retrieveOne(toAccountId, 
mostRelevantToAccountType,
-                    fromAccount.currencyCode());
-            mostRelevantToClientId = toAccount.clientId();
-        }
-
-        if (mostRelevantToClientId != null) {
-            toClient = 
this.clientReadPlatformService.retrieveOne(mostRelevantToClientId);
-            mostRelevantToOfficeId = toClient.officeId();
-
-            toClientOptions = 
this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
-
-            toAccountOptions = retrieveToAccounts(fromAccount, 
mostRelevantToAccountType, mostRelevantToClientId);
-        }
-
-        if (mostRelevantToOfficeId != null) {
-            toOffice = 
this.officeReadPlatformService.retrieveOffice(mostRelevantToOfficeId);
-            toOfficeOptions = 
this.officeReadPlatformService.retrieveAllOfficesForDropdown();
-
-            toClientOptions = 
this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
-            if (toClientOptions != null && toClientOptions.size() == 1) {
-                toClient = new ArrayList<>(toClientOptions).get(0);
-
-                toAccountOptions = retrieveToAccounts(fromAccount, 
mostRelevantToAccountType, mostRelevantToClientId);
-            }
-        }
-
-        return AccountTransferData.template(fromOffice, fromClient, 
fromAccountTypeData, fromAccount, transferDate, toOffice, toClient,
-                toAccountTypeData, toAccount, fromOfficeOptions, 
fromClientOptions, fromAccountTypeOptions, fromAccountOptions,
-                toOfficeOptions, toClientOptions, toAccountTypeOptions, 
toAccountOptions);
-    }
-
-    private Collection<PortfolioAccountData> retrieveToAccounts(final 
PortfolioAccountData excludeThisAccountFromOptions,
-            final Integer toAccountType, final Long toClientId) {
-
-        final String currencyCode = excludeThisAccountFromOptions != null ? 
excludeThisAccountFromOptions.currencyCode() : null;
-
-        PortfolioAccountDTO portfolioAccountDTO = new 
PortfolioAccountDTO(toAccountType, toClientId, currencyCode, null, null);
-        Collection<PortfolioAccountData> accountOptions = 
this.portfolioAccountReadPlatformService
-                .retrieveAllForLookup(portfolioAccountDTO);
-        if (!CollectionUtils.isEmpty(accountOptions)) {
-            accountOptions.remove(excludeThisAccountFromOptions);
-        } else {
-            accountOptions = null;
-        }
-
-        return accountOptions;
-    }
-
-    @Override
-    public Page<AccountTransferData> retrieveAll(final SearchParameters 
searchParameters, final Long accountDetailId) {
-
-        final StringBuilder sqlBuilder = new StringBuilder(200);
-        sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
-        sqlBuilder.append(this.accountTransfersMapper.schema());
-        Object[] finalObjectArray = {};
-        if (accountDetailId != null) {
-            sqlBuilder.append(" where att.account_transfer_details_id=?");
-            finalObjectArray = new Object[] { accountDetailId };
-        }
-
-        if (searchParameters.isOrderByRequested()) {
-            sqlBuilder.append(" order by 
").append(searchParameters.getOrderBy());
-
-            if (searchParameters.isSortOrderProvided()) {
-                sqlBuilder.append(' ').append(searchParameters.getSortOrder());
-            }
-        }
-
-        if (searchParameters.isLimited()) {
-            sqlBuilder.append(" limit ").append(searchParameters.getLimit());
-            if (searchParameters.isOffset()) {
-                sqlBuilder.append(" offset 
").append(searchParameters.getOffset());
-            }
-        }
-
-        final String sqlCountRows = "SELECT FOUND_ROWS()";
-        return this.paginationHelper.fetchPage(this.jdbcTemplate, 
sqlCountRows, sqlBuilder.toString(), finalObjectArray,
-                this.accountTransfersMapper);
-    }
-
-    @Override
-    public AccountTransferData retrieveOne(final Long transferId) {
-
-        try {
-            final String sql = "select " + 
this.accountTransfersMapper.schema() + " where att.id = ?";
-
-            return this.jdbcTemplate.queryForObject(sql, 
this.accountTransfersMapper, new Object[] { transferId });
-        } catch (final EmptyResultDataAccessException e) {
-            throw new AccountTransferNotFoundException(transferId);
-        }
-    }
-
-    @Override
-    public Collection<Long> fetchPostInterestTransactionIds(final Long 
accountId) {
-        final String sql = "select att.from_savings_transaction_id from 
m_account_transfer_transaction att inner join m_account_transfer_details atd on 
atd.id = att.account_transfer_details_id where atd.from_savings_account_id=? 
and att.is_reversed =0 and atd.transfer_type = ?";
-
-        final List<Long> transactionId = this.jdbcTemplate.queryForList(sql, 
Long.class, accountId,
-                AccountTransferType.INTEREST_TRANSFER.getValue());
-
-        return transactionId;
-    }
-
-    private static final class AccountTransfersMapper implements 
RowMapper<AccountTransferData> {
-
-        private final String schemaSql;
-
-        public AccountTransfersMapper() {
-            final StringBuilder sqlBuilder = new StringBuilder(400);
-            sqlBuilder.append("att.id as id, att.is_reversed as isReversed,");
-            sqlBuilder.append("att.transaction_date as transferDate, 
att.amount as transferAmount,");
-            sqlBuilder.append("att.description as transferDescription,");
-            sqlBuilder.append("att.currency_code as currencyCode, 
att.currency_digits as currencyDigits,");
-            sqlBuilder.append("att.currency_multiplesof as inMultiplesOf, ");
-            sqlBuilder.append("curr.name as currencyName, 
curr.internationalized_name_code as currencyNameCode, ");
-            sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol, 
");
-            sqlBuilder.append("fromoff.id as fromOfficeId, fromoff.name as 
fromOfficeName,");
-            sqlBuilder.append("tooff.id as toOfficeId, tooff.name as 
toOfficeName,");
-            sqlBuilder.append("fromclient.id as fromClientId, 
fromclient.display_name as fromClientName,");
-            sqlBuilder.append("toclient.id as toClientId, 
toclient.display_name as toClientName,");
-            sqlBuilder.append("fromsavacc.id as fromSavingsAccountId, 
fromsavacc.account_no as fromSavingsAccountNo,");
-            sqlBuilder.append("fromloanacc.id as fromLoanAccountId, 
fromloanacc.account_no as fromLoanAccountNo,");
-            sqlBuilder.append("tosavacc.id as toSavingsAccountId, 
tosavacc.account_no as toSavingsAccountNo,");
-            sqlBuilder.append("toloanacc.id as toLoanAccountId, 
toloanacc.account_no as toLoanAccountNo,");
-            sqlBuilder.append("fromsavtran.id as 
fromSavingsAccountTransactionId,");
-            sqlBuilder.append("fromsavtran.transaction_type_enum as 
fromSavingsAccountTransactionType,");
-            sqlBuilder.append("tosavtran.id as 
toSavingsAccountTransactionId,");
-            sqlBuilder.append("tosavtran.transaction_type_enum as 
toSavingsAccountTransactionType");
-            sqlBuilder.append(" FROM m_account_transfer_transaction att ");
-            sqlBuilder.append("left join m_account_transfer_details atd on 
atd.id = att.account_transfer_details_id ");
-            sqlBuilder.append("join m_currency curr on curr.code = 
att.currency_code ");
-            sqlBuilder.append("join m_office fromoff on fromoff.id = 
atd.from_office_id ");
-            sqlBuilder.append("join m_office tooff on tooff.id = 
atd.to_office_id ");
-            sqlBuilder.append("join m_client fromclient on fromclient.id = 
atd.from_client_id ");
-            sqlBuilder.append("join m_client toclient on toclient.id = 
atd.to_client_id ");
-            sqlBuilder.append("left join m_savings_account fromsavacc on 
fromsavacc.id = atd.from_savings_account_id ");
-            sqlBuilder.append("left join m_loan fromloanacc on fromloanacc.id 
= atd.from_loan_account_id ");
-            sqlBuilder.append("left join m_savings_account tosavacc on 
tosavacc.id = atd.to_savings_account_id ");
-            sqlBuilder.append("left join m_loan toloanacc on toloanacc.id = 
atd.to_loan_account_id ");
-            sqlBuilder.append("left join m_savings_account_transaction 
fromsavtran on fromsavtran.id = att.from_savings_transaction_id ");
-            sqlBuilder.append("left join m_savings_account_transaction 
tosavtran on tosavtran.id = att.to_savings_transaction_id ");
-            sqlBuilder.append("left join m_loan_transaction fromloantran on 
fromloantran.id = att.from_savings_transaction_id ");
-            sqlBuilder.append("left join m_loan_transaction toloantran on 
toloantran.id = att.to_savings_transaction_id ");
-
-            this.schemaSql = sqlBuilder.toString();
-        }
-
-        public String schema() {
-            return this.schemaSql;
-        }
-
-        @Override
-        public AccountTransferData mapRow(final ResultSet rs, 
@SuppressWarnings("unused") final int rowNum) throws SQLException {
-
-            final Long id = rs.getLong("id");
-            final boolean reversed = rs.getBoolean("isReversed");
-
-            final LocalDate transferDate = JdbcSupport.getLocalDate(rs, 
"transferDate");
-            final BigDecimal transferAmount = 
JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "transferAmount");
-            final String transferDescription = 
rs.getString("transferDescription");
-
-            final String currencyCode = rs.getString("currencyCode");
-            final String currencyName = rs.getString("currencyName");
-            final String currencyNameCode = rs.getString("currencyNameCode");
-            final String currencyDisplaySymbol = 
rs.getString("currencyDisplaySymbol");
-            final Integer currencyDigits = JdbcSupport.getInteger(rs, 
"currencyDigits");
-            final Integer inMultiplesOf = JdbcSupport.getInteger(rs, 
"inMultiplesOf");
-            final CurrencyData currency = new CurrencyData(currencyCode, 
currencyName, currencyDigits, inMultiplesOf,
-                    currencyDisplaySymbol, currencyNameCode);
-
-            final Long fromOfficeId = JdbcSupport.getLong(rs, "fromOfficeId");
-            final String fromOfficeName = rs.getString("fromOfficeName");
-            final OfficeData fromOffice = OfficeData.dropdown(fromOfficeId, 
fromOfficeName, null);
-
-            final Long toOfficeId = JdbcSupport.getLong(rs, "toOfficeId");
-            final String toOfficeName = rs.getString("toOfficeName");
-            final OfficeData toOffice = OfficeData.dropdown(toOfficeId, 
toOfficeName, null);
-
-            final Long fromClientId = JdbcSupport.getLong(rs, "fromClientId");
-            final String fromClientName = rs.getString("fromClientName");
-            final ClientData fromClient = ClientData.lookup(fromClientId, 
fromClientName, fromOfficeId, fromOfficeName);
-
-            final Long toClientId = JdbcSupport.getLong(rs, "toClientId");
-            final String toClientName = rs.getString("toClientName");
-            final ClientData toClient = ClientData.lookup(toClientId, 
toClientName, toOfficeId, toOfficeName);
-
-            final Long fromSavingsAccountId = JdbcSupport.getLong(rs, 
"fromSavingsAccountId");
-            final String fromSavingsAccountNo = 
rs.getString("fromSavingsAccountNo");
-            final Long fromLoanAccountId = JdbcSupport.getLong(rs, 
"fromLoanAccountId");
-            final String fromLoanAccountNo = rs.getString("fromLoanAccountNo");
-            PortfolioAccountData fromAccount = null;
-            EnumOptionData fromAccountType = null;
-            if (fromSavingsAccountId != null) {
-                fromAccount = 
PortfolioAccountData.lookup(fromSavingsAccountId, fromSavingsAccountNo);
-                fromAccountType = 
AccountTransferEnumerations.accountType(PortfolioAccountType.SAVINGS);
-            } else if (fromLoanAccountId != null) {
-                fromAccount = PortfolioAccountData.lookup(fromLoanAccountId, 
fromLoanAccountNo);
-                fromAccountType = 
AccountTransferEnumerations.accountType(PortfolioAccountType.LOAN);
-            }
-
-            PortfolioAccountData toAccount = null;
-            EnumOptionData toAccountType = null;
-            final Long toSavingsAccountId = JdbcSupport.getLong(rs, 
"toSavingsAccountId");
-            final String toSavingsAccountNo = 
rs.getString("toSavingsAccountNo");
-            final Long toLoanAccountId = JdbcSupport.getLong(rs, 
"toLoanAccountId");
-            final String toLoanAccountNo = rs.getString("toLoanAccountNo");
-
-            if (toSavingsAccountId != null) {
-                toAccount = PortfolioAccountData.lookup(toSavingsAccountId, 
toSavingsAccountNo);
-                toAccountType = 
AccountTransferEnumerations.accountType(PortfolioAccountType.SAVINGS);
-            } else if (toLoanAccountId != null) {
-                toAccount = PortfolioAccountData.lookup(toLoanAccountId, 
toLoanAccountNo);
-                toAccountType = 
AccountTransferEnumerations.accountType(PortfolioAccountType.LOAN);
-            }
-
-            return AccountTransferData.instance(id, reversed, transferDate, 
currency, transferAmount, transferDescription, fromOffice,
-                    toOffice, fromClient, toClient, fromAccountType, 
fromAccount, toAccountType, toAccount);
-        }
-    }
-
-    @Override
-    public boolean isAccountTransfer(final Long transactionId, final 
PortfolioAccountType accountType) {
-        final StringBuilder sql = new StringBuilder("select count(*) from 
m_account_transfer_transaction at where ");
-        if (accountType.isLoanAccount()) {
-            
sql.append("at.from_loan_transaction_id=").append(transactionId).append(" or 
at.to_loan_transaction_id=").append(transactionId);
-        } else {
-            
sql.append("at.from_savings_transaction_id=").append(transactionId).append(" or 
at.to_savings_transaction_id=")
-                    .append(transactionId);
-        }
-
-        @SuppressWarnings("deprecation")
-        final int count = this.jdbcTemplate.queryForInt(sql.toString());
-        return count > 0;
-    }
-
-    @Override
-    public Page<AccountTransferData> retrieveByStandingInstruction(final Long 
id, final SearchParameters searchParameters) {
-
-        final StringBuilder sqlBuilder = new StringBuilder(200);
-        sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
-        sqlBuilder
-                .append(this.accountTransfersMapper.schema())
-                .append(" join m_account_transfer_standing_instructions atsi 
on atsi.account_transfer_details_id = att.account_transfer_details_id ");
-        sqlBuilder.append(" where atsi.id = ?");
-
-        if (searchParameters != null) {
-            if (searchParameters.isOrderByRequested()) {
-                sqlBuilder.append(" order by 
").append(searchParameters.getOrderBy());
-
-                if (searchParameters.isSortOrderProvided()) {
-                    sqlBuilder.append(' 
').append(searchParameters.getSortOrder());
-                }
-            }
-
-            if (searchParameters.isLimited()) {
-                sqlBuilder.append(" limit 
").append(searchParameters.getLimit());
-                if (searchParameters.isOffset()) {
-                    sqlBuilder.append(" offset 
").append(searchParameters.getOffset());
-                }
-            }
-        }
-
-        final Object[] finalObjectArray = { id };
-        final String sqlCountRows = "SELECT FOUND_ROWS()";
-        return this.paginationHelper.fetchPage(this.jdbcTemplate, 
sqlCountRows, sqlBuilder.toString(), finalObjectArray,
-                this.accountTransfersMapper);
-    }
-
-    @Override
-    public AccountTransferData retrieveRefundByTransferTemplate(final Long 
fromOfficeId, final Long fromClientId, final Long fromAccountId,
-            final Integer fromAccountType, final Long toOfficeId, final Long 
toClientId, final Long toAccountId, final Integer toAccountType) {
-        // TODO Auto-generated method stub
-        final EnumOptionData loanAccountType = 
AccountTransferEnumerations.accountType(PortfolioAccountType.LOAN);
-        final EnumOptionData savingsAccountType = 
AccountTransferEnumerations.accountType(PortfolioAccountType.SAVINGS);
-
-        final Integer mostRelevantFromAccountType = fromAccountType;
-        final Collection<EnumOptionData> fromAccountTypeOptions = 
Arrays.asList(savingsAccountType, loanAccountType);
-        final Collection<EnumOptionData> toAccountTypeOptions;
-        if (mostRelevantFromAccountType == 1) {
-            // overpaid loan amt transfer to savings account
-            toAccountTypeOptions = Arrays.asList(savingsAccountType);
-        } else {
-            toAccountTypeOptions = Arrays.asList(loanAccountType, 
savingsAccountType);
-        }
-        final Integer mostRelevantToAccountType = toAccountType;
-
-        final EnumOptionData fromAccountTypeData = 
AccountTransferEnumerations.accountType(mostRelevantFromAccountType);
-        final EnumOptionData toAccountTypeData = 
AccountTransferEnumerations.accountType(mostRelevantToAccountType);
-
-        // from settings
-        OfficeData fromOffice = null;
-        ClientData fromClient = null;
-        PortfolioAccountData fromAccount = null;
-
-        OfficeData toOffice = null;
-        ClientData toClient = null;
-        PortfolioAccountData toAccount = null;
-
-        // template
-        Collection<PortfolioAccountData> fromAccountOptions = null;
-        Collection<PortfolioAccountData> toAccountOptions = null;
-
-        Long mostRelevantFromOfficeId = fromOfficeId;
-        Long mostRelevantFromClientId = fromClientId;
-
-        Long mostRelevantToOfficeId = toOfficeId;
-        Long mostRelevantToClientId = toClientId;
-
-        if (fromAccountId != null) {
-            Integer accountType;
-            if (mostRelevantFromAccountType == 1) {
-                accountType = PortfolioAccountType.LOAN.getValue();
-            } else {
-                accountType = PortfolioAccountType.SAVINGS.getValue();
-            }
-            fromAccount = 
this.portfolioAccountReadPlatformService.retrieveOneByPaidInAdvance(fromAccountId,
 accountType);
-
-            // override provided fromClient with client of account
-            mostRelevantFromClientId = fromAccount.clientId();
-        }
-
-        if (mostRelevantFromClientId != null) {
-            fromClient = 
this.clientReadPlatformService.retrieveOne(mostRelevantFromClientId);
-            mostRelevantFromOfficeId = fromClient.officeId();
-            long[] loanStatus = null;
-            if (mostRelevantFromAccountType == 1) {
-                loanStatus = new long[] { 300, 700 };
-            }
-            PortfolioAccountDTO portfolioAccountDTO = new 
PortfolioAccountDTO(mostRelevantFromAccountType, mostRelevantFromClientId,
-                    loanStatus);
-            fromAccountOptions = 
this.portfolioAccountReadPlatformService.retrieveAllForLookup(portfolioAccountDTO);
-        }
-
-        Collection<OfficeData> fromOfficeOptions = null;
-        Collection<ClientData> fromClientOptions = null;
-        if (mostRelevantFromOfficeId != null) {
-            fromOffice = 
this.officeReadPlatformService.retrieveOffice(mostRelevantFromOfficeId);
-            fromOfficeOptions = 
this.officeReadPlatformService.retrieveAllOfficesForDropdown();
-            fromClientOptions = 
this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantFromOfficeId);
-        }
-
-        // defaults
-        final LocalDate transferDate = DateUtils.getLocalDateOfTenant();
-        Collection<OfficeData> toOfficeOptions = fromOfficeOptions;
-        Collection<ClientData> toClientOptions = null;
-
-        if (toAccountId != null && fromAccount != null) {
-            toAccount = 
this.portfolioAccountReadPlatformService.retrieveOne(toAccountId, 
mostRelevantToAccountType,
-                    fromAccount.currencyCode());
-            mostRelevantToClientId = toAccount.clientId();
-        }
-
-        if (mostRelevantToClientId != null) {
-            toClient = 
this.clientReadPlatformService.retrieveOne(mostRelevantToClientId);
-            mostRelevantToOfficeId = toClient.officeId();
-
-            toClientOptions = 
this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
-
-            toAccountOptions = retrieveToAccounts(fromAccount, 
mostRelevantToAccountType, mostRelevantToClientId);
-        }
-
-        if (mostRelevantToOfficeId != null) {
-            toOffice = 
this.officeReadPlatformService.retrieveOffice(mostRelevantToOfficeId);
-            toOfficeOptions = 
this.officeReadPlatformService.retrieveAllOfficesForDropdown();
-
-            toClientOptions = 
this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
-            if (toClientOptions != null && toClientOptions.size() == 1) {
-                toClient = new ArrayList<>(toClientOptions).get(0);
-
-                toAccountOptions = retrieveToAccounts(fromAccount, 
mostRelevantToAccountType, mostRelevantToClientId);
-            }
-        }
-
-        return AccountTransferData.template(fromOffice, fromClient, 
fromAccountTypeData, fromAccount, transferDate, toOffice, toClient,
-                toAccountTypeData, toAccount, fromOfficeOptions, 
fromClientOptions, fromAccountTypeOptions, fromAccountOptions,
-                toOfficeOptions, toClientOptions, toAccountTypeOptions, 
toAccountOptions);
-    }
+public class AccountTransfersReadPlatformServiceImpl implements
+               AccountTransfersReadPlatformService {
+
+       private final JdbcTemplate jdbcTemplate;
+       private final ClientReadPlatformService clientReadPlatformService;
+       private final OfficeReadPlatformService officeReadPlatformService;
+       private final PortfolioAccountReadPlatformService 
portfolioAccountReadPlatformService;
+
+       // mapper
+       private final AccountTransfersMapper accountTransfersMapper;
+
+       // pagination
+       private final PaginationHelper<AccountTransferData> paginationHelper = 
new PaginationHelper<>();
+       private final DateTimeFormatter formatter = DateTimeFormat
+                       .forPattern("yyyy-MM-dd");
+
+       @Autowired
+       public AccountTransfersReadPlatformServiceImpl(
+                       final RoutingDataSource dataSource,
+                       final ClientReadPlatformService 
clientReadPlatformService,
+                       final OfficeReadPlatformService 
officeReadPlatformService,
+                       final PortfolioAccountReadPlatformService 
portfolioAccountReadPlatformService) {
+               this.jdbcTemplate = new JdbcTemplate(dataSource);
+               this.clientReadPlatformService = clientReadPlatformService;
+               this.officeReadPlatformService = officeReadPlatformService;
+               this.portfolioAccountReadPlatformService = 
portfolioAccountReadPlatformService;
+
+               this.accountTransfersMapper = new AccountTransfersMapper();
+       }
+
+       @Override
+       public AccountTransferData retrieveTemplate(final Long fromOfficeId,
+                       final Long fromClientId, final Long fromAccountId,
+                       final Integer fromAccountType, final Long toOfficeId,
+                       final Long toClientId, final Long toAccountId,
+                       final Integer toAccountType) {
+
+               final EnumOptionData loanAccountType = 
AccountTransferEnumerations
+                               .accountType(PortfolioAccountType.LOAN);
+               final EnumOptionData savingsAccountType = 
AccountTransferEnumerations
+                               .accountType(PortfolioAccountType.SAVINGS);
+
+               final Integer mostRelevantFromAccountType = fromAccountType;
+               final Collection<EnumOptionData> fromAccountTypeOptions = Arrays
+                               .asList(savingsAccountType, loanAccountType);
+               final Collection<EnumOptionData> toAccountTypeOptions;
+               if (mostRelevantFromAccountType != null
+                               && mostRelevantFromAccountType == 1) {
+                       // overpaid loan amt transfer to savings account
+                       toAccountTypeOptions = 
Arrays.asList(savingsAccountType);
+               } else {
+                       toAccountTypeOptions = Arrays.asList(loanAccountType,
+                                       savingsAccountType);
+               }
+               final Integer mostRelevantToAccountType = toAccountType;
+
+               final EnumOptionData fromAccountTypeData = 
AccountTransferEnumerations
+                               .accountType(mostRelevantFromAccountType);
+               final EnumOptionData toAccountTypeData = 
AccountTransferEnumerations
+                               .accountType(mostRelevantToAccountType);
+
+               // from settings
+               OfficeData fromOffice = null;
+               ClientData fromClient = null;
+               PortfolioAccountData fromAccount = null;
+
+               OfficeData toOffice = null;
+               ClientData toClient = null;
+               PortfolioAccountData toAccount = null;
+
+               // template
+               Collection<PortfolioAccountData> fromAccountOptions = null;
+               Collection<PortfolioAccountData> toAccountOptions = null;
+
+               Long mostRelevantFromOfficeId = fromOfficeId;
+               Long mostRelevantFromClientId = fromClientId;
+
+               Long mostRelevantToOfficeId = toOfficeId;
+               Long mostRelevantToClientId = toClientId;
+
+               if (fromAccountId != null) {
+                       Integer accountType;
+                       if (mostRelevantFromAccountType == 1) {
+                               accountType = 
PortfolioAccountType.LOAN.getValue();
+                       } else {
+                               accountType = 
PortfolioAccountType.SAVINGS.getValue();
+                       }
+                       fromAccount = 
this.portfolioAccountReadPlatformService.retrieveOne(
+                                       fromAccountId, accountType);
+
+                       // override provided fromClient with client of account
+                       mostRelevantFromClientId = fromAccount.clientId();
+               }
+
+               if (mostRelevantFromClientId != null) {
+                       fromClient = this.clientReadPlatformService
+                                       .retrieveOne(mostRelevantFromClientId);
+                       mostRelevantFromOfficeId = fromClient.officeId();
+                       long[] loanStatus = null;
+                       if (mostRelevantFromAccountType == 1) {
+                               loanStatus = new long[] { 300, 700 };
+                       }
+                       PortfolioAccountDTO portfolioAccountDTO = new 
PortfolioAccountDTO(
+                                       mostRelevantFromAccountType, 
mostRelevantFromClientId,
+                                       loanStatus);
+                       fromAccountOptions = 
this.portfolioAccountReadPlatformService
+                                       
.retrieveAllForLookup(portfolioAccountDTO);
+               }
+
+               Collection<OfficeData> fromOfficeOptions = null;
+               Collection<ClientData> fromClientOptions = null;
+               if (mostRelevantFromOfficeId != null) {
+                       fromOffice = this.officeReadPlatformService
+                                       
.retrieveOffice(mostRelevantFromOfficeId);
+                       fromOfficeOptions = this.officeReadPlatformService
+                                       .retrieveAllOfficesForDropdown();
+                       fromClientOptions = this.clientReadPlatformService
+                                       
.retrieveAllForLookupByOfficeId(mostRelevantFromOfficeId);
+               }
+
+               // defaults
+               final LocalDate transferDate = DateUtils.getLocalDateOfTenant();
+               Collection<OfficeData> toOfficeOptions = fromOfficeOptions;
+               Collection<ClientData> toClientOptions = null;
+
+               if (toAccountId != null && fromAccount != null) {
+                       toAccount = 
this.portfolioAccountReadPlatformService.retrieveOne(
+                                       toAccountId, mostRelevantToAccountType,
+                                       fromAccount.currencyCode());
+                       mostRelevantToClientId = toAccount.clientId();
+               }
+
+               if (mostRelevantToClientId != null) {
+                       toClient = this.clientReadPlatformService
+                                       .retrieveOne(mostRelevantToClientId);
+                       mostRelevantToOfficeId = toClient.officeId();
+
+                       toClientOptions = this.clientReadPlatformService
+                                       
.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
+
+                       toAccountOptions = retrieveToAccounts(fromAccount,
+                                       mostRelevantToAccountType, 
mostRelevantToClientId);
+               }
+
+               if (mostRelevantToOfficeId != null) {
+                       toOffice = this.officeReadPlatformService
+                                       .retrieveOffice(mostRelevantToOfficeId);
+                       toOfficeOptions = this.officeReadPlatformService
+                                       .retrieveAllOfficesForDropdown();
+
+                       toClientOptions = this.clientReadPlatformService
+                                       
.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
+                       if (toClientOptions != null && toClientOptions.size() 
== 1) {
+                               toClient = new 
ArrayList<>(toClientOptions).get(0);
+
+                               toAccountOptions = 
retrieveToAccounts(fromAccount,
+                                               mostRelevantToAccountType, 
mostRelevantToClientId);
+                       }
+               }
+
+               return AccountTransferData.template(fromOffice, fromClient,
+                               fromAccountTypeData, fromAccount, transferDate, 
toOffice,
+                               toClient, toAccountTypeData, toAccount, 
fromOfficeOptions,
+                               fromClientOptions, fromAccountTypeOptions, 
fromAccountOptions,
+                               toOfficeOptions, toClientOptions, 
toAccountTypeOptions,
+                               toAccountOptions);
+       }
+
+       private Collection<PortfolioAccountData> retrieveToAccounts(
+                       final PortfolioAccountData 
excludeThisAccountFromOptions,
+                       final Integer toAccountType, final Long toClientId) {
+
+               final String currencyCode = excludeThisAccountFromOptions != 
null ? excludeThisAccountFromOptions
+                               .currencyCode() : null;
+
+               PortfolioAccountDTO portfolioAccountDTO = new 
PortfolioAccountDTO(
+                               toAccountType, toClientId, currencyCode, null, 
null);
+               Collection<PortfolioAccountData> accountOptions = 
this.portfolioAccountReadPlatformService
+                               .retrieveAllForLookup(portfolioAccountDTO);
+               if (!CollectionUtils.isEmpty(accountOptions)) {
+                       accountOptions.remove(excludeThisAccountFromOptions);
+               } else {
+                       accountOptions = null;
+               }
+
+               return accountOptions;
+       }
+
+       @Override
+       public Page<AccountTransferData> retrieveAll(
+                       final SearchParameters searchParameters, final Long 
accountDetailId) {
+
+               final StringBuilder sqlBuilder = new StringBuilder(200);
+               sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
+               sqlBuilder.append(this.accountTransfersMapper.schema());
+               Object[] finalObjectArray = {};
+               if (accountDetailId != null) {
+                       sqlBuilder.append(" where 
att.account_transfer_details_id=?");
+                       finalObjectArray = new Object[] { accountDetailId };
+               }
+
+               if (searchParameters.isOrderByRequested()) {
+                       sqlBuilder.append(" order by ").append(
+                                       searchParameters.getOrderBy());
+
+                       if (searchParameters.isSortOrderProvided()) {
+                               sqlBuilder.append(' 
').append(searchParameters.getSortOrder());
+                       }
+               }
+
+               if (searchParameters.isLimited()) {
+                       sqlBuilder.append(" limit 
").append(searchParameters.getLimit());
+                       if (searchParameters.isOffset()) {
+                               sqlBuilder.append(" offset ").append(
+                                               searchParameters.getOffset());
+                       }
+               }
+
+               final String sqlCountRows = "SELECT FOUND_ROWS()";
+               return this.paginationHelper.fetchPage(this.jdbcTemplate, 
sqlCountRows,
+                               sqlBuilder.toString(), finalObjectArray,
+                               this.accountTransfersMapper);
+       }
+
+       @Override
+       public AccountTransferData retrieveOne(final Long transferId) {
+
+               try {
+                       final String sql = "select " + 
this.accountTransfersMapper.schema()
+                                       + " where att.id = ?";
+
+                       return this.jdbcTemplate.queryForObject(sql,
+                                       this.accountTransfersMapper, new 
Object[] { transferId });
+               } catch (final EmptyResultDataAccessException e) {
+                       throw new AccountTransferNotFoundException(transferId);
+               }
+       }
+
+       @Override
+       public Collection<Long> fetchPostInterestTransactionIds(final Long 
accountId) {
+               final String sql = "select att.from_savings_transaction_id from 
m_account_transfer_transaction att inner join m_account_transfer_details atd on 
atd.id = att.account_transfer_details_id where atd.from_savings_account_id=? 
and att.is_reversed =0 and atd.transfer_type = ?";
+
+               final List<Long> transactionId = 
this.jdbcTemplate.queryForList(sql,
+                               Long.class, accountId,
+                               
AccountTransferType.INTEREST_TRANSFER.getValue());
+
+               return transactionId;
+       }
+
+       private static final class AccountTransfersMapper implements
+                       RowMapper<AccountTransferData> {
+
+               private final String schemaSql;
+
+               public AccountTransfersMapper() {
+                       final StringBuilder sqlBuilder = new StringBuilder(400);
+                       sqlBuilder.append("att.id as id, att.is_reversed as 
isReversed,");
+                       sqlBuilder
+                                       .append("att.transaction_date as 
transferDate, att.amount as transferAmount,");
+                       sqlBuilder.append("att.description as 
transferDescription,");
+                       sqlBuilder
+                                       .append("att.currency_code as 
currencyCode, att.currency_digits as currencyDigits,");
+                       sqlBuilder.append("att.currency_multiplesof as 
inMultiplesOf, ");
+                       sqlBuilder
+                                       .append("curr.name as currencyName, 
curr.internationalized_name_code as currencyNameCode, ");
+                       sqlBuilder.append("curr.display_symbol as 
currencyDisplaySymbol, ");
+                       sqlBuilder
+                                       .append("fromoff.id as fromOfficeId, 
fromoff.name as fromOfficeName,");
+                       sqlBuilder
+                                       .append("tooff.id as toOfficeId, 
tooff.name as toOfficeName,");
+                       sqlBuilder
+                                       .append("fromclient.id as fromClientId, 
fromclient.display_name as fromClientName,");
+                       sqlBuilder
+                                       .append("toclient.id as toClientId, 
toclient.display_name as toClientName,");
+                       sqlBuilder
+                                       .append("fromsavacc.id as 
fromSavingsAccountId, fromsavacc.account_no as fromSavingsAccountNo,");
+                       sqlBuilder
+                                       .append("fromloanacc.id as 
fromLoanAccountId, fromloanacc.account_no as fromLoanAccountNo,");
+                       sqlBuilder
+                                       .append("tosavacc.id as 
toSavingsAccountId, tosavacc.account_no as toSavingsAccountNo,");
+                       sqlBuilder
+                                       .append("toloanacc.id as 
toLoanAccountId, toloanacc.account_no as toLoanAccountNo,");
+                       sqlBuilder
+                                       .append("fromsavtran.id as 
fromSavingsAccountTransactionId,");
+                       sqlBuilder
+                                       
.append("fromsavtran.transaction_type_enum as 
fromSavingsAccountTransactionType,");
+                       sqlBuilder.append("tosavtran.id as 
toSavingsAccountTransactionId,");
+                       sqlBuilder
+                                       
.append("tosavtran.transaction_type_enum as toSavingsAccountTransactionType");
+                       sqlBuilder.append(" FROM m_account_transfer_transaction 
att ");
+                       sqlBuilder
+                                       .append("left join 
m_account_transfer_details atd on atd.id = att.account_transfer_details_id ");
+                       sqlBuilder
+                                       .append("join m_currency curr on 
curr.code = att.currency_code ");
+                       sqlBuilder
+                                       .append("join m_office fromoff on 
fromoff.id = atd.from_office_id ");
+                       sqlBuilder
+                                       .append("join m_office tooff on 
tooff.id = atd.to_office_id ");
+                       sqlBuilder
+                                       .append("join m_client fromclient on 
fromclient.id = atd.from_client_id ");
+                       sqlBuilder
+                                       .append("join m_client toclient on 
toclient.id = atd.to_client_id ");
+                       sqlBuilder
+                                       .append("left join m_savings_account 
fromsavacc on fromsavacc.id = atd.from_savings_account_id ");
+                       sqlBuilder
+                                       .append("left join m_loan fromloanacc 
on fromloanacc.id = atd.from_loan_account_id ");
+                       sqlBuilder
+                                       .append("left join m_savings_account 
tosavacc on tosavacc.id = atd.to_savings_account_id ");
+                       sqlBuilder
+                                       .append("left join m_loan toloanacc on 
toloanacc.id = atd.to_loan_account_id ");
+                       sqlBuilder
+                                       .append("left join 
m_savings_account_transaction fromsavtran on fromsavtran.id = 
att.from_savings_transaction_id ");
+                       sqlBuilder
+                                       .append("left join 
m_savings_account_transaction tosavtran on tosavtran.id = 
att.to_savings_transaction_id ");
+                       sqlBuilder
+                                       .append("left join m_loan_transaction 
fromloantran on fromloantran.id = att.from_savings_transaction_id ");
+                       sqlBuilder
+                                       .append("left join m_loan_transaction 
toloantran on toloantran.id = att.to_savings_transaction_id ");
+
+                       this.schemaSql = sqlBuilder.toString();
+               }
+
+               public String schema() {
+                       return this.schemaSql;
+               }
+
+               @Override
+               public AccountTransferData mapRow(final ResultSet rs,
+                               @SuppressWarnings("unused") final int rowNum)
+                               throws SQLException {
+
+                       final Long id = rs.getLong("id");
+                       final boolean reversed = rs.getBoolean("isReversed");
+
+                       final LocalDate transferDate = 
JdbcSupport.getLocalDate(rs,
+                                       "transferDate");
+                       final BigDecimal transferAmount = JdbcSupport
+                                       .getBigDecimalDefaultToZeroIfNull(rs, 
"transferAmount");
+                       final String transferDescription = rs
+                                       .getString("transferDescription");
+
+                       final String currencyCode = 
rs.getString("currencyCode");
+                       final String currencyName = 
rs.getString("currencyName");
+                       final String currencyNameCode = 
rs.getString("currencyNameCode");
+                       final String currencyDisplaySymbol = rs
+                                       .getString("currencyDisplaySymbol");
+                       final Integer currencyDigits = 
JdbcSupport.getInteger(rs,
+                                       "currencyDigits");
+                       final Integer inMultiplesOf = JdbcSupport.getInteger(rs,
+                                       "inMultiplesOf");
+                       final CurrencyData currency = new 
CurrencyData(currencyCode,
+                                       currencyName, currencyDigits, 
inMultiplesOf,
+                                       currencyDisplaySymbol, 
currencyNameCode);
+
+                       final Long fromOfficeId = JdbcSupport.getLong(rs, 
"fromOfficeId");
+                       final String fromOfficeName = 
rs.getString("fromOfficeName");
+                       final OfficeData fromOffice = 
OfficeData.dropdown(fromOfficeId,
+                                       fromOfficeName, null);
+
+                       final Long toOfficeId = JdbcSupport.getLong(rs, 
"toOfficeId");
+                       final String toOfficeName = 
rs.getString("toOfficeName");
+                       final OfficeData toOffice = 
OfficeData.dropdown(toOfficeId,
+                                       toOfficeName, null);
+
+                       final Long fromClientId = JdbcSupport.getLong(rs, 
"fromClientId");
+                       final String fromClientName = 
rs.getString("fromClientName");
+                       final ClientData fromClient = 
ClientData.lookup(fromClientId,
+                                       fromClientName, fromOfficeId, 
fromOfficeName);
+
+                       final Long toClientId = JdbcSupport.getLong(rs, 
"toClientId");
+                       final String toClientName = 
rs.getString("toClientName");
+                       final ClientData toClient = 
ClientData.lookup(toClientId,
+                                       toClientName, toOfficeId, toOfficeName);
+
+                       final Long fromSavingsAccountId = 
JdbcSupport.getLong(rs,
+                                       "fromSavingsAccountId");
+                       final String fromSavingsAccountNo = rs
+                                       .getString("fromSavingsAccountNo");
+                       final Long fromLoanAccountId = JdbcSupport.getLong(rs,
+                                       "fromLoanAccountId");
+                       final String fromLoanAccountNo = 
rs.getString("fromLoanAccountNo");
+                       PortfolioAccountData fromAccount = null;
+                       EnumOptionData fromAccountType = null;
+                       if (fromSavingsAccountId != null) {
+                               fromAccount = 
PortfolioAccountData.lookup(fromSavingsAccountId,
+                                               fromSavingsAccountNo);
+                               fromAccountType = AccountTransferEnumerations
+                                               
.accountType(PortfolioAccountType.SAVINGS);
+                       } else if (fromLoanAccountId != null) {
+                               fromAccount = 
PortfolioAccountData.lookup(fromLoanAccountId,
+                                               fromLoanAccountNo);
+                               fromAccountType = AccountTransferEnumerations
+                                               
.accountType(PortfolioAccountType.LOAN);
+                       }
+
+                       PortfolioAccountData toAccount = null;
+                       EnumOptionData toAccountType = null;
+                       final Long toSavingsAccountId = JdbcSupport.getLong(rs,
+                                       "toSavingsAccountId");
+                       final String toSavingsAccountNo = rs
+                                       .getString("toSavingsAccountNo");
+                       final Long toLoanAccountId = JdbcSupport.getLong(rs,
+                                       "toLoanAccountId");
+                       final String toLoanAccountNo = 
rs.getString("toLoanAccountNo");
+
+                       if (toSavingsAccountId != null) {
+                               toAccount = 
PortfolioAccountData.lookup(toSavingsAccountId,
+                                               toSavingsAccountNo);
+                               toAccountType = AccountTransferEnumerations
+                                               
.accountType(PortfolioAccountType.SAVINGS);
+                       } else if (toLoanAccountId != null) {
+                               toAccount = 
PortfolioAccountData.lookup(toLoanAccountId,
+                                               toLoanAccountNo);
+                               toAccountType = AccountTransferEnumerations
+                                               
.accountType(PortfolioAccountType.LOAN);
+                       }
+
+                       return AccountTransferData.instance(id, reversed, 
transferDate,
+                                       currency, transferAmount, 
transferDescription, fromOffice,
+                                       toOffice, fromClient, toClient, 
fromAccountType,
+                                       fromAccount, toAccountType, toAccount);
+               }
+       }
+
+       @Override
+       public boolean isAccountTransfer(final Long transactionId,
+                       final PortfolioAccountType accountType) {
+               final StringBuilder sql = new StringBuilder(
+                               "select count(*) from 
m_account_transfer_transaction at where ");
+               if (accountType.isLoanAccount()) {
+                       
sql.append("at.from_loan_transaction_id=").append(transactionId)
+                                       .append(" or 
at.to_loan_transaction_id=")
+                                       .append(transactionId);
+               } else {
+                       
sql.append("at.from_savings_transaction_id=").append(transactionId)
+                                       .append(" or 
at.to_savings_transaction_id=")
+                                       .append(transactionId);
+               }
+
+               @SuppressWarnings("deprecation")
+               final int count = this.jdbcTemplate.queryForInt(sql.toString());
+               return count > 0;
+       }
+
+       @Override
+       public Page<AccountTransferData> retrieveByStandingInstruction(
+                       final Long id, final SearchParameters searchParameters) 
{
+
+               final StringBuilder sqlBuilder = new StringBuilder(200);
+               sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
+               sqlBuilder
+                               .append(this.accountTransfersMapper.schema())
+                               .append(" join 
m_account_transfer_standing_instructions atsi on 
atsi.account_transfer_details_id = att.account_transfer_details_id ");
+               sqlBuilder.append(" where atsi.id = ?");
+
+               if (searchParameters != null) {
+                       if (searchParameters.isOrderByRequested()) {
+                               sqlBuilder.append(" order by ").append(
+                                               searchParameters.getOrderBy());
+
+                               if (searchParameters.isSortOrderProvided()) {
+                                       sqlBuilder.append(' ').append(
+                                                       
searchParameters.getSortOrder());
+                               }
+                       }
+
+                       if (searchParameters.isLimited()) {
+                               sqlBuilder.append(" limit ")
+                                               
.append(searchParameters.getLimit());
+                               if (searchParameters.isOffset()) {
+                                       sqlBuilder.append(" offset ").append(
+                                                       
searchParameters.getOffset());
+                               }
+                       }
+               }
+
+               final Object[] finalObjectArray = { id };
+               final String sqlCountRows = "SELECT FOUND_ROWS()";
+               return this.paginationHelper.fetchPage(this.jdbcTemplate, 
sqlCountRows,
+                               sqlBuilder.toString(), finalObjectArray,
+                               this.accountTransfersMapper);
+       }
+
+       @Override
+       public AccountTransferData retrieveRefundByTransferTemplate(
+                       final Long fromOfficeId, final Long fromClientId,
+                       final Long fromAccountId, final Integer fromAccountType,
+                       final Long toOfficeId, final Long toClientId,
+                       final Long toAccountId, final Integer toAccountType) {
+               // TODO Auto-generated method stub
+               final EnumOptionData loanAccountType = 
AccountTransferEnumerations
+                               .accountType(PortfolioAccountType.LOAN);
+               final EnumOptionData savingsAccountType = 
AccountTransferEnumerations
+                               .accountType(PortfolioAccountType.SAVINGS);
+
+               final Integer mostRelevantFromAccountType = fromAccountType;
+               final Collection<EnumOptionData> fromAccountTypeOptions = Arrays
+                               .asList(savingsAccountType, loanAccountType);
+               final Collection<EnumOptionData> toAccountTypeOptions;
+               if (mostRelevantFromAccountType == 1) {
+                       // overpaid loan amt transfer to savings account
+                       toAccountTypeOptions = 
Arrays.asList(savingsAccountType);
+               } else {
+                       toAccountTypeOptions = Arrays.asList(loanAccountType,
+                                       savingsAccountType);
+               }
+               final Integer mostRelevantToAccountType = toAccountType;
+
+               final EnumOptionData fromAccountTypeData = 
AccountTransferEnumerations
+                               .accountType(mostRelevantFromAccountType);
+               final EnumOptionData toAccountTypeData = 
AccountTransferEnumerations
+                               .accountType(mostRelevantToAccountType);
+
+               // from settings
+               OfficeData fromOffice = null;
+               ClientData fromClient = null;
+               PortfolioAccountData fromAccount = null;
+
+               OfficeData toOffice = null;
+               ClientData toClient = null;
+               PortfolioAccountData toAccount = null;
+
+               // template
+               Collection<PortfolioAccountData> fromAccountOptions = null;
+               Collection<PortfolioAccountData> toAccountOptions = null;
+
+               Long mostRelevantFromOfficeId = fromOfficeId;
+               Long mostRelevantFromClientId = fromClientId;
+
+               Long mostRelevantToOfficeId = toOfficeId;
+               Long mostRelevantToClientId = toClientId;
+
+               if (fromAccountId != null) {
+                       Integer accountType;
+                       if (mostRelevantFromAccountType == 1) {
+                               accountType = 
PortfolioAccountType.LOAN.getValue();
+                       } else {
+                               accountType = 
PortfolioAccountType.SAVINGS.getValue();
+                       }
+                       fromAccount = this.portfolioAccountReadPlatformService
+                                       
.retrieveOneByPaidInAdvance(fromAccountId, accountType);
+
+                       // override provided fromClient with client of account
+                       mostRelevantFromClientId = fromAccount.clientId();
+               }
+
+               if (mostRelevantFromClientId != null) {
+                       fromClient = this.clientReadPlatformService
+                                       .retrieveOne(mostRelevantFromClientId);
+                       mostRelevantFromOfficeId = fromClient.officeId();
+                       long[] loanStatus = null;
+                       if (mostRelevantFromAccountType == 1) {
+                               loanStatus = new long[] { 300, 700 };
+                       }
+                       PortfolioAccountDTO portfolioAccountDTO = new 
PortfolioAccountDTO(
+                                       mostRelevantFromAccountType, 
mostRelevantFromClientId,
+                                       loanStatus);
+                       fromAccountOptions = 
this.portfolioAccountReadPlatformService
+                                       
.retrieveAllForLookup(portfolioAccountDTO);
+               }
+
+               Collection<OfficeData> fromOfficeOptions = null;
+               Collection<ClientData> fromClientOptions = null;
+               if (mostRelevantFromOfficeId != null) {
+                       fromOffice = this.officeReadPlatformService
+                                       
.retrieveOffice(mostRelevantFromOfficeId);
+                       fromOfficeOptions = this.officeReadPlatformService
+                                       .retrieveAllOfficesForDropdown();
+                       fromClientOptions = this.clientReadPlatformService
+                                       
.retrieveAllForLookupByOfficeId(mostRelevantFromOfficeId);
+               }
+
+               // defaults
+               final LocalDate transferDate = DateUtils.getLocalDateOfTenant();
+               Collection<OfficeData> toOfficeOptions = fromOfficeOptions;
+               Collection<ClientData> toClientOptions = null;
+
+               if (toAccountId != null && fromAccount != null) {
+                       toAccount = 
this.portfolioAccountReadPlatformService.retrieveOne(
+                                       toAccountId, mostRelevantToAccountType,
+                                       fromAccount.currencyCode());
+                       mostRelevantToClientId = toAccount.clientId();
+               }
+
+               if (mostRelevantToClientId != null) {
+                       toClient = this.clientReadPlatformService
+                                       .retrieveOne(mostRelevantToClientId);
+                       mostRelevantToOfficeId = toClient.officeId();
+
+                       toClientOptions = this.clientReadPlatformService
+                                       
.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
+
+                       toAccountOptions = retrieveToAccounts(fromAccount,
+                                       mostRelevantToAccountType, 
mostRelevantToClientId);
+               }
+
+               if (mostRelevantToOfficeId != null) {
+                       toOffice = this.officeReadPlatformService
+                                       .retrieveOffice(mostRelevantToOfficeId);
+                       toOfficeOptions = this.officeReadPlatformService
+                                       .retrieveAllOfficesForDropdown();
+
+                       toClientOptions = this.clientReadPlatformService
+                                       
.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
+                       if (toClientOptions != null && toClientOptions.size() 
== 1) {
+                               toClient = new 
ArrayList<>(toClientOptions).get(0);
+
+                               toAccountOptions = 
retrieveToAccounts(fromAccount,
+                                               mostRelevantToAccountType, 
mostRelevantToClientId);
+                       }
+               }
+
+               return AccountTransferData.template(fromOffice, fromClient,
+                               fromAccountTypeData, fromAccount, transferDate, 
toOffice,
+                               toClient, toAccountTypeData, toAccount, 
fromOfficeOptions,
+                               fromClientOptions, fromAccountTypeOptions, 
fromAccountOptions,
+                               toOfficeOptions, toClientOptions, 
toAccountTypeOptions,
+                               toAccountOptions);
+       }
+
+       @Override
+       public BigDecimal getTotalTransactionAmount(Long accountId,
+                       Integer accountType, LocalDate transactionDate) {
+               StringBuilder sqlBuilder = new StringBuilder(
+                               " select sum(trans.amount) as 
totalTransactionAmount ");
+               sqlBuilder.append(" from m_account_transfer_details as det ");
+               sqlBuilder
+                               .append(" inner join 
m_account_transfer_transaction as trans ");
+               sqlBuilder.append(" on det.id = 
trans.account_transfer_details_id ");
+               sqlBuilder.append(" where trans.is_reversed = 0 ");
+               sqlBuilder.append(" and trans.transaction_date = ? ");
+               sqlBuilder
+                               .append(" and IF(1=?, det.from_loan_account_id 
= ?, det.from_savings_account_id = ?) ");
+
+               return this.jdbcTemplate.queryForObject(sqlBuilder.toString(),
+                               new Object[] { 
this.formatter.print(transactionDate),
+                                               accountType, accountId, 
accountId }, BigDecimal.class);
+       }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java
index 845cc67..b306d70 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java
@@ -69,6 +69,8 @@ public interface LoanRepository extends JpaRepository<Loan, 
Long>, JpaSpecificat
 
     public static final String DOES_PRODUCT_HAVE_NON_CLOSED_LOANS = "select 
case when (count (loan) > 0) then true else false end from Loan loan where 
loan.loanProduct.id = :productId and loan.loanStatus in 
(100,200,300,303,304,700)";
 
+    public static final String FIND_BY_ACCOUNT_NUMBER = "from Loan loan where 
loan.accountNumber = :accountNumber and loan.loanStatus in 
(100,200,300,303,304)";
+
     @Query(FIND_GROUP_LOANS_DISBURSED_AFTER)
     List<Loan> getGroupLoansDisbursedAfter(@Param("disbursementDate") Date 
disbursementDate, @Param("groupId") Long groupId,
             @Param("loanType") Integer loanType);
@@ -144,5 +146,7 @@ public interface LoanRepository extends JpaRepository<Loan, 
Long>, JpaSpecificat
     
     @Query(DOES_PRODUCT_HAVE_NON_CLOSED_LOANS)
     boolean doNonClosedLoanAccountsExistForProduct(@Param("productId") Long 
productId);
-
+    
+    @Query(FIND_BY_ACCOUNT_NUMBER)
+    Loan findNonClosedLoanByAccountNumber(@Param("accountNumber") String 
accountNumber);
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepository.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepository.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepository.java
index b34e897..b614b25 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepository.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepository.java
@@ -45,4 +45,7 @@ public interface SavingsAccountRepository extends 
JpaRepository<SavingsAccount,
     @Query("from SavingsAccount sa where sa.id = :accountId and sa.depositType 
= :depositAccountTypeId")
     SavingsAccount findByIdAndDepositAccountType(@Param("accountId") Long 
accountId,
             @Param("depositAccountTypeId") Integer depositAccountTypeId);
+
+    @Query("from SavingsAccount sa where sa.accountNumber = :accountNumber and 
sa.status in (100, 200, 300, 303, 304) ")
+    SavingsAccount findNonClosedAccountByAccountNumber(@Param("accountNumber") 
String accountNumber);
 }
\ No newline at end of file

Reply via email to