Customer Self Service : APIs for Third Party Beneficiary management and Third Party Account Transfers
This commit is contained in:
+378
-1
@@ -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 -->
|
||||
|
||||
+25
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
+4
@@ -79,4 +79,8 @@ public interface ConfigurationDomainService {
|
||||
|
||||
boolean isChangeEmiIfRepaymentDateSameAsDisbursementDateEnabled();
|
||||
|
||||
boolean isDailyTPTLimitEnabled();
|
||||
|
||||
Long getDailyTPTLimit();
|
||||
|
||||
}
|
||||
+16
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+1
-1
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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) {
|
||||
|
||||
+5
@@ -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);
|
||||
}
|
||||
+293
-133
@@ -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,7 +55,8 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@Service
|
||||
public class AccountTransfersReadPlatformServiceImpl implements AccountTransfersReadPlatformService {
|
||||
public class AccountTransfersReadPlatformServiceImpl implements
|
||||
AccountTransfersReadPlatformService {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final ClientReadPlatformService clientReadPlatformService;
|
||||
@@ -65,10 +68,14 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
|
||||
|
||||
// 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,
|
||||
public AccountTransfersReadPlatformServiceImpl(
|
||||
final RoutingDataSource dataSource,
|
||||
final ClientReadPlatformService clientReadPlatformService,
|
||||
final OfficeReadPlatformService officeReadPlatformService,
|
||||
final PortfolioAccountReadPlatformService portfolioAccountReadPlatformService) {
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
this.clientReadPlatformService = clientReadPlatformService;
|
||||
@@ -79,25 +86,35 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
|
||||
}
|
||||
|
||||
@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) {
|
||||
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 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> fromAccountTypeOptions = Arrays
|
||||
.asList(savingsAccountType, loanAccountType);
|
||||
final Collection<EnumOptionData> toAccountTypeOptions;
|
||||
if (mostRelevantFromAccountType != null && mostRelevantFromAccountType == 1) {
|
||||
if (mostRelevantFromAccountType != null
|
||||
&& mostRelevantFromAccountType == 1) {
|
||||
// overpaid loan amt transfer to savings account
|
||||
toAccountTypeOptions = Arrays.asList(savingsAccountType);
|
||||
} else {
|
||||
toAccountTypeOptions = Arrays.asList(loanAccountType, savingsAccountType);
|
||||
toAccountTypeOptions = Arrays.asList(loanAccountType,
|
||||
savingsAccountType);
|
||||
}
|
||||
final Integer mostRelevantToAccountType = toAccountType;
|
||||
|
||||
final EnumOptionData fromAccountTypeData = AccountTransferEnumerations.accountType(mostRelevantFromAccountType);
|
||||
final EnumOptionData toAccountTypeData = AccountTransferEnumerations.accountType(mostRelevantToAccountType);
|
||||
final EnumOptionData fromAccountTypeData = AccountTransferEnumerations
|
||||
.accountType(mostRelevantFromAccountType);
|
||||
final EnumOptionData toAccountTypeData = AccountTransferEnumerations
|
||||
.accountType(mostRelevantToAccountType);
|
||||
|
||||
// from settings
|
||||
OfficeData fromOffice = null;
|
||||
@@ -125,30 +142,37 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
|
||||
} else {
|
||||
accountType = PortfolioAccountType.SAVINGS.getValue();
|
||||
}
|
||||
fromAccount = this.portfolioAccountReadPlatformService.retrieveOne(fromAccountId, accountType);
|
||||
fromAccount = this.portfolioAccountReadPlatformService.retrieveOne(
|
||||
fromAccountId, accountType);
|
||||
|
||||
// override provided fromClient with client of account
|
||||
mostRelevantFromClientId = fromAccount.clientId();
|
||||
}
|
||||
|
||||
if (mostRelevantFromClientId != null) {
|
||||
fromClient = this.clientReadPlatformService.retrieveOne(mostRelevantFromClientId);
|
||||
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,
|
||||
PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(
|
||||
mostRelevantFromAccountType, mostRelevantFromClientId,
|
||||
loanStatus);
|
||||
fromAccountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(portfolioAccountDTO);
|
||||
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);
|
||||
fromOffice = this.officeReadPlatformService
|
||||
.retrieveOffice(mostRelevantFromOfficeId);
|
||||
fromOfficeOptions = this.officeReadPlatformService
|
||||
.retrieveAllOfficesForDropdown();
|
||||
fromClientOptions = this.clientReadPlatformService
|
||||
.retrieveAllForLookupByOfficeId(mostRelevantFromOfficeId);
|
||||
}
|
||||
|
||||
// defaults
|
||||
@@ -157,43 +181,57 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
|
||||
Collection<ClientData> toClientOptions = null;
|
||||
|
||||
if (toAccountId != null && fromAccount != null) {
|
||||
toAccount = this.portfolioAccountReadPlatformService.retrieveOne(toAccountId, mostRelevantToAccountType,
|
||||
toAccount = this.portfolioAccountReadPlatformService.retrieveOne(
|
||||
toAccountId, mostRelevantToAccountType,
|
||||
fromAccount.currencyCode());
|
||||
mostRelevantToClientId = toAccount.clientId();
|
||||
}
|
||||
|
||||
if (mostRelevantToClientId != null) {
|
||||
toClient = this.clientReadPlatformService.retrieveOne(mostRelevantToClientId);
|
||||
toClient = this.clientReadPlatformService
|
||||
.retrieveOne(mostRelevantToClientId);
|
||||
mostRelevantToOfficeId = toClient.officeId();
|
||||
|
||||
toClientOptions = this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
|
||||
toClientOptions = this.clientReadPlatformService
|
||||
.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
|
||||
|
||||
toAccountOptions = retrieveToAccounts(fromAccount, mostRelevantToAccountType, mostRelevantToClientId);
|
||||
toAccountOptions = retrieveToAccounts(fromAccount,
|
||||
mostRelevantToAccountType, mostRelevantToClientId);
|
||||
}
|
||||
|
||||
if (mostRelevantToOfficeId != null) {
|
||||
toOffice = this.officeReadPlatformService.retrieveOffice(mostRelevantToOfficeId);
|
||||
toOfficeOptions = this.officeReadPlatformService.retrieveAllOfficesForDropdown();
|
||||
toOffice = this.officeReadPlatformService
|
||||
.retrieveOffice(mostRelevantToOfficeId);
|
||||
toOfficeOptions = this.officeReadPlatformService
|
||||
.retrieveAllOfficesForDropdown();
|
||||
|
||||
toClientOptions = this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
|
||||
toClientOptions = this.clientReadPlatformService
|
||||
.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
|
||||
if (toClientOptions != null && toClientOptions.size() == 1) {
|
||||
toClient = new ArrayList<>(toClientOptions).get(0);
|
||||
|
||||
toAccountOptions = retrieveToAccounts(fromAccount, mostRelevantToAccountType, mostRelevantToClientId);
|
||||
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);
|
||||
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,
|
||||
private Collection<PortfolioAccountData> retrieveToAccounts(
|
||||
final PortfolioAccountData excludeThisAccountFromOptions,
|
||||
final Integer toAccountType, final Long toClientId) {
|
||||
|
||||
final String currencyCode = excludeThisAccountFromOptions != null ? excludeThisAccountFromOptions.currencyCode() : null;
|
||||
final String currencyCode = excludeThisAccountFromOptions != null ? excludeThisAccountFromOptions
|
||||
.currencyCode() : null;
|
||||
|
||||
PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(toAccountType, toClientId, currencyCode, null, null);
|
||||
PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(
|
||||
toAccountType, toClientId, currencyCode, null, null);
|
||||
Collection<PortfolioAccountData> accountOptions = this.portfolioAccountReadPlatformService
|
||||
.retrieveAllForLookup(portfolioAccountDTO);
|
||||
if (!CollectionUtils.isEmpty(accountOptions)) {
|
||||
@@ -206,7 +244,8 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<AccountTransferData> retrieveAll(final SearchParameters searchParameters, final Long accountDetailId) {
|
||||
public Page<AccountTransferData> retrieveAll(
|
||||
final SearchParameters searchParameters, final Long accountDetailId) {
|
||||
|
||||
final StringBuilder sqlBuilder = new StringBuilder(200);
|
||||
sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
|
||||
@@ -218,7 +257,8 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
|
||||
}
|
||||
|
||||
if (searchParameters.isOrderByRequested()) {
|
||||
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
|
||||
sqlBuilder.append(" order by ").append(
|
||||
searchParameters.getOrderBy());
|
||||
|
||||
if (searchParameters.isSortOrderProvided()) {
|
||||
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
|
||||
@@ -228,12 +268,14 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
|
||||
if (searchParameters.isLimited()) {
|
||||
sqlBuilder.append(" limit ").append(searchParameters.getLimit());
|
||||
if (searchParameters.isOffset()) {
|
||||
sqlBuilder.append(" offset ").append(searchParameters.getOffset());
|
||||
sqlBuilder.append(" offset ").append(
|
||||
searchParameters.getOffset());
|
||||
}
|
||||
}
|
||||
|
||||
final String sqlCountRows = "SELECT FOUND_ROWS()";
|
||||
return this.paginationHelper.fetchPage(this.jdbcTemplate, sqlCountRows, sqlBuilder.toString(), finalObjectArray,
|
||||
return this.paginationHelper.fetchPage(this.jdbcTemplate, sqlCountRows,
|
||||
sqlBuilder.toString(), finalObjectArray,
|
||||
this.accountTransfersMapper);
|
||||
}
|
||||
|
||||
@@ -241,9 +283,11 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
|
||||
public AccountTransferData retrieveOne(final Long transferId) {
|
||||
|
||||
try {
|
||||
final String sql = "select " + this.accountTransfersMapper.schema() + " where att.id = ?";
|
||||
final String sql = "select " + this.accountTransfersMapper.schema()
|
||||
+ " where att.id = ?";
|
||||
|
||||
return this.jdbcTemplate.queryForObject(sql, this.accountTransfersMapper, new Object[] { transferId });
|
||||
return this.jdbcTemplate.queryForObject(sql,
|
||||
this.accountTransfersMapper, new Object[] { transferId });
|
||||
} catch (final EmptyResultDataAccessException e) {
|
||||
throw new AccountTransferNotFoundException(transferId);
|
||||
}
|
||||
@@ -253,52 +297,82 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
|
||||
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,
|
||||
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 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.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_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.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("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("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 ");
|
||||
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();
|
||||
}
|
||||
@@ -308,81 +382,115 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccountTransferData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
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 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,
|
||||
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 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 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 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 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 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);
|
||||
fromAccount = PortfolioAccountData.lookup(fromSavingsAccountId,
|
||||
fromSavingsAccountNo);
|
||||
fromAccountType = AccountTransferEnumerations
|
||||
.accountType(PortfolioAccountType.SAVINGS);
|
||||
} else if (fromLoanAccountId != null) {
|
||||
fromAccount = PortfolioAccountData.lookup(fromLoanAccountId, fromLoanAccountNo);
|
||||
fromAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.LOAN);
|
||||
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 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);
|
||||
toAccount = PortfolioAccountData.lookup(toSavingsAccountId,
|
||||
toSavingsAccountNo);
|
||||
toAccountType = AccountTransferEnumerations
|
||||
.accountType(PortfolioAccountType.SAVINGS);
|
||||
} else if (toLoanAccountId != null) {
|
||||
toAccount = PortfolioAccountData.lookup(toLoanAccountId, toLoanAccountNo);
|
||||
toAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.LOAN);
|
||||
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);
|
||||
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 ");
|
||||
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);
|
||||
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=")
|
||||
sql.append("at.from_savings_transaction_id=").append(transactionId)
|
||||
.append(" or at.to_savings_transaction_id=")
|
||||
.append(transactionId);
|
||||
}
|
||||
|
||||
@@ -392,7 +500,8 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<AccountTransferData> retrieveByStandingInstruction(final Long id, final SearchParameters searchParameters) {
|
||||
public Page<AccountTransferData> retrieveByStandingInstruction(
|
||||
final Long id, final SearchParameters searchParameters) {
|
||||
|
||||
final StringBuilder sqlBuilder = new StringBuilder(200);
|
||||
sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
|
||||
@@ -403,47 +512,61 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
|
||||
|
||||
if (searchParameters != null) {
|
||||
if (searchParameters.isOrderByRequested()) {
|
||||
sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
|
||||
sqlBuilder.append(" order by ").append(
|
||||
searchParameters.getOrderBy());
|
||||
|
||||
if (searchParameters.isSortOrderProvided()) {
|
||||
sqlBuilder.append(' ').append(searchParameters.getSortOrder());
|
||||
sqlBuilder.append(' ').append(
|
||||
searchParameters.getSortOrder());
|
||||
}
|
||||
}
|
||||
|
||||
if (searchParameters.isLimited()) {
|
||||
sqlBuilder.append(" limit ").append(searchParameters.getLimit());
|
||||
sqlBuilder.append(" limit ")
|
||||
.append(searchParameters.getLimit());
|
||||
if (searchParameters.isOffset()) {
|
||||
sqlBuilder.append(" offset ").append(searchParameters.getOffset());
|
||||
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,
|
||||
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) {
|
||||
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 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> 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);
|
||||
toAccountTypeOptions = Arrays.asList(loanAccountType,
|
||||
savingsAccountType);
|
||||
}
|
||||
final Integer mostRelevantToAccountType = toAccountType;
|
||||
|
||||
final EnumOptionData fromAccountTypeData = AccountTransferEnumerations.accountType(mostRelevantFromAccountType);
|
||||
final EnumOptionData toAccountTypeData = AccountTransferEnumerations.accountType(mostRelevantToAccountType);
|
||||
final EnumOptionData fromAccountTypeData = AccountTransferEnumerations
|
||||
.accountType(mostRelevantFromAccountType);
|
||||
final EnumOptionData toAccountTypeData = AccountTransferEnumerations
|
||||
.accountType(mostRelevantToAccountType);
|
||||
|
||||
// from settings
|
||||
OfficeData fromOffice = null;
|
||||
@@ -471,30 +594,37 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
|
||||
} else {
|
||||
accountType = PortfolioAccountType.SAVINGS.getValue();
|
||||
}
|
||||
fromAccount = this.portfolioAccountReadPlatformService.retrieveOneByPaidInAdvance(fromAccountId, accountType);
|
||||
fromAccount = this.portfolioAccountReadPlatformService
|
||||
.retrieveOneByPaidInAdvance(fromAccountId, accountType);
|
||||
|
||||
// override provided fromClient with client of account
|
||||
mostRelevantFromClientId = fromAccount.clientId();
|
||||
}
|
||||
|
||||
if (mostRelevantFromClientId != null) {
|
||||
fromClient = this.clientReadPlatformService.retrieveOne(mostRelevantFromClientId);
|
||||
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,
|
||||
PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(
|
||||
mostRelevantFromAccountType, mostRelevantFromClientId,
|
||||
loanStatus);
|
||||
fromAccountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(portfolioAccountDTO);
|
||||
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);
|
||||
fromOffice = this.officeReadPlatformService
|
||||
.retrieveOffice(mostRelevantFromOfficeId);
|
||||
fromOfficeOptions = this.officeReadPlatformService
|
||||
.retrieveAllOfficesForDropdown();
|
||||
fromClientOptions = this.clientReadPlatformService
|
||||
.retrieveAllForLookupByOfficeId(mostRelevantFromOfficeId);
|
||||
}
|
||||
|
||||
// defaults
|
||||
@@ -503,35 +633,65 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
|
||||
Collection<ClientData> toClientOptions = null;
|
||||
|
||||
if (toAccountId != null && fromAccount != null) {
|
||||
toAccount = this.portfolioAccountReadPlatformService.retrieveOne(toAccountId, mostRelevantToAccountType,
|
||||
toAccount = this.portfolioAccountReadPlatformService.retrieveOne(
|
||||
toAccountId, mostRelevantToAccountType,
|
||||
fromAccount.currencyCode());
|
||||
mostRelevantToClientId = toAccount.clientId();
|
||||
}
|
||||
|
||||
if (mostRelevantToClientId != null) {
|
||||
toClient = this.clientReadPlatformService.retrieveOne(mostRelevantToClientId);
|
||||
toClient = this.clientReadPlatformService
|
||||
.retrieveOne(mostRelevantToClientId);
|
||||
mostRelevantToOfficeId = toClient.officeId();
|
||||
|
||||
toClientOptions = this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
|
||||
toClientOptions = this.clientReadPlatformService
|
||||
.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
|
||||
|
||||
toAccountOptions = retrieveToAccounts(fromAccount, mostRelevantToAccountType, mostRelevantToClientId);
|
||||
toAccountOptions = retrieveToAccounts(fromAccount,
|
||||
mostRelevantToAccountType, mostRelevantToClientId);
|
||||
}
|
||||
|
||||
if (mostRelevantToOfficeId != null) {
|
||||
toOffice = this.officeReadPlatformService.retrieveOffice(mostRelevantToOfficeId);
|
||||
toOfficeOptions = this.officeReadPlatformService.retrieveAllOfficesForDropdown();
|
||||
toOffice = this.officeReadPlatformService
|
||||
.retrieveOffice(mostRelevantToOfficeId);
|
||||
toOfficeOptions = this.officeReadPlatformService
|
||||
.retrieveAllOfficesForDropdown();
|
||||
|
||||
toClientOptions = this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
|
||||
toClientOptions = this.clientReadPlatformService
|
||||
.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
|
||||
if (toClientOptions != null && toClientOptions.size() == 1) {
|
||||
toClient = new ArrayList<>(toClientOptions).get(0);
|
||||
|
||||
toAccountOptions = retrieveToAccounts(fromAccount, mostRelevantToAccountType, mostRelevantToClientId);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
+4
@@ -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);
|
||||
@@ -145,4 +147,6 @@ 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);
|
||||
}
|
||||
+3
@@ -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);
|
||||
}
|
||||
+85
-8
@@ -18,27 +18,37 @@
|
||||
*/
|
||||
package org.apache.fineract.portfolio.self.account.api;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
|
||||
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
|
||||
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.portfolio.account.api.AccountTransfersApiResource;
|
||||
import org.apache.fineract.portfolio.account.service.AccountTransfersReadPlatformService;
|
||||
import org.apache.fineract.portfolio.self.account.data.SelfAccountTemplateData;
|
||||
import org.apache.fineract.portfolio.self.account.data.SelfAccountTransferData;
|
||||
import org.apache.fineract.portfolio.self.account.data.SelfAccountTransferDataValidator;
|
||||
import org.apache.fineract.portfolio.self.account.exception.BeneficiaryTransferLimitExceededException;
|
||||
import org.apache.fineract.portfolio.self.account.exception.DailyTPTTransactionAmountLimitExceededException;
|
||||
import org.apache.fineract.portfolio.self.account.service.SelfAccountTransferReadService;
|
||||
import org.apache.fineract.portfolio.self.account.service.SelfBeneficiariesTPTReadPlatformService;
|
||||
import org.apache.fineract.useradministration.domain.AppUser;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -54,6 +64,9 @@ public class SelfAccountTransferApiResource {
|
||||
private final SelfAccountTransferReadService selfAccountTransferReadService;
|
||||
private final ApiRequestParameterHelper apiRequestParameterHelper;
|
||||
private final SelfAccountTransferDataValidator dataValidator;
|
||||
private final SelfBeneficiariesTPTReadPlatformService tptBeneficiaryReadPlatformService;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
private final AccountTransfersReadPlatformService accountTransfersReadPlatformService;
|
||||
|
||||
@Autowired
|
||||
public SelfAccountTransferApiResource(
|
||||
@@ -62,37 +75,101 @@ public class SelfAccountTransferApiResource {
|
||||
final AccountTransfersApiResource accountTransfersApiResource,
|
||||
final SelfAccountTransferReadService selfAccountTransferReadService,
|
||||
final ApiRequestParameterHelper apiRequestParameterHelper,
|
||||
final SelfAccountTransferDataValidator dataValidator) {
|
||||
final SelfAccountTransferDataValidator dataValidator,
|
||||
final SelfBeneficiariesTPTReadPlatformService tptBeneficiaryReadPlatformService,
|
||||
final ConfigurationDomainService configurationDomainService,
|
||||
final AccountTransfersReadPlatformService accountTransfersReadPlatformService) {
|
||||
this.context = context;
|
||||
this.toApiJsonSerializer = toApiJsonSerializer;
|
||||
this.accountTransfersApiResource = accountTransfersApiResource;
|
||||
this.selfAccountTransferReadService = selfAccountTransferReadService;
|
||||
this.apiRequestParameterHelper = apiRequestParameterHelper;
|
||||
this.dataValidator = dataValidator;
|
||||
this.tptBeneficiaryReadPlatformService = tptBeneficiaryReadPlatformService;
|
||||
this.configurationDomainService = configurationDomainService;
|
||||
this.accountTransfersReadPlatformService = accountTransfersReadPlatformService;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("template")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String template(@Context final UriInfo uriInfo) {
|
||||
public String template(
|
||||
@DefaultValue("") @QueryParam("type") final String type,
|
||||
@Context final UriInfo uriInfo) {
|
||||
|
||||
AppUser user = this.context.authenticatedUser();
|
||||
Collection<SelfAccountTemplateData> templateData = this.selfAccountTransferReadService
|
||||
.retrieveSelfAccountTemplateData(user);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper
|
||||
.process(uriInfo.getQueryParameters());
|
||||
Collection<SelfAccountTemplateData> selfTemplateData = this.selfAccountTransferReadService
|
||||
.retrieveSelfAccountTemplateData(user);
|
||||
|
||||
if (type.equals("tpt")) {
|
||||
Collection<SelfAccountTemplateData> tptTemplateData = this.tptBeneficiaryReadPlatformService
|
||||
.retrieveTPTSelfAccountTemplateData(user);
|
||||
return this.toApiJsonSerializer.serialize(settings,
|
||||
new SelfAccountTransferData(templateData));
|
||||
new SelfAccountTransferData(selfTemplateData,
|
||||
tptTemplateData));
|
||||
}
|
||||
|
||||
return this.toApiJsonSerializer
|
||||
.serialize(settings, new SelfAccountTransferData(
|
||||
selfTemplateData, selfTemplateData));
|
||||
}
|
||||
|
||||
@POST
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String create(final String apiRequestBodyAsJson) {
|
||||
this.dataValidator.validateCreate(apiRequestBodyAsJson);
|
||||
public String create(
|
||||
@DefaultValue("") @QueryParam("type") final String type,
|
||||
final String apiRequestBodyAsJson) {
|
||||
Map<String, Object> params = this.dataValidator.validateCreate(type,
|
||||
apiRequestBodyAsJson);
|
||||
if (type.equals("tpt")) {
|
||||
checkForLimits(params);
|
||||
}
|
||||
return this.accountTransfersApiResource.create(apiRequestBodyAsJson);
|
||||
}
|
||||
|
||||
private void checkForLimits(Map<String, Object> params) {
|
||||
SelfAccountTemplateData fromAccount = (SelfAccountTemplateData) params
|
||||
.get("fromAccount");
|
||||
SelfAccountTemplateData toAccount = (SelfAccountTemplateData) params
|
||||
.get("toAccount");
|
||||
LocalDate transactionDate = (LocalDate) params.get("transactionDate");
|
||||
BigDecimal transactionAmount = (BigDecimal) params
|
||||
.get("transactionAmount");
|
||||
|
||||
AppUser user = this.context.authenticatedUser();
|
||||
Long transferLimit = this.tptBeneficiaryReadPlatformService
|
||||
.getTransferLimit(user.getId(), toAccount.getAccountId(),
|
||||
toAccount.getAccountType());
|
||||
if (transferLimit != null && transferLimit > 0) {
|
||||
if (transactionAmount.compareTo(new BigDecimal(transferLimit)) > 0) {
|
||||
throw new BeneficiaryTransferLimitExceededException();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.configurationDomainService.isDailyTPTLimitEnabled()) {
|
||||
Long dailyTPTLimit = this.configurationDomainService
|
||||
.getDailyTPTLimit();
|
||||
if (dailyTPTLimit != null && dailyTPTLimit > 0) {
|
||||
BigDecimal dailyTPTLimitBD = new BigDecimal(dailyTPTLimit);
|
||||
BigDecimal totTransactionAmount = this.accountTransfersReadPlatformService
|
||||
.getTotalTransactionAmount(fromAccount.getAccountId(),
|
||||
fromAccount.getAccountType(), transactionDate);
|
||||
if (totTransactionAmount != null
|
||||
&& totTransactionAmount.compareTo(BigDecimal.ZERO) > 0) {
|
||||
if (dailyTPTLimitBD.compareTo(totTransactionAmount) <= 0
|
||||
|| dailyTPTLimitBD.compareTo(totTransactionAmount
|
||||
.add(transactionAmount)) < 0) {
|
||||
throw new DailyTPTTransactionAmountLimitExceededException(
|
||||
fromAccount.getAccountId(),
|
||||
fromAccount.getAccountType());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.self.account.api;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public interface SelfBeneficiariesTPTApiConstants {
|
||||
|
||||
public static final String BENEFICIARY_ENTITY_NAME = "SSBENEFICIARYTPT";
|
||||
public static final String RESOURCE_NAME = "beneficiary";
|
||||
public static final String LOCALE = "locale";
|
||||
public static final String NAME_PARAM_NAME = "name";
|
||||
public static final String OFFICE_NAME_PARAM_NAME = "officeName";
|
||||
public static final String ACCOUNT_TYPE_PARAM_NAME = "accountType";
|
||||
public static final String ACCOUNT_NUMBER_PARAM_NAME = "accountNumber";
|
||||
public static final String TRANSFER_LIMIT_PARAM_NAME = "transferLimit";
|
||||
|
||||
public static final String ID_PARAM_NAME = "id";
|
||||
public static final String CLIENT_NAME_PARAM_NAME = "clientName";
|
||||
public static final String ACCOUNT_TYPE_OPTIONS_PARAM_NAME = "accountTypeOptions";
|
||||
|
||||
public static final Set<String> CREATE_REQUEST_DATA_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList(LOCALE, NAME_PARAM_NAME, OFFICE_NAME_PARAM_NAME,
|
||||
ACCOUNT_NUMBER_PARAM_NAME, ACCOUNT_TYPE_PARAM_NAME,
|
||||
TRANSFER_LIMIT_PARAM_NAME));
|
||||
|
||||
public static final Set<String> UPDATE_REQUEST_DATA_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList(NAME_PARAM_NAME, TRANSFER_LIMIT_PARAM_NAME));
|
||||
|
||||
public static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList(NAME_PARAM_NAME, OFFICE_NAME_PARAM_NAME,
|
||||
ACCOUNT_NUMBER_PARAM_NAME, ACCOUNT_TYPE_PARAM_NAME,
|
||||
TRANSFER_LIMIT_PARAM_NAME, ID_PARAM_NAME,
|
||||
CLIENT_NAME_PARAM_NAME, ACCOUNT_TYPE_OPTIONS_PARAM_NAME));
|
||||
}
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.self.account.api;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||
import org.apache.fineract.commands.service.CommandWrapperBuilder;
|
||||
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
|
||||
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
|
||||
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
||||
import org.apache.fineract.portfolio.account.service.AccountTransferEnumerations;
|
||||
import org.apache.fineract.portfolio.self.account.data.SelfBeneficiariesTPTData;
|
||||
import org.apache.fineract.portfolio.self.account.service.SelfBeneficiariesTPTReadPlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Path("/self/beneficiaries/tpt")
|
||||
@Component
|
||||
@Scope("singleton")
|
||||
public class SelfBeneficiariesTPTApiResource {
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final DefaultToApiJsonSerializer<SelfBeneficiariesTPTData> toApiJsonSerializer;
|
||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||
private final ApiRequestParameterHelper apiRequestParameterHelper;
|
||||
private final SelfBeneficiariesTPTReadPlatformService readPlatformService;
|
||||
|
||||
@Autowired
|
||||
public SelfBeneficiariesTPTApiResource(
|
||||
final PlatformSecurityContext context,
|
||||
final DefaultToApiJsonSerializer<SelfBeneficiariesTPTData> toApiJsonSerializer,
|
||||
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
|
||||
final ApiRequestParameterHelper apiRequestParameterHelper,
|
||||
final SelfBeneficiariesTPTReadPlatformService readPlatformService) {
|
||||
this.context = context;
|
||||
this.toApiJsonSerializer = toApiJsonSerializer;
|
||||
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
|
||||
this.apiRequestParameterHelper = apiRequestParameterHelper;
|
||||
this.readPlatformService = readPlatformService;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("template")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String template(@Context final UriInfo uriInfo) {
|
||||
|
||||
final EnumOptionData loanAccountType = AccountTransferEnumerations
|
||||
.accountType(PortfolioAccountType.LOAN);
|
||||
final EnumOptionData savingsAccountType = AccountTransferEnumerations
|
||||
.accountType(PortfolioAccountType.SAVINGS);
|
||||
|
||||
final Collection<EnumOptionData> accountTypeOptions = Arrays.asList(
|
||||
savingsAccountType, loanAccountType);
|
||||
|
||||
SelfBeneficiariesTPTData templateData = new SelfBeneficiariesTPTData(
|
||||
accountTypeOptions);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper
|
||||
.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, templateData,
|
||||
SelfBeneficiariesTPTApiConstants.RESPONSE_DATA_PARAMETERS);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String add(final String apiRequestBodyAsJson) {
|
||||
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder()
|
||||
.addSelfServiceBeneficiaryTPT().withJson(apiRequestBodyAsJson)
|
||||
.build();
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService
|
||||
.logCommandSource(commandRequest);
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("{beneficiaryId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String update(@PathParam("beneficiaryId") final Long beneficiaryId,
|
||||
final String apiRequestBodyAsJson) {
|
||||
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder()
|
||||
.updateSelfServiceBeneficiaryTPT(beneficiaryId)
|
||||
.withJson(apiRequestBodyAsJson).build();
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService
|
||||
.logCommandSource(commandRequest);
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("{beneficiaryId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String delete(@PathParam("beneficiaryId") final Long beneficiaryId,
|
||||
final String apiRequestBodyAsJson) {
|
||||
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder()
|
||||
.deleteSelfServiceBeneficiaryTPT(beneficiaryId)
|
||||
.withJson(apiRequestBodyAsJson).build();
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService
|
||||
.logCommandSource(commandRequest);
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String retrieveAll(@Context final UriInfo uriInfo) {
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(
|
||||
SelfBeneficiariesTPTApiConstants.BENEFICIARY_ENTITY_NAME);
|
||||
|
||||
final Collection<SelfBeneficiariesTPTData> beneficiaries = this.readPlatformService
|
||||
.retrieveAll();
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper
|
||||
.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, beneficiaries,
|
||||
SelfBeneficiariesTPTApiConstants.RESPONSE_DATA_PARAMETERS);
|
||||
}
|
||||
|
||||
}
|
||||
+9
@@ -103,4 +103,13 @@ public class SelfAccountTemplateData implements
|
||||
.toHashCode();
|
||||
}
|
||||
|
||||
public Long getAccountId() {
|
||||
return this.accountId;
|
||||
}
|
||||
|
||||
public Integer getAccountType() {
|
||||
return this.accountType.getId().intValue();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+6
-3
@@ -23,11 +23,14 @@ import java.util.Collection;
|
||||
@SuppressWarnings("unused")
|
||||
public class SelfAccountTransferData {
|
||||
|
||||
private final Collection<SelfAccountTemplateData> accountOptions;
|
||||
private final Collection<SelfAccountTemplateData> fromAccountOptions;
|
||||
private final Collection<SelfAccountTemplateData> toAccountOptions;
|
||||
|
||||
public SelfAccountTransferData(
|
||||
final Collection<SelfAccountTemplateData> accountOptions) {
|
||||
this.accountOptions = accountOptions;
|
||||
final Collection<SelfAccountTemplateData> fromAccountOptions,
|
||||
Collection<SelfAccountTemplateData> toAccountOptions) {
|
||||
this.fromAccountOptions = fromAccountOptions;
|
||||
this.toAccountOptions = toAccountOptions;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+42
-7
@@ -27,10 +27,16 @@ import static org.apache.fineract.portfolio.account.AccountDetailConstants.toAcc
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.toClientIdParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.toOfficeIdParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.AccountTransfersApiConstants.ACCOUNT_TRANSFER_RESOURCE_NAME;
|
||||
import static org.apache.fineract.portfolio.account.api.AccountTransfersApiConstants.transferAmountParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.AccountTransfersApiConstants.transferDateParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.AccountTransfersApiConstants.transferDescriptionParamName;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
@@ -40,7 +46,9 @@ import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidati
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.portfolio.self.account.service.SelfAccountTransferReadService;
|
||||
import org.apache.fineract.portfolio.self.account.service.SelfBeneficiariesTPTReadPlatformService;
|
||||
import org.apache.fineract.useradministration.domain.AppUser;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -51,19 +59,22 @@ public class SelfAccountTransferDataValidator {
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final SelfAccountTransferReadService selfAccountTransferReadService;
|
||||
private final SelfBeneficiariesTPTReadPlatformService tptBeneficiaryReadPlatformService;
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
@Autowired
|
||||
public SelfAccountTransferDataValidator(
|
||||
final PlatformSecurityContext context,
|
||||
final SelfAccountTransferReadService selfAccountTransferReadService,
|
||||
final SelfBeneficiariesTPTReadPlatformService tptBeneficiaryReadPlatformService,
|
||||
final FromJsonHelper fromApiJsonHelper) {
|
||||
this.context = context;
|
||||
this.selfAccountTransferReadService = selfAccountTransferReadService;
|
||||
this.tptBeneficiaryReadPlatformService = tptBeneficiaryReadPlatformService;
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
}
|
||||
|
||||
public void validateCreate(String apiRequestBodyAsJson) {
|
||||
public Map<String,Object> validateCreate(String type, String apiRequestBodyAsJson) {
|
||||
if (StringUtils.isBlank(apiRequestBodyAsJson)) {
|
||||
throw new InvalidJsonException();
|
||||
}
|
||||
@@ -126,6 +137,16 @@ public class SelfAccountTransferDataValidator {
|
||||
"Cannot transfer from Loan account to another Loan account.");
|
||||
}
|
||||
|
||||
final LocalDate transactionDate = this.fromApiJsonHelper.extractLocalDateNamed(transferDateParamName, element);
|
||||
baseDataValidator.reset().parameter(transferDateParamName).value(transactionDate).notNull();
|
||||
|
||||
final BigDecimal transactionAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(transferAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(transferAmountParamName).value(transactionAmount).notNull().positiveAmount();
|
||||
|
||||
final String transactionDescription = this.fromApiJsonHelper.extractStringNamed(transferDescriptionParamName, element);
|
||||
baseDataValidator.reset().parameter(transferDescriptionParamName).value(transactionDescription).notBlank()
|
||||
.notExceedingLengthOf(200);
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
|
||||
SelfAccountTemplateData fromAccount = new SelfAccountTemplateData(
|
||||
@@ -133,21 +154,35 @@ public class SelfAccountTransferDataValidator {
|
||||
SelfAccountTemplateData toAccount = new SelfAccountTemplateData(
|
||||
toAccountId, toAccountType, toClientId, toOfficeId);
|
||||
|
||||
validateSelfUserAccounts(fromAccount, toAccount, baseDataValidator);
|
||||
validateUserAccounts(fromAccount, toAccount, baseDataValidator, type);
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
|
||||
Map<String, Object> ret = new HashMap<>();
|
||||
ret.put("fromAccount", fromAccount);
|
||||
ret.put("toAccount", toAccount);
|
||||
ret.put("transactionDate", transactionDate);
|
||||
ret.put("transactionAmount", transactionAmount);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
private void validateSelfUserAccounts(
|
||||
private void validateUserAccounts(
|
||||
final SelfAccountTemplateData fromAccount,
|
||||
final SelfAccountTemplateData toAccount,
|
||||
final DataValidatorBuilder baseDataValidator) {
|
||||
final DataValidatorBuilder baseDataValidator, final String type) {
|
||||
AppUser user = this.context.authenticatedUser();
|
||||
Collection<SelfAccountTemplateData> userValidAccounts = this.selfAccountTransferReadService
|
||||
Collection<SelfAccountTemplateData> validFromAccounts = this.selfAccountTransferReadService
|
||||
.retrieveSelfAccountTemplateData(user);
|
||||
|
||||
Collection<SelfAccountTemplateData> validToAccounts = validFromAccounts;
|
||||
if (type.equals("tpt")) {
|
||||
validToAccounts = this.tptBeneficiaryReadPlatformService
|
||||
.retrieveTPTSelfAccountTemplateData(user);
|
||||
}
|
||||
|
||||
boolean validFromAccount = false;
|
||||
for (SelfAccountTemplateData validAccount : userValidAccounts) {
|
||||
for (SelfAccountTemplateData validAccount : validFromAccounts) {
|
||||
if (validAccount.equals(fromAccount)) {
|
||||
validFromAccount = true;
|
||||
break;
|
||||
@@ -155,7 +190,7 @@ public class SelfAccountTransferDataValidator {
|
||||
}
|
||||
|
||||
boolean validToAccount = false;
|
||||
for (SelfAccountTemplateData validAccount : userValidAccounts) {
|
||||
for (SelfAccountTemplateData validAccount : validToAccounts) {
|
||||
if (validAccount.equals(toAccount)) {
|
||||
validToAccount = true;
|
||||
break;
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.self.account.data;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
|
||||
public class SelfBeneficiariesTPTData {
|
||||
@SuppressWarnings("unused")
|
||||
private final Long id;
|
||||
@SuppressWarnings("unused")
|
||||
private final String name;
|
||||
@SuppressWarnings("unused")
|
||||
private final String officeName;
|
||||
@SuppressWarnings("unused")
|
||||
private final String clientName;
|
||||
@SuppressWarnings("unused")
|
||||
private final EnumOptionData accountType;
|
||||
@SuppressWarnings("unused")
|
||||
private final String accountNumber;
|
||||
@SuppressWarnings("unused")
|
||||
private final Long transferLimit;
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<EnumOptionData> accountTypeOptions;
|
||||
|
||||
public SelfBeneficiariesTPTData(
|
||||
final Collection<EnumOptionData> accountTypeOptions) {
|
||||
this.accountTypeOptions = accountTypeOptions;
|
||||
this.id = null;
|
||||
this.name = null;
|
||||
this.officeName = null;
|
||||
this.clientName = null;
|
||||
this.accountType = null;
|
||||
this.accountNumber = null;
|
||||
this.transferLimit = null;
|
||||
}
|
||||
|
||||
public SelfBeneficiariesTPTData(final Long id, final String name,
|
||||
final String officeName, final String clientName,
|
||||
final EnumOptionData accountType, final String accountNumber,
|
||||
final Long transferLimit) {
|
||||
this.accountTypeOptions = null;
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.officeName = officeName;
|
||||
this.clientName = clientName;
|
||||
this.accountType = accountType;
|
||||
this.accountNumber = accountNumber;
|
||||
this.transferLimit = transferLimit;
|
||||
}
|
||||
|
||||
}
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.self.account.data;
|
||||
|
||||
import static org.apache.fineract.portfolio.self.account.api.SelfBeneficiariesTPTApiConstants.RESOURCE_NAME;
|
||||
import static org.apache.fineract.portfolio.self.account.api.SelfBeneficiariesTPTApiConstants.NAME_PARAM_NAME;
|
||||
import static org.apache.fineract.portfolio.self.account.api.SelfBeneficiariesTPTApiConstants.OFFICE_NAME_PARAM_NAME;
|
||||
import static org.apache.fineract.portfolio.self.account.api.SelfBeneficiariesTPTApiConstants.ACCOUNT_TYPE_PARAM_NAME;
|
||||
import static org.apache.fineract.portfolio.self.account.api.SelfBeneficiariesTPTApiConstants.ACCOUNT_NUMBER_PARAM_NAME;
|
||||
import static org.apache.fineract.portfolio.self.account.api.SelfBeneficiariesTPTApiConstants.TRANSFER_LIMIT_PARAM_NAME;
|
||||
import static org.apache.fineract.portfolio.self.account.api.SelfBeneficiariesTPTApiConstants.CREATE_REQUEST_DATA_PARAMETERS;
|
||||
import static org.apache.fineract.portfolio.self.account.api.SelfBeneficiariesTPTApiConstants.UPDATE_REQUEST_DATA_PARAMETERS;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
@Component
|
||||
public class SelfBeneficiariesTPTDataValidator {
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
@Autowired
|
||||
public SelfBeneficiariesTPTDataValidator(
|
||||
final FromJsonHelper fromApiJsonHelper) {
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
}
|
||||
|
||||
public HashMap<String, Object> validateForCreate(String json) {
|
||||
if (StringUtils.isBlank(json)) {
|
||||
throw new InvalidJsonException();
|
||||
}
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {
|
||||
}.getType();
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json,
|
||||
CREATE_REQUEST_DATA_PARAMETERS);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(
|
||||
dataValidationErrors).resource(RESOURCE_NAME);
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||
|
||||
final String name = this.fromApiJsonHelper.extractStringNamed(
|
||||
NAME_PARAM_NAME, element);
|
||||
baseDataValidator.reset().parameter(NAME_PARAM_NAME).value(name)
|
||||
.notBlank().notExceedingLengthOf(50);
|
||||
|
||||
final String officeName = this.fromApiJsonHelper.extractStringNamed(
|
||||
OFFICE_NAME_PARAM_NAME, element);
|
||||
baseDataValidator.reset().parameter(OFFICE_NAME_PARAM_NAME)
|
||||
.value(officeName).notBlank()
|
||||
.notExceedingLengthOf(50);
|
||||
|
||||
final String accountNo = this.fromApiJsonHelper.extractStringNamed(
|
||||
ACCOUNT_NUMBER_PARAM_NAME, element);
|
||||
baseDataValidator.reset().parameter(ACCOUNT_NUMBER_PARAM_NAME)
|
||||
.value(accountNo).notBlank().notExceedingLengthOf(20);
|
||||
|
||||
final Integer accountType = this.fromApiJsonHelper.extractIntegerNamed(
|
||||
ACCOUNT_TYPE_PARAM_NAME, element, this.fromApiJsonHelper
|
||||
.extractLocaleParameter(element.getAsJsonObject()));
|
||||
baseDataValidator
|
||||
.reset()
|
||||
.parameter(ACCOUNT_TYPE_PARAM_NAME)
|
||||
.value(accountType)
|
||||
.notNull()
|
||||
.isOneOfTheseValues(PortfolioAccountType.LOAN.getValue(),
|
||||
PortfolioAccountType.SAVINGS.getValue());
|
||||
|
||||
final Long transferLimit = this.fromApiJsonHelper.extractLongNamed(
|
||||
TRANSFER_LIMIT_PARAM_NAME, element);
|
||||
baseDataValidator.reset().parameter(TRANSFER_LIMIT_PARAM_NAME)
|
||||
.value(transferLimit).ignoreIfNull().longGreaterThanZero();
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
|
||||
HashMap<String, Object> ret = new HashMap<>();
|
||||
ret.put(NAME_PARAM_NAME, name);
|
||||
ret.put(OFFICE_NAME_PARAM_NAME, officeName);
|
||||
ret.put(ACCOUNT_NUMBER_PARAM_NAME, accountNo);
|
||||
ret.put(ACCOUNT_TYPE_PARAM_NAME, accountType);
|
||||
ret.put(TRANSFER_LIMIT_PARAM_NAME, transferLimit);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public HashMap<String, Object> validateForUpdate(String json) {
|
||||
if (StringUtils.isBlank(json)) {
|
||||
throw new InvalidJsonException();
|
||||
}
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {
|
||||
}.getType();
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json,
|
||||
UPDATE_REQUEST_DATA_PARAMETERS);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(
|
||||
dataValidationErrors).resource(RESOURCE_NAME);
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||
|
||||
HashMap<String, Object> ret = new HashMap<>();
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(NAME_PARAM_NAME, element)) {
|
||||
final String name = this.fromApiJsonHelper.extractStringNamed(
|
||||
NAME_PARAM_NAME, element);
|
||||
baseDataValidator.reset().parameter(NAME_PARAM_NAME).value(name)
|
||||
.notBlank().notExceedingLengthOf(50);
|
||||
ret.put(NAME_PARAM_NAME, name);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(TRANSFER_LIMIT_PARAM_NAME,
|
||||
element)) {
|
||||
final Long transferLimit = this.fromApiJsonHelper.extractLongNamed(
|
||||
TRANSFER_LIMIT_PARAM_NAME, element);
|
||||
baseDataValidator.reset().parameter(TRANSFER_LIMIT_PARAM_NAME)
|
||||
.value(transferLimit).ignoreIfNull().longGreaterThanZero();
|
||||
ret.put(TRANSFER_LIMIT_PARAM_NAME, transferLimit);
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void throwExceptionIfValidationWarningsExist(
|
||||
final List<ApiParameterError> dataValidationErrors) {
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.self.account.domain;
|
||||
|
||||
import static org.apache.fineract.portfolio.self.account.api.SelfBeneficiariesTPTApiConstants.NAME_PARAM_NAME;
|
||||
import static org.apache.fineract.portfolio.self.account.api.SelfBeneficiariesTPTApiConstants.TRANSFER_LIMIT_PARAM_NAME;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_selfservice_beneficiaries_tpt", uniqueConstraints = { @UniqueConstraint(columnNames = {
|
||||
"name", "app_user_id", "is_active" }, name = "name") })
|
||||
public class SelfBeneficiariesTPT extends AbstractPersistable<Long> {
|
||||
|
||||
@Column(name = "app_user_id", nullable = false)
|
||||
private Long appUserId;
|
||||
|
||||
@Column(name = "name", length = 50, nullable = false)
|
||||
private String name;
|
||||
|
||||
@Column(name = "office_id", nullable = false)
|
||||
private Long officeId;
|
||||
|
||||
@Column(name = "client_id", nullable = false)
|
||||
private Long clientId;
|
||||
|
||||
@Column(name = "account_id", nullable = false)
|
||||
private Long accountId;
|
||||
|
||||
@Column(name = "account_type", nullable = false)
|
||||
private Integer accountType;
|
||||
|
||||
@Column(name = "transfer_limit", nullable = true)
|
||||
private Long transferLimit;
|
||||
|
||||
@Column(name = "is_active", nullable = false)
|
||||
private boolean isActive = true;
|
||||
|
||||
protected SelfBeneficiariesTPT() {
|
||||
//
|
||||
}
|
||||
|
||||
public SelfBeneficiariesTPT(Long appUserId, String name, Long officeId,
|
||||
Long clientId, Long accountId, Integer accountType,
|
||||
Long transferLimit) {
|
||||
this.appUserId = appUserId;
|
||||
this.name = name;
|
||||
this.officeId = officeId;
|
||||
this.clientId = clientId;
|
||||
this.accountId = accountId;
|
||||
this.accountType = accountType;
|
||||
this.transferLimit = transferLimit;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Long getTransferLimit() {
|
||||
return this.transferLimit;
|
||||
}
|
||||
|
||||
public void setTransferLimit(Long transferLimit) {
|
||||
this.transferLimit = transferLimit;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return this.isActive;
|
||||
}
|
||||
|
||||
public void setActive(boolean isActive) {
|
||||
this.isActive = isActive;
|
||||
}
|
||||
|
||||
public Long getAppUserId() {
|
||||
return this.appUserId;
|
||||
}
|
||||
|
||||
public Long getOfficeId() {
|
||||
return this.officeId;
|
||||
}
|
||||
|
||||
public Long getClientId() {
|
||||
return this.clientId;
|
||||
}
|
||||
|
||||
public Long getAccountId() {
|
||||
return this.accountId;
|
||||
}
|
||||
|
||||
public Integer getAccountType() {
|
||||
return this.accountType;
|
||||
}
|
||||
|
||||
public Map<String, Object> update(String newName, Long newTransferLimit) {
|
||||
Map<String, Object> changes = new HashMap<>();
|
||||
if (!this.name.equals(newName)) {
|
||||
this.name = newName;
|
||||
changes.put(NAME_PARAM_NAME, newName);
|
||||
}
|
||||
if ((this.transferLimit !=null && !this.transferLimit.equals(newTransferLimit))
|
||||
|| (this.transferLimit == null && newTransferLimit != null)) {
|
||||
this.transferLimit = newTransferLimit;
|
||||
changes.put(TRANSFER_LIMIT_PARAM_NAME, newTransferLimit);
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.self.account.domain;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
public interface SelfBeneficiariesTPTRepository extends
|
||||
JpaRepository<SelfBeneficiariesTPT, Long>,
|
||||
JpaSpecificationExecutor<SelfBeneficiariesTPT> {
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.self.account.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
public class BeneficiaryTransferLimitExceededException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public BeneficiaryTransferLimitExceededException() {
|
||||
super("error.msg.beneficiary.transfer.amount.limit.for.beneficiary.exceeded",
|
||||
"Transfer amount limit for beneficiary exceeded");
|
||||
}
|
||||
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.self.account.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
public class DailyTPTTransactionAmountLimitExceededException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public DailyTPTTransactionAmountLimitExceededException(Long accountId,
|
||||
Integer accountType) {
|
||||
super("error.msg.beneficiary.daily.tpt.transfer.limit.for.fromaccountid."+accountId+".fromaccounttype."+accountType+".exceeded",
|
||||
"Daily third party transfer limit for the source account excceeded");
|
||||
}
|
||||
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.self.account.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
public class InvalidAccountInformationException extends
|
||||
AbstractPlatformDomainRuleException {
|
||||
public InvalidAccountInformationException(final String officeName,
|
||||
final String accountNumber, final String accountType) {
|
||||
super("error.msg.beneficiary.invalid.account.details.with.officeName."
|
||||
+ officeName + ".accountNumber." + accountNumber
|
||||
+ ".accountType." + accountType,
|
||||
"Invalid Office Name, Account Number, Account Type combination");
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.self.account.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
public class InvalidBeneficiaryException extends
|
||||
AbstractPlatformDomainRuleException {
|
||||
public InvalidBeneficiaryException(final Long beneficiaryId) {
|
||||
super("error.msg.beneficiary.invalid.beneficiary.id." + beneficiaryId,
|
||||
"Beneficiary ID doesn't belong to the User");
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.self.account.handler;
|
||||
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.self.account.service.SelfBeneficiariesTPTWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@CommandType(entity = "SSBENEFICIARYTPT", action = "CREATE")
|
||||
public class AddSelfBeneficiariesTPTCommandHandler implements
|
||||
NewCommandSourceHandler {
|
||||
private final SelfBeneficiariesTPTWritePlatformService writePlatformService;
|
||||
|
||||
@Autowired
|
||||
public AddSelfBeneficiariesTPTCommandHandler(
|
||||
final SelfBeneficiariesTPTWritePlatformService writePlatformService) {
|
||||
this.writePlatformService = writePlatformService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
return this.writePlatformService.add(command);
|
||||
}
|
||||
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.self.account.handler;
|
||||
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.self.account.service.SelfBeneficiariesTPTWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@CommandType(entity = "SSBENEFICIARYTPT", action = "DELETE")
|
||||
public class DeleteSelfBeneficiariesTPTCommandHandler implements
|
||||
NewCommandSourceHandler {
|
||||
private final SelfBeneficiariesTPTWritePlatformService writePlatformService;
|
||||
|
||||
@Autowired
|
||||
public DeleteSelfBeneficiariesTPTCommandHandler(
|
||||
final SelfBeneficiariesTPTWritePlatformService writePlatformService) {
|
||||
this.writePlatformService = writePlatformService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
return this.writePlatformService.delete(command);
|
||||
}
|
||||
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.self.account.handler;
|
||||
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.self.account.service.SelfBeneficiariesTPTWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@CommandType(entity = "SSBENEFICIARYTPT", action = "UPDATE")
|
||||
public class UpdateSelfBeneficiariesTPTCommandHandler implements
|
||||
NewCommandSourceHandler {
|
||||
private final SelfBeneficiariesTPTWritePlatformService writePlatformService;
|
||||
|
||||
@Autowired
|
||||
public UpdateSelfBeneficiariesTPTCommandHandler(
|
||||
final SelfBeneficiariesTPTWritePlatformService writePlatformService) {
|
||||
this.writePlatformService = writePlatformService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
return this.writePlatformService.update(command);
|
||||
}
|
||||
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.self.account.service;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.fineract.portfolio.self.account.data.SelfAccountTemplateData;
|
||||
import org.apache.fineract.portfolio.self.account.data.SelfBeneficiariesTPTData;
|
||||
import org.apache.fineract.useradministration.domain.AppUser;
|
||||
|
||||
public interface SelfBeneficiariesTPTReadPlatformService {
|
||||
|
||||
Collection<SelfBeneficiariesTPTData> retrieveAll();
|
||||
|
||||
Collection<SelfAccountTemplateData> retrieveTPTSelfAccountTemplateData(
|
||||
AppUser user);
|
||||
|
||||
Long getTransferLimit(Long id, Long accountId, Integer accountType);
|
||||
|
||||
}
|
||||
+222
@@ -0,0 +1,222 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.self.account.service;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
||||
import org.apache.fineract.portfolio.account.service.AccountTransferEnumerations;
|
||||
import org.apache.fineract.portfolio.self.account.data.SelfAccountTemplateData;
|
||||
import org.apache.fineract.portfolio.self.account.data.SelfBeneficiariesTPTData;
|
||||
import org.apache.fineract.useradministration.domain.AppUser;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class SelfBeneficiariesTPTReadPlatformServiceImpl implements
|
||||
SelfBeneficiariesTPTReadPlatformService {
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final BeneficiaryMapper mapper;
|
||||
private final AccountTemplateMapper accountTemplateMapper;
|
||||
|
||||
@Autowired
|
||||
public SelfBeneficiariesTPTReadPlatformServiceImpl(
|
||||
final PlatformSecurityContext context,
|
||||
final RoutingDataSource dataSource) {
|
||||
this.context = context;
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
this.mapper = new BeneficiaryMapper();
|
||||
this.accountTemplateMapper = new AccountTemplateMapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SelfBeneficiariesTPTData> retrieveAll() {
|
||||
AppUser user = this.context.authenticatedUser();
|
||||
return this.jdbcTemplate.query(this.mapper.schema(), this.mapper,
|
||||
new Object[] { user.getId(), user.getId() });
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SelfAccountTemplateData> retrieveTPTSelfAccountTemplateData(
|
||||
AppUser user) {
|
||||
return this.jdbcTemplate.query(this.accountTemplateMapper.schema(),
|
||||
this.accountTemplateMapper,
|
||||
new Object[] { user.getId(), user.getId() });
|
||||
}
|
||||
|
||||
private static final class BeneficiaryMapper implements
|
||||
RowMapper<SelfBeneficiariesTPTData> {
|
||||
|
||||
private final String schemaSql;
|
||||
|
||||
public BeneficiaryMapper() {
|
||||
final StringBuilder sqlBuilder = new StringBuilder(
|
||||
"(select b.id as id, ");
|
||||
sqlBuilder.append(" b.name as name, ");
|
||||
sqlBuilder.append(" o.name as officeName, ");
|
||||
sqlBuilder.append(" c.display_name as clientName, ");
|
||||
sqlBuilder.append(" b.account_type as accountType, ");
|
||||
sqlBuilder.append(" s.account_no as accountNumber, ");
|
||||
sqlBuilder.append(" b.transfer_limit as transferLimit ");
|
||||
sqlBuilder.append(" from m_selfservice_beneficiaries_tpt as b ");
|
||||
sqlBuilder
|
||||
.append(" inner join m_office as o on b.office_id = o.id ");
|
||||
sqlBuilder
|
||||
.append(" inner join m_client as c on b.client_id = c.id ");
|
||||
sqlBuilder
|
||||
.append(" inner join m_savings_account as s on b.account_id = s.id ");
|
||||
sqlBuilder.append(" where b.is_active = 1 ");
|
||||
sqlBuilder.append(" and b.account_type = 2 ");
|
||||
sqlBuilder.append(" and b.app_user_id = ?) ");
|
||||
sqlBuilder.append(" union all ");
|
||||
sqlBuilder.append(" (select b.id as id, ");
|
||||
sqlBuilder.append(" b.name as name, ");
|
||||
sqlBuilder.append(" o.name as officeName, ");
|
||||
sqlBuilder.append(" c.display_name as clientName, ");
|
||||
sqlBuilder.append(" b.account_type as accountType, ");
|
||||
sqlBuilder.append(" l.account_no as accountNumber, ");
|
||||
sqlBuilder.append(" b.transfer_limit as transferLimit ");
|
||||
sqlBuilder.append(" from m_selfservice_beneficiaries_tpt as b ");
|
||||
sqlBuilder
|
||||
.append(" inner join m_office as o on b.office_id = o.id ");
|
||||
sqlBuilder
|
||||
.append(" inner join m_client as c on b.client_id = c.id ");
|
||||
sqlBuilder
|
||||
.append(" inner join m_loan as l on b.account_id = l.id ");
|
||||
sqlBuilder.append(" where b.is_active = 1 ");
|
||||
sqlBuilder.append(" and b.account_type = 1 ");
|
||||
sqlBuilder.append(" and b.app_user_id = ?) ");
|
||||
|
||||
this.schemaSql = sqlBuilder.toString();
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
return this.schemaSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SelfBeneficiariesTPTData mapRow(final ResultSet rs,
|
||||
@SuppressWarnings("unused") final int rowNum)
|
||||
throws SQLException {
|
||||
|
||||
final Long id = rs.getLong("id");
|
||||
final String name = rs.getString("name");
|
||||
final String officeName = rs.getString("officeName");
|
||||
final String clientName = rs.getString("clientName");
|
||||
final Integer accountTypeId = rs.getInt("accountType");
|
||||
final EnumOptionData accountType = AccountTransferEnumerations
|
||||
.accountType(PortfolioAccountType.fromInt(accountTypeId));
|
||||
final String accountNumber = rs.getString("accountNumber");
|
||||
final Long transferLimit = rs.getLong("transferLimit");
|
||||
|
||||
return new SelfBeneficiariesTPTData(id, name, officeName,
|
||||
clientName, accountType, accountNumber, transferLimit);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class AccountTemplateMapper implements
|
||||
RowMapper<SelfAccountTemplateData> {
|
||||
|
||||
private final String schemaSql;
|
||||
|
||||
public AccountTemplateMapper() {
|
||||
final StringBuilder sqlBuilder = new StringBuilder(
|
||||
"(select o.name as officeName, ");
|
||||
sqlBuilder.append(" o.id as officeId, ");
|
||||
sqlBuilder.append(" c.display_name as clientName, ");
|
||||
sqlBuilder.append(" c.id as clientId, ");
|
||||
sqlBuilder.append(" b.account_type as accountType, ");
|
||||
sqlBuilder.append(" s.account_no as accountNumber, ");
|
||||
sqlBuilder.append(" s.id as accountId ");
|
||||
sqlBuilder.append(" from m_selfservice_beneficiaries_tpt as b ");
|
||||
sqlBuilder
|
||||
.append(" inner join m_office as o on b.office_id = o.id ");
|
||||
sqlBuilder
|
||||
.append(" inner join m_client as c on b.client_id = c.id ");
|
||||
sqlBuilder
|
||||
.append(" inner join m_savings_account as s on b.account_id = s.id ");
|
||||
sqlBuilder.append(" where b.is_active = 1 ");
|
||||
sqlBuilder.append(" and b.account_type = 2 ");
|
||||
sqlBuilder.append(" and b.app_user_id = ?) ");
|
||||
sqlBuilder.append(" union all ");
|
||||
sqlBuilder.append(" (select o.name as officeName, ");
|
||||
sqlBuilder.append(" o.id as officeId, ");
|
||||
sqlBuilder.append(" c.display_name as clientName, ");
|
||||
sqlBuilder.append(" c.id as clientId, ");
|
||||
sqlBuilder.append(" b.account_type as accountType, ");
|
||||
sqlBuilder.append(" l.account_no as accountNumber, ");
|
||||
sqlBuilder.append(" l.id as accountId ");
|
||||
sqlBuilder.append(" from m_selfservice_beneficiaries_tpt as b ");
|
||||
sqlBuilder
|
||||
.append(" inner join m_office as o on b.office_id = o.id ");
|
||||
sqlBuilder
|
||||
.append(" inner join m_client as c on b.client_id = c.id ");
|
||||
sqlBuilder
|
||||
.append(" inner join m_loan as l on b.account_id = l.id ");
|
||||
sqlBuilder.append(" where b.is_active = 1 ");
|
||||
sqlBuilder.append(" and b.account_type = 1 ");
|
||||
sqlBuilder.append(" and b.app_user_id = ?) ");
|
||||
|
||||
this.schemaSql = sqlBuilder.toString();
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
return this.schemaSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SelfAccountTemplateData mapRow(final ResultSet rs,
|
||||
@SuppressWarnings("unused") final int rowNum)
|
||||
throws SQLException {
|
||||
|
||||
final String officeName = rs.getString("officeName");
|
||||
final Long officeId = rs.getLong("officeId");
|
||||
final String clientName = rs.getString("clientName");
|
||||
final Long clientId = rs.getLong("clientId");
|
||||
final Integer accountTypeId = rs.getInt("accountType");
|
||||
final String accountNumber = rs.getString("accountNumber");
|
||||
final Long accountId = rs.getLong("accountId");
|
||||
|
||||
return new SelfAccountTemplateData(accountId, accountNumber,
|
||||
accountTypeId, clientId, clientName, officeId, officeName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getTransferLimit(Long appUserId, Long accountId, Integer accountType) {
|
||||
final StringBuilder sqlBuilder = new StringBuilder("select b.transfer_limit ");
|
||||
sqlBuilder.append(" from m_selfservice_beneficiaries_tpt as b ");
|
||||
sqlBuilder.append(" where b.app_user_id = ? ");
|
||||
sqlBuilder.append(" and b.account_id = ? ");
|
||||
sqlBuilder.append(" and b.account_type = ? ");
|
||||
sqlBuilder.append(" and b.is_active = 1; ");
|
||||
|
||||
return this.jdbcTemplate.queryForObject(sqlBuilder.toString(),
|
||||
new Object[]{appUserId, accountId, accountType}, Long.class);
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.self.account.service;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
|
||||
public interface SelfBeneficiariesTPTWritePlatformService {
|
||||
|
||||
CommandProcessingResult add(JsonCommand command);
|
||||
|
||||
CommandProcessingResult update(JsonCommand command);
|
||||
|
||||
CommandProcessingResult delete(JsonCommand command);
|
||||
|
||||
}
|
||||
+212
@@ -0,0 +1,212 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.self.account.service;
|
||||
|
||||
import static org.apache.fineract.portfolio.self.account.api.SelfBeneficiariesTPTApiConstants.ACCOUNT_NUMBER_PARAM_NAME;
|
||||
import static org.apache.fineract.portfolio.self.account.api.SelfBeneficiariesTPTApiConstants.ACCOUNT_TYPE_PARAM_NAME;
|
||||
import static org.apache.fineract.portfolio.self.account.api.SelfBeneficiariesTPTApiConstants.NAME_PARAM_NAME;
|
||||
import static org.apache.fineract.portfolio.self.account.api.SelfBeneficiariesTPTApiConstants.OFFICE_NAME_PARAM_NAME;
|
||||
import static org.apache.fineract.portfolio.self.account.api.SelfBeneficiariesTPTApiConstants.TRANSFER_LIMIT_PARAM_NAME;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountRepository;
|
||||
import org.apache.fineract.portfolio.self.account.data.SelfBeneficiariesTPTDataValidator;
|
||||
import org.apache.fineract.portfolio.self.account.domain.SelfBeneficiariesTPT;
|
||||
import org.apache.fineract.portfolio.self.account.domain.SelfBeneficiariesTPTRepository;
|
||||
import org.apache.fineract.portfolio.self.account.exception.InvalidAccountInformationException;
|
||||
import org.apache.fineract.portfolio.self.account.exception.InvalidBeneficiaryException;
|
||||
import org.apache.fineract.useradministration.domain.AppUser;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class SelfBeneficiariesTPTWritePlatformServiceImpl implements
|
||||
SelfBeneficiariesTPTWritePlatformService {
|
||||
|
||||
private final Logger logger;
|
||||
private final PlatformSecurityContext context;
|
||||
private final SelfBeneficiariesTPTRepository repository;
|
||||
private final SelfBeneficiariesTPTDataValidator validator;
|
||||
private final LoanRepository loanRepo;
|
||||
private final SavingsAccountRepository savingRepo;
|
||||
|
||||
@Autowired
|
||||
public SelfBeneficiariesTPTWritePlatformServiceImpl(
|
||||
final PlatformSecurityContext context,
|
||||
final SelfBeneficiariesTPTRepository repository,
|
||||
final SelfBeneficiariesTPTDataValidator validator,
|
||||
final LoanRepository loanRepo,
|
||||
final SavingsAccountRepository savingRepo) {
|
||||
this.context = context;
|
||||
this.repository = repository;
|
||||
this.validator = validator;
|
||||
this.loanRepo = loanRepo;
|
||||
this.savingRepo = savingRepo;
|
||||
this.logger = LoggerFactory
|
||||
.getLogger(SelfBeneficiariesTPTWritePlatformServiceImpl.class);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult add(JsonCommand command) {
|
||||
HashMap<String, Object> params = this.validator
|
||||
.validateForCreate(command.json());
|
||||
|
||||
String name = (String) params.get(NAME_PARAM_NAME);
|
||||
Integer accountType = (Integer) params.get(ACCOUNT_TYPE_PARAM_NAME);
|
||||
String accountNumber = (String) params.get(ACCOUNT_NUMBER_PARAM_NAME);
|
||||
String officeName = (String) params.get(OFFICE_NAME_PARAM_NAME);
|
||||
Long transferLimit = (Long) params.get(TRANSFER_LIMIT_PARAM_NAME);
|
||||
|
||||
Long accountId = null;
|
||||
Long clientId = null;
|
||||
Long officeId = null;
|
||||
|
||||
boolean validAccountDetails = true;
|
||||
if (accountType.equals(PortfolioAccountType.LOAN)) {
|
||||
Loan loan = this.loanRepo
|
||||
.findNonClosedLoanByAccountNumber(accountNumber);
|
||||
if (loan != null && loan.getClientId() != null
|
||||
&& loan.getOffice().getName().equals(officeName)) {
|
||||
accountId = loan.getId();
|
||||
officeId = loan.getOfficeId();
|
||||
clientId = loan.getClientId();
|
||||
} else {
|
||||
validAccountDetails = false;
|
||||
}
|
||||
} else {
|
||||
SavingsAccount savings = this.savingRepo
|
||||
.findNonClosedAccountByAccountNumber(accountNumber);
|
||||
if (savings != null
|
||||
&& savings.getClient() != null
|
||||
&& savings.getClient().getOffice().getName()
|
||||
.equals(officeName)) {
|
||||
accountId = savings.getId();
|
||||
clientId = savings.getClient().getId();
|
||||
officeId = savings.getClient().getOffice().getId();
|
||||
} else {
|
||||
validAccountDetails = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (validAccountDetails) {
|
||||
try {
|
||||
AppUser user = this.context.authenticatedUser();
|
||||
SelfBeneficiariesTPT beneficiary = new SelfBeneficiariesTPT(
|
||||
user.getId(), name, officeId, clientId, accountId,
|
||||
accountType, transferLimit);
|
||||
this.repository.save(beneficiary);
|
||||
return new CommandProcessingResultBuilder().withEntityId(
|
||||
beneficiary.getId()).build();
|
||||
} catch (DataAccessException dae) {
|
||||
handleDataIntegrityIssues(command, dae);
|
||||
}
|
||||
}
|
||||
throw new InvalidAccountInformationException(officeName, accountNumber,
|
||||
PortfolioAccountType.fromInt(accountType).getCode());
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult update(JsonCommand command) {
|
||||
HashMap<String, Object> params = this.validator
|
||||
.validateForUpdate(command.json());
|
||||
AppUser user = this.context.authenticatedUser();
|
||||
Long beneficiaryId = command.entityId();
|
||||
SelfBeneficiariesTPT beneficiary = this.repository
|
||||
.findOne(beneficiaryId);
|
||||
if (beneficiary != null
|
||||
&& beneficiary.getAppUserId().equals(user.getId())) {
|
||||
String name = (String) params.get(NAME_PARAM_NAME);
|
||||
Long transferLimit = (Long) params.get(TRANSFER_LIMIT_PARAM_NAME);
|
||||
|
||||
Map<String, Object> changes = beneficiary.update(name,
|
||||
transferLimit);
|
||||
if (!changes.isEmpty()) {
|
||||
try {
|
||||
this.repository.save(beneficiary);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withEntityId(beneficiary.getId()) //
|
||||
.with(changes).build();
|
||||
} catch (DataAccessException dae) {
|
||||
handleDataIntegrityIssues(command, dae);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
throw new InvalidBeneficiaryException(beneficiaryId);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult delete(JsonCommand command) {
|
||||
AppUser user = this.context.authenticatedUser();
|
||||
Long beneficiaryId = command.entityId();
|
||||
SelfBeneficiariesTPT beneficiary = this.repository
|
||||
.findOne(beneficiaryId);
|
||||
if (beneficiary != null
|
||||
&& beneficiary.getAppUserId().equals(user.getId())) {
|
||||
|
||||
beneficiary.setActive(false);
|
||||
this.repository.save(beneficiary);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withEntityId(beneficiary.getId()) //
|
||||
.build();
|
||||
}
|
||||
throw new InvalidBeneficiaryException(beneficiaryId);
|
||||
}
|
||||
|
||||
private void handleDataIntegrityIssues(final JsonCommand command,
|
||||
final DataAccessException dae) {
|
||||
|
||||
final Throwable realCause = dae.getMostSpecificCause();
|
||||
if (realCause.getMessage().contains("name")) {
|
||||
|
||||
final String name = command
|
||||
.stringValueOfParameterNamed(NAME_PARAM_NAME);
|
||||
throw new PlatformDataIntegrityException(
|
||||
"error.msg.beneficiary.duplicate.name",
|
||||
"Beneficiary with name `" + name + "` already exists",
|
||||
NAME_PARAM_NAME, name);
|
||||
}
|
||||
|
||||
this.logger.error(dae.getMessage(), dae);
|
||||
throw new PlatformDataIntegrityException(
|
||||
"error.msg.beneficiary.unknown.data.integrity.issue",
|
||||
"Unknown data integrity issue with resource.");
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
INSERT INTO `c_configuration` (`name`, `value`, `date_value`, `enabled`, `is_trap_door`, `description`) VALUES ( 'daily-tpt-limit', 0, NULL, 0, 0, 'Daily limit for third party transfers');
|
||||
|
||||
CREATE TABLE `m_selfservice_beneficiaries_tpt` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`app_user_id` BIGINT NOT NULL,
|
||||
`name` VARCHAR(50) NOT NULL,
|
||||
`office_id` BIGINT NOT NULL,
|
||||
`client_id` BIGINT NOT NULL,
|
||||
`account_id` BIGINT NOT NULL,
|
||||
`account_type` SMALLINT(4) NOT NULL,
|
||||
`transfer_limit` BIGINT NULL DEFAULT 0,
|
||||
`is_active` BIT(1) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE INDEX `name` (`name`, `app_user_id`, `is_active`)
|
||||
)
|
||||
COLLATE='utf8_general_ci'
|
||||
ENGINE=InnoDB
|
||||
;
|
||||
|
||||
INSERT INTO `m_permission`(`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES
|
||||
('SSBENEFICIARYTPT', 'READ_SSBENEFICIARYTPT', 'SSBENEFICIARYTPT', 'READ', 0),
|
||||
('SSBENEFICIARYTPT', 'CREATE_SSBENEFICIARYTPT', 'SSBENEFICIARYTPT', 'CREATE', 0),
|
||||
('SSBENEFICIARYTPT', 'UPDATE_SSBENEFICIARYTPT', 'SSBENEFICIARYTPT', 'UPDATE', 0),
|
||||
('SSBENEFICIARYTPT', 'DELETE_SSBENEFICIARYTPT', 'SSBENEFICIARYTPT', 'DELETE', 0);
|
||||
Reference in New Issue
Block a user