You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by na...@apache.org on 2016/05/04 09:51:10 UTC
[2/2] incubator-fineract git commit: Customer Self Service : APIs for
Third Party Beneficiary management and Third Party Account Transfers
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 <ad...@confluxtechnologies.com>
Authored: Wed May 4 13:00:41 2016 +0530
Committer: Adi Narayana Raju <ad...@confluxtechnologies.com>
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"> </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"> </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"> </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"> </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"> </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"> </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"> </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