diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm
index c2fa3283c..3139b1a5b 100644
--- a/api-docs/apiLive.htm
+++ b/api-docs/apiLive.htm
@@ -3312,6 +3312,38 @@
|
|
+
+ | Beneficiary for Third Party Transfer |
+ /self/beneficiaries/tpt/template |
+ |
+ Beneficiary TPT Template |
+ |
+ |
+
+
+ |
+ /self/beneficiaries/tpt |
+ Add TPT Beneficiary |
+ Get TPT Beneficiary List |
+ Update TPT Beneficiary |
+ Delete TPT Beneficiary |
+
+
+ | Third Party Account Transfers |
+ self/accounttransfers/template?type="tpt" |
+ |
+ Third Party Account Transfer Template |
+ |
+ |
+
+
+ |
+ self/accounttransfers?type="tpt" |
+ Third Party Account Transfer |
+ |
+ |
+ |
+
@@ -42193,7 +42225,35 @@ GET https://DomainName/api/v1/self/savingsaccounts/{accountId}/charges/{savingsA
{
- "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"
}
]
+
}
@@ -42262,6 +42323,322 @@ No Request Body:
+
+
+
+
Beneficiary Third Party Transfer Template
+
Returns Account Type enumerations. Self User is expected to know office name and account number to be able to add beneficiary.
+
Example Requests:
+
/self/beneficiaries/tpt/template
+
+
+ GET https://DomainName/api/v1/self/beneficiaries/tpt/template
+
+
+ {
+ "accountTypeOptions":
+ [
+ {
+ "id": 2,
+ "code": "accountType.savings",
+ "value": "Savings Account"
+ },
+ {
+ "id": 1,
+ "code": "accountType.loan",
+ "value": "Loan Account"
+ }
+ ]
+ }
+
+
+
+
+
+
+
+
Add TPT Beneficiary
+
Api to add third party beneficiary linked to current user.
+
Parameter Definitions
+
name : Nick name for beneficiary, should be unique for an self service user
+
officeName : Office Name of beneficiary(not id)
+
accountNumber : Account Number of beneficiary(not id)
+
transferLimit : Each transfer initiated to this account will not exceed this amount
+
Example Requests:
+
/self/beneficiaries/tpt
+
+
+ Mandatory Fields |
+
+
+ | name, officeName, accountNumber, accountType |
+
+
+
+
+
+ Optional Fields |
+
+
+ | transferLimit
+ |
+
+
+
+
+
+ POST https://DomainName/api/v1/self/beneficiaries/tpt
+
+
+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
+
+}
+
+
+{
+ "resourceId": 5
+}
+
+
+
+
+
+
+
+
Get All TPT Beneficiary
+
Api to get all third party beneficiary linked to current user.
+
Example Requests:
+
/self/beneficiaries/tpt
+
+
+
+ GET https://DomainName/api/v1/self/beneficiaries/tpt
+
+
+GET self/beneficiaries/tpt
+Content-Type: application/json
+
+
+{
+[
+ {
+ "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
+ }]
+}
+
+
+
+
+
+
+
+
Update TPT Beneficiary
+
Api to update third party beneficiary linked to current user.
+
Example Requests:
+
/self/beneficiaries/tpt/{beneficiaryId}
+
+
+
+ Optional Fields |
+
+
+ | name, transferLimit
+ |
+
+
+
+
+
+ PUT https://DomainName/api/v1/self/beneficiaries/tpt/{beneficiaryId}
+
+
+PUT self/beneficiaries/tpt/5
+Content-Type: application/json
+Request Body:
+{
+ "name": "beneficiary nick name",
+ "transferLimit": 1000
+
+}
+
+
+{
+ "resourceId": 5,
+ "changes": {
+ "transferLimit": 1000,
+ "name": "Client22"
+ }
+}
+
+
+
+
+
+
+
+
Delete TPT Beneficiary
+
Api to delete third party beneficiary linked to current user.
+
Example Requests:
+
/self/beneficiaries/tpt/{beneficiaryId}
+
+
+
+ DELETE https://DomainName/api/v1/self/beneficiaries/tpt/{beneficiaryId}
+
+
+DELETE self/beneficiaries/tpt/5
+Content-Type: application/json
+
+
+{
+ "resourceId": 5
+}
+
+
+
+
+
+
+
+
Third Party Account Transfer Template
+
Returns list of loan/savings accounts that can be used for third party account transfer
+
Example Requests:
+
self/accounttransfers/template?type="tpt"
+
+
+ GET https://DomainName/api/v1/self/accounttransfers/template?type="tpt"
+
+
+{
+ "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"
+ }
+ ]
+
+}
+
+
+
+
+
+
+
+
Third Party Account Transfer
+
Ability to create new third party transfer of monetary funds from one account to another.
+
+
+ POST https://DomainName/api/v1/self/accounttransfers?type="tpt"
+ 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"
+}
+
+
+{
+ "savingsId": 1,
+ "resourceId": 1
+}
+
+
+
diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
index bd1357494..5751e0e3d 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
@@ -2702,4 +2702,29 @@ public class CommandWrapperBuilder {
this.href = "/savingsaccounts/" + accountId + "?commad=updateTaxWithHoldTax";
return this;
}
+
+ public CommandWrapperBuilder addSelfServiceBeneficiaryTPT() {
+ this.actionName = "CREATE";
+ this.entityName = "SSBENEFICIARYTPT";
+ this.entityId = null;
+ this.href = "/self/beneficiaries/tpt";
+ return this;
+ }
+
+ public CommandWrapperBuilder updateSelfServiceBeneficiaryTPT(final Long beneficiaryId) {
+ this.actionName = "UPDATE";
+ this.entityName = "SSBENEFICIARYTPT";
+ this.entityId = beneficiaryId;
+ this.href = "/self/beneficiaries/tpt/"+beneficiaryId;
+ return this;
+ }
+
+ public CommandWrapperBuilder deleteSelfServiceBeneficiaryTPT(final Long beneficiaryId) {
+ this.actionName = "DELETE";
+ this.entityName = "SSBENEFICIARYTPT";
+ this.entityId = beneficiaryId;
+ this.href = "/self/beneficiaries/tpt/"+beneficiaryId;
+ return this;
+ }
+
}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java
index 75aefb219..58494c271 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java
@@ -79,4 +79,8 @@ public interface ConfigurationDomainService {
boolean isChangeEmiIfRepaymentDateSameAsDisbursementDateEnabled();
+ boolean isDailyTPTLimitEnabled();
+
+ Long getDailyTPTLimit();
+
}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java
index 356d098e7..67ebdc5ba 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java
@@ -19,6 +19,7 @@
package org.apache.fineract.infrastructure.configuration.domain;
import java.util.Date;
+
import org.apache.commons.lang.StringUtils;
import org.apache.fineract.infrastructure.cache.domain.CacheType;
import org.apache.fineract.infrastructure.cache.domain.PlatformCache;
@@ -209,6 +210,7 @@ public class ConfigurationDomainServiceJpa implements ConfigurationDomainService
return defaultValue;
}
+ @Override
public boolean isBackdatePenaltiesEnabled() {
final String propertyName = "backdate-penalties-enabled";
final GlobalConfigurationProperty property = this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
@@ -263,5 +265,19 @@ public class ConfigurationDomainServiceJpa implements ConfigurationDomainService
return property.isEnabled();
}
+ @Override
+ public boolean isDailyTPTLimitEnabled() {
+ final String propertyName = "daily-tpt-limit";
+ final GlobalConfigurationProperty property = this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+ return property.isEnabled();
+ }
+
+ @Override
+ public Long getDailyTPTLimit() {
+ final String propertyName = "daily-tpt-limit";
+ final GlobalConfigurationProperty property = this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+ return property.getValue();
+ }
+
}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/TenantDatabaseUpgradeService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/TenantDatabaseUpgradeService.java
index 8bf9199b4..740dcb57b 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/TenantDatabaseUpgradeService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/TenantDatabaseUpgradeService.java
@@ -74,7 +74,7 @@ public class TenantDatabaseUpgradeService {
flyway.migrate();
} catch (FlywayException e) {
String betterMessage = e.getMessage() + "; for Tenant DB URL: " + connectionProtocol + ", username: "
- + connection.getSchemaPassword();
+ + connection.getSchemaUsername();
throw new FlywayException(betterMessage, e.getCause());
}
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/SchedularWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/SchedularWritePlatformServiceJpaRepositoryImpl.java
index f4ac6ac63..7e5d5de73 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/SchedularWritePlatformServiceJpaRepositoryImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/SchedularWritePlatformServiceJpaRepositoryImpl.java
@@ -136,11 +136,11 @@ public class SchedularWritePlatformServiceJpaRepositoryImpl implements Schedular
boolean isStopExecution = false;
final ScheduledJobDetail scheduledJobDetail = this.scheduledJobDetailsRepository.findByJobKeyWithLock(jobKey);
if (scheduledJobDetail.isCurrentlyRunning()
- || (triggerType == SchedulerServiceConstants.TRIGGER_TYPE_CRON && (scheduledJobDetail.getNextRunTime().after(new Date())))) {
+ || (triggerType.equals(SchedulerServiceConstants.TRIGGER_TYPE_CRON) && (scheduledJobDetail.getNextRunTime().after(new Date())))) {
isStopExecution = true;
}
final SchedulerDetail schedulerDetail = retriveSchedulerDetail();
- if (triggerType == SchedulerServiceConstants.TRIGGER_TYPE_CRON && schedulerDetail.isSuspended()) {
+ if (triggerType.equals(SchedulerServiceConstants.TRIGGER_TYPE_CRON) && schedulerDetail.isSuspended()) {
scheduledJobDetail.updateTriggerMisfired(true);
isStopExecution = true;
} else if (!isStopExecution) {
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformService.java
index c053b0115..0434261b3 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformService.java
@@ -18,12 +18,14 @@
*/
package org.apache.fineract.portfolio.account.service;
+import java.math.BigDecimal;
import java.util.Collection;
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.portfolio.account.PortfolioAccountType;
import org.apache.fineract.portfolio.account.data.AccountTransferData;
+import org.joda.time.LocalDate;
public interface AccountTransfersReadPlatformService {
@@ -42,4 +44,7 @@ public interface AccountTransfersReadPlatformService {
AccountTransferData retrieveRefundByTransferTemplate(Long fromOfficeId, Long fromClientId, Long fromAccountId, Integer fromAccountType,
Long toOfficeId, Long toClientId, Long toAccountId, Integer toAccountType);
+
+ BigDecimal getTotalTransactionAmount(Long accountId, Integer accountType,
+ LocalDate transactionDate);
}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformServiceImpl.java
index 9dbe4c939..08af09180 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformServiceImpl.java
@@ -45,6 +45,8 @@ import org.apache.fineract.portfolio.account.exception.AccountTransferNotFoundEx
import org.apache.fineract.portfolio.client.data.ClientData;
import org.apache.fineract.portfolio.client.service.ClientReadPlatformService;
import org.joda.time.LocalDate;
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.DateTimeFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
@@ -53,485 +55,643 @@ import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
@Service
-public class AccountTransfersReadPlatformServiceImpl implements AccountTransfersReadPlatformService {
-
- private final JdbcTemplate jdbcTemplate;
- private final ClientReadPlatformService clientReadPlatformService;
- private final OfficeReadPlatformService officeReadPlatformService;
- private final PortfolioAccountReadPlatformService portfolioAccountReadPlatformService;
-
- // mapper
- private final AccountTransfersMapper accountTransfersMapper;
-
- // pagination
- private final PaginationHelper paginationHelper = new PaginationHelper<>();
-
- @Autowired
- public AccountTransfersReadPlatformServiceImpl(final RoutingDataSource dataSource,
- final ClientReadPlatformService clientReadPlatformService, final OfficeReadPlatformService officeReadPlatformService,
- final PortfolioAccountReadPlatformService portfolioAccountReadPlatformService) {
- this.jdbcTemplate = new JdbcTemplate(dataSource);
- this.clientReadPlatformService = clientReadPlatformService;
- this.officeReadPlatformService = officeReadPlatformService;
- this.portfolioAccountReadPlatformService = portfolioAccountReadPlatformService;
-
- this.accountTransfersMapper = new AccountTransfersMapper();
- }
-
- @Override
- public AccountTransferData retrieveTemplate(final Long fromOfficeId, final Long fromClientId, final Long fromAccountId,
- final Integer fromAccountType, final Long toOfficeId, final Long toClientId, final Long toAccountId, final Integer toAccountType) {
-
- final EnumOptionData loanAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.LOAN);
- final EnumOptionData savingsAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.SAVINGS);
-
- final Integer mostRelevantFromAccountType = fromAccountType;
- final Collection fromAccountTypeOptions = Arrays.asList(savingsAccountType, loanAccountType);
- final Collection toAccountTypeOptions;
- if (mostRelevantFromAccountType != null && mostRelevantFromAccountType == 1) {
- // overpaid loan amt transfer to savings account
- toAccountTypeOptions = Arrays.asList(savingsAccountType);
- } else {
- toAccountTypeOptions = Arrays.asList(loanAccountType, savingsAccountType);
- }
- final Integer mostRelevantToAccountType = toAccountType;
-
- final EnumOptionData fromAccountTypeData = AccountTransferEnumerations.accountType(mostRelevantFromAccountType);
- final EnumOptionData toAccountTypeData = AccountTransferEnumerations.accountType(mostRelevantToAccountType);
-
- // from settings
- OfficeData fromOffice = null;
- ClientData fromClient = null;
- PortfolioAccountData fromAccount = null;
-
- OfficeData toOffice = null;
- ClientData toClient = null;
- PortfolioAccountData toAccount = null;
-
- // template
- Collection fromAccountOptions = null;
- Collection toAccountOptions = null;
-
- Long mostRelevantFromOfficeId = fromOfficeId;
- Long mostRelevantFromClientId = fromClientId;
-
- Long mostRelevantToOfficeId = toOfficeId;
- Long mostRelevantToClientId = toClientId;
-
- if (fromAccountId != null) {
- Integer accountType;
- if (mostRelevantFromAccountType == 1) {
- accountType = PortfolioAccountType.LOAN.getValue();
- } else {
- accountType = PortfolioAccountType.SAVINGS.getValue();
- }
- fromAccount = this.portfolioAccountReadPlatformService.retrieveOne(fromAccountId, accountType);
-
- // override provided fromClient with client of account
- mostRelevantFromClientId = fromAccount.clientId();
- }
-
- if (mostRelevantFromClientId != null) {
- fromClient = this.clientReadPlatformService.retrieveOne(mostRelevantFromClientId);
- mostRelevantFromOfficeId = fromClient.officeId();
- long[] loanStatus = null;
- if (mostRelevantFromAccountType == 1) {
- loanStatus = new long[] { 300, 700 };
- }
- PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(mostRelevantFromAccountType, mostRelevantFromClientId,
- loanStatus);
- fromAccountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(portfolioAccountDTO);
- }
-
- Collection fromOfficeOptions = null;
- Collection fromClientOptions = null;
- if (mostRelevantFromOfficeId != null) {
- fromOffice = this.officeReadPlatformService.retrieveOffice(mostRelevantFromOfficeId);
- fromOfficeOptions = this.officeReadPlatformService.retrieveAllOfficesForDropdown();
- fromClientOptions = this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantFromOfficeId);
- }
-
- // defaults
- final LocalDate transferDate = DateUtils.getLocalDateOfTenant();
- Collection toOfficeOptions = fromOfficeOptions;
- Collection toClientOptions = null;
-
- if (toAccountId != null && fromAccount != null) {
- toAccount = this.portfolioAccountReadPlatformService.retrieveOne(toAccountId, mostRelevantToAccountType,
- fromAccount.currencyCode());
- mostRelevantToClientId = toAccount.clientId();
- }
-
- if (mostRelevantToClientId != null) {
- toClient = this.clientReadPlatformService.retrieveOne(mostRelevantToClientId);
- mostRelevantToOfficeId = toClient.officeId();
-
- toClientOptions = this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
-
- toAccountOptions = retrieveToAccounts(fromAccount, mostRelevantToAccountType, mostRelevantToClientId);
- }
-
- if (mostRelevantToOfficeId != null) {
- toOffice = this.officeReadPlatformService.retrieveOffice(mostRelevantToOfficeId);
- toOfficeOptions = this.officeReadPlatformService.retrieveAllOfficesForDropdown();
-
- toClientOptions = this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
- if (toClientOptions != null && toClientOptions.size() == 1) {
- toClient = new ArrayList<>(toClientOptions).get(0);
-
- toAccountOptions = retrieveToAccounts(fromAccount, mostRelevantToAccountType, mostRelevantToClientId);
- }
- }
-
- return AccountTransferData.template(fromOffice, fromClient, fromAccountTypeData, fromAccount, transferDate, toOffice, toClient,
- toAccountTypeData, toAccount, fromOfficeOptions, fromClientOptions, fromAccountTypeOptions, fromAccountOptions,
- toOfficeOptions, toClientOptions, toAccountTypeOptions, toAccountOptions);
- }
-
- private Collection retrieveToAccounts(final PortfolioAccountData excludeThisAccountFromOptions,
- final Integer toAccountType, final Long toClientId) {
-
- final String currencyCode = excludeThisAccountFromOptions != null ? excludeThisAccountFromOptions.currencyCode() : null;
-
- PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(toAccountType, toClientId, currencyCode, null, null);
- Collection accountOptions = this.portfolioAccountReadPlatformService
- .retrieveAllForLookup(portfolioAccountDTO);
- if (!CollectionUtils.isEmpty(accountOptions)) {
- accountOptions.remove(excludeThisAccountFromOptions);
- } else {
- accountOptions = null;
- }
-
- return accountOptions;
- }
-
- @Override
- public Page retrieveAll(final SearchParameters searchParameters, final Long accountDetailId) {
-
- final StringBuilder sqlBuilder = new StringBuilder(200);
- sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
- sqlBuilder.append(this.accountTransfersMapper.schema());
- Object[] finalObjectArray = {};
- if (accountDetailId != null) {
- sqlBuilder.append(" where att.account_transfer_details_id=?");
- finalObjectArray = new Object[] { accountDetailId };
- }
-
- if (searchParameters.isOrderByRequested()) {
- sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
-
- if (searchParameters.isSortOrderProvided()) {
- sqlBuilder.append(' ').append(searchParameters.getSortOrder());
- }
- }
-
- if (searchParameters.isLimited()) {
- sqlBuilder.append(" limit ").append(searchParameters.getLimit());
- if (searchParameters.isOffset()) {
- sqlBuilder.append(" offset ").append(searchParameters.getOffset());
- }
- }
-
- final String sqlCountRows = "SELECT FOUND_ROWS()";
- return this.paginationHelper.fetchPage(this.jdbcTemplate, sqlCountRows, sqlBuilder.toString(), finalObjectArray,
- this.accountTransfersMapper);
- }
-
- @Override
- public AccountTransferData retrieveOne(final Long transferId) {
-
- try {
- final String sql = "select " + this.accountTransfersMapper.schema() + " where att.id = ?";
-
- return this.jdbcTemplate.queryForObject(sql, this.accountTransfersMapper, new Object[] { transferId });
- } catch (final EmptyResultDataAccessException e) {
- throw new AccountTransferNotFoundException(transferId);
- }
- }
-
- @Override
- public Collection 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 transactionId = this.jdbcTemplate.queryForList(sql, Long.class, accountId,
- AccountTransferType.INTEREST_TRANSFER.getValue());
-
- return transactionId;
- }
-
- private static final class AccountTransfersMapper implements RowMapper {
-
- private final String schemaSql;
-
- public AccountTransfersMapper() {
- final StringBuilder sqlBuilder = new StringBuilder(400);
- sqlBuilder.append("att.id as id, att.is_reversed as isReversed,");
- sqlBuilder.append("att.transaction_date as transferDate, att.amount as transferAmount,");
- sqlBuilder.append("att.description as transferDescription,");
- sqlBuilder.append("att.currency_code as currencyCode, att.currency_digits as currencyDigits,");
- sqlBuilder.append("att.currency_multiplesof as inMultiplesOf, ");
- sqlBuilder.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
- sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol, ");
- sqlBuilder.append("fromoff.id as fromOfficeId, fromoff.name as fromOfficeName,");
- sqlBuilder.append("tooff.id as toOfficeId, tooff.name as toOfficeName,");
- sqlBuilder.append("fromclient.id as fromClientId, fromclient.display_name as fromClientName,");
- sqlBuilder.append("toclient.id as toClientId, toclient.display_name as toClientName,");
- sqlBuilder.append("fromsavacc.id as fromSavingsAccountId, fromsavacc.account_no as fromSavingsAccountNo,");
- sqlBuilder.append("fromloanacc.id as fromLoanAccountId, fromloanacc.account_no as fromLoanAccountNo,");
- sqlBuilder.append("tosavacc.id as toSavingsAccountId, tosavacc.account_no as toSavingsAccountNo,");
- sqlBuilder.append("toloanacc.id as toLoanAccountId, toloanacc.account_no as toLoanAccountNo,");
- sqlBuilder.append("fromsavtran.id as fromSavingsAccountTransactionId,");
- sqlBuilder.append("fromsavtran.transaction_type_enum as fromSavingsAccountTransactionType,");
- sqlBuilder.append("tosavtran.id as toSavingsAccountTransactionId,");
- sqlBuilder.append("tosavtran.transaction_type_enum as toSavingsAccountTransactionType");
- sqlBuilder.append(" FROM m_account_transfer_transaction att ");
- sqlBuilder.append("left join m_account_transfer_details atd on atd.id = att.account_transfer_details_id ");
- sqlBuilder.append("join m_currency curr on curr.code = att.currency_code ");
- sqlBuilder.append("join m_office fromoff on fromoff.id = atd.from_office_id ");
- sqlBuilder.append("join m_office tooff on tooff.id = atd.to_office_id ");
- sqlBuilder.append("join m_client fromclient on fromclient.id = atd.from_client_id ");
- sqlBuilder.append("join m_client toclient on toclient.id = atd.to_client_id ");
- sqlBuilder.append("left join m_savings_account fromsavacc on fromsavacc.id = atd.from_savings_account_id ");
- sqlBuilder.append("left join m_loan fromloanacc on fromloanacc.id = atd.from_loan_account_id ");
- sqlBuilder.append("left join m_savings_account tosavacc on tosavacc.id = atd.to_savings_account_id ");
- sqlBuilder.append("left join m_loan toloanacc on toloanacc.id = atd.to_loan_account_id ");
- sqlBuilder.append("left join m_savings_account_transaction fromsavtran on fromsavtran.id = att.from_savings_transaction_id ");
- sqlBuilder.append("left join m_savings_account_transaction tosavtran on tosavtran.id = att.to_savings_transaction_id ");
- sqlBuilder.append("left join m_loan_transaction fromloantran on fromloantran.id = att.from_savings_transaction_id ");
- sqlBuilder.append("left join m_loan_transaction toloantran on toloantran.id = att.to_savings_transaction_id ");
-
- this.schemaSql = sqlBuilder.toString();
- }
-
- public String schema() {
- return this.schemaSql;
- }
-
- @Override
- public AccountTransferData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
-
- final Long id = rs.getLong("id");
- final boolean reversed = rs.getBoolean("isReversed");
-
- final LocalDate transferDate = JdbcSupport.getLocalDate(rs, "transferDate");
- final BigDecimal transferAmount = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "transferAmount");
- final String transferDescription = rs.getString("transferDescription");
-
- final String currencyCode = rs.getString("currencyCode");
- final String currencyName = rs.getString("currencyName");
- final String currencyNameCode = rs.getString("currencyNameCode");
- final String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
- final Integer currencyDigits = JdbcSupport.getInteger(rs, "currencyDigits");
- final Integer inMultiplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf");
- final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, inMultiplesOf,
- currencyDisplaySymbol, currencyNameCode);
-
- final Long fromOfficeId = JdbcSupport.getLong(rs, "fromOfficeId");
- final String fromOfficeName = rs.getString("fromOfficeName");
- final OfficeData fromOffice = OfficeData.dropdown(fromOfficeId, fromOfficeName, null);
-
- final Long toOfficeId = JdbcSupport.getLong(rs, "toOfficeId");
- final String toOfficeName = rs.getString("toOfficeName");
- final OfficeData toOffice = OfficeData.dropdown(toOfficeId, toOfficeName, null);
-
- final Long fromClientId = JdbcSupport.getLong(rs, "fromClientId");
- final String fromClientName = rs.getString("fromClientName");
- final ClientData fromClient = ClientData.lookup(fromClientId, fromClientName, fromOfficeId, fromOfficeName);
-
- final Long toClientId = JdbcSupport.getLong(rs, "toClientId");
- final String toClientName = rs.getString("toClientName");
- final ClientData toClient = ClientData.lookup(toClientId, toClientName, toOfficeId, toOfficeName);
-
- final Long fromSavingsAccountId = JdbcSupport.getLong(rs, "fromSavingsAccountId");
- final String fromSavingsAccountNo = rs.getString("fromSavingsAccountNo");
- final Long fromLoanAccountId = JdbcSupport.getLong(rs, "fromLoanAccountId");
- final String fromLoanAccountNo = rs.getString("fromLoanAccountNo");
- PortfolioAccountData fromAccount = null;
- EnumOptionData fromAccountType = null;
- if (fromSavingsAccountId != null) {
- fromAccount = PortfolioAccountData.lookup(fromSavingsAccountId, fromSavingsAccountNo);
- fromAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.SAVINGS);
- } else if (fromLoanAccountId != null) {
- fromAccount = PortfolioAccountData.lookup(fromLoanAccountId, fromLoanAccountNo);
- fromAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.LOAN);
- }
-
- PortfolioAccountData toAccount = null;
- EnumOptionData toAccountType = null;
- final Long toSavingsAccountId = JdbcSupport.getLong(rs, "toSavingsAccountId");
- final String toSavingsAccountNo = rs.getString("toSavingsAccountNo");
- final Long toLoanAccountId = JdbcSupport.getLong(rs, "toLoanAccountId");
- final String toLoanAccountNo = rs.getString("toLoanAccountNo");
-
- if (toSavingsAccountId != null) {
- toAccount = PortfolioAccountData.lookup(toSavingsAccountId, toSavingsAccountNo);
- toAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.SAVINGS);
- } else if (toLoanAccountId != null) {
- toAccount = PortfolioAccountData.lookup(toLoanAccountId, toLoanAccountNo);
- toAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.LOAN);
- }
-
- return AccountTransferData.instance(id, reversed, transferDate, currency, transferAmount, transferDescription, fromOffice,
- toOffice, fromClient, toClient, fromAccountType, fromAccount, toAccountType, toAccount);
- }
- }
-
- @Override
- public boolean isAccountTransfer(final Long transactionId, final PortfolioAccountType accountType) {
- final StringBuilder sql = new StringBuilder("select count(*) from m_account_transfer_transaction at where ");
- if (accountType.isLoanAccount()) {
- sql.append("at.from_loan_transaction_id=").append(transactionId).append(" or at.to_loan_transaction_id=").append(transactionId);
- } else {
- sql.append("at.from_savings_transaction_id=").append(transactionId).append(" or at.to_savings_transaction_id=")
- .append(transactionId);
- }
-
- @SuppressWarnings("deprecation")
- final int count = this.jdbcTemplate.queryForInt(sql.toString());
- return count > 0;
- }
-
- @Override
- public Page retrieveByStandingInstruction(final Long id, final SearchParameters searchParameters) {
-
- final StringBuilder sqlBuilder = new StringBuilder(200);
- sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
- sqlBuilder
- .append(this.accountTransfersMapper.schema())
- .append(" join m_account_transfer_standing_instructions atsi on atsi.account_transfer_details_id = att.account_transfer_details_id ");
- sqlBuilder.append(" where atsi.id = ?");
-
- if (searchParameters != null) {
- if (searchParameters.isOrderByRequested()) {
- sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
-
- if (searchParameters.isSortOrderProvided()) {
- sqlBuilder.append(' ').append(searchParameters.getSortOrder());
- }
- }
-
- if (searchParameters.isLimited()) {
- sqlBuilder.append(" limit ").append(searchParameters.getLimit());
- if (searchParameters.isOffset()) {
- sqlBuilder.append(" offset ").append(searchParameters.getOffset());
- }
- }
- }
-
- final Object[] finalObjectArray = { id };
- final String sqlCountRows = "SELECT FOUND_ROWS()";
- return this.paginationHelper.fetchPage(this.jdbcTemplate, sqlCountRows, sqlBuilder.toString(), finalObjectArray,
- this.accountTransfersMapper);
- }
-
- @Override
- public AccountTransferData retrieveRefundByTransferTemplate(final Long fromOfficeId, final Long fromClientId, final Long fromAccountId,
- final Integer fromAccountType, final Long toOfficeId, final Long toClientId, final Long toAccountId, final Integer toAccountType) {
- // TODO Auto-generated method stub
- final EnumOptionData loanAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.LOAN);
- final EnumOptionData savingsAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.SAVINGS);
-
- final Integer mostRelevantFromAccountType = fromAccountType;
- final Collection fromAccountTypeOptions = Arrays.asList(savingsAccountType, loanAccountType);
- final Collection toAccountTypeOptions;
- if (mostRelevantFromAccountType == 1) {
- // overpaid loan amt transfer to savings account
- toAccountTypeOptions = Arrays.asList(savingsAccountType);
- } else {
- toAccountTypeOptions = Arrays.asList(loanAccountType, savingsAccountType);
- }
- final Integer mostRelevantToAccountType = toAccountType;
-
- final EnumOptionData fromAccountTypeData = AccountTransferEnumerations.accountType(mostRelevantFromAccountType);
- final EnumOptionData toAccountTypeData = AccountTransferEnumerations.accountType(mostRelevantToAccountType);
-
- // from settings
- OfficeData fromOffice = null;
- ClientData fromClient = null;
- PortfolioAccountData fromAccount = null;
-
- OfficeData toOffice = null;
- ClientData toClient = null;
- PortfolioAccountData toAccount = null;
-
- // template
- Collection fromAccountOptions = null;
- Collection toAccountOptions = null;
-
- Long mostRelevantFromOfficeId = fromOfficeId;
- Long mostRelevantFromClientId = fromClientId;
-
- Long mostRelevantToOfficeId = toOfficeId;
- Long mostRelevantToClientId = toClientId;
-
- if (fromAccountId != null) {
- Integer accountType;
- if (mostRelevantFromAccountType == 1) {
- accountType = PortfolioAccountType.LOAN.getValue();
- } else {
- accountType = PortfolioAccountType.SAVINGS.getValue();
- }
- fromAccount = this.portfolioAccountReadPlatformService.retrieveOneByPaidInAdvance(fromAccountId, accountType);
-
- // override provided fromClient with client of account
- mostRelevantFromClientId = fromAccount.clientId();
- }
-
- if (mostRelevantFromClientId != null) {
- fromClient = this.clientReadPlatformService.retrieveOne(mostRelevantFromClientId);
- mostRelevantFromOfficeId = fromClient.officeId();
- long[] loanStatus = null;
- if (mostRelevantFromAccountType == 1) {
- loanStatus = new long[] { 300, 700 };
- }
- PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(mostRelevantFromAccountType, mostRelevantFromClientId,
- loanStatus);
- fromAccountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(portfolioAccountDTO);
- }
-
- Collection fromOfficeOptions = null;
- Collection fromClientOptions = null;
- if (mostRelevantFromOfficeId != null) {
- fromOffice = this.officeReadPlatformService.retrieveOffice(mostRelevantFromOfficeId);
- fromOfficeOptions = this.officeReadPlatformService.retrieveAllOfficesForDropdown();
- fromClientOptions = this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantFromOfficeId);
- }
-
- // defaults
- final LocalDate transferDate = DateUtils.getLocalDateOfTenant();
- Collection toOfficeOptions = fromOfficeOptions;
- Collection toClientOptions = null;
-
- if (toAccountId != null && fromAccount != null) {
- toAccount = this.portfolioAccountReadPlatformService.retrieveOne(toAccountId, mostRelevantToAccountType,
- fromAccount.currencyCode());
- mostRelevantToClientId = toAccount.clientId();
- }
-
- if (mostRelevantToClientId != null) {
- toClient = this.clientReadPlatformService.retrieveOne(mostRelevantToClientId);
- mostRelevantToOfficeId = toClient.officeId();
-
- toClientOptions = this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
-
- toAccountOptions = retrieveToAccounts(fromAccount, mostRelevantToAccountType, mostRelevantToClientId);
- }
-
- if (mostRelevantToOfficeId != null) {
- toOffice = this.officeReadPlatformService.retrieveOffice(mostRelevantToOfficeId);
- toOfficeOptions = this.officeReadPlatformService.retrieveAllOfficesForDropdown();
-
- toClientOptions = this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
- if (toClientOptions != null && toClientOptions.size() == 1) {
- toClient = new ArrayList<>(toClientOptions).get(0);
-
- toAccountOptions = retrieveToAccounts(fromAccount, mostRelevantToAccountType, mostRelevantToClientId);
- }
- }
-
- return AccountTransferData.template(fromOffice, fromClient, fromAccountTypeData, fromAccount, transferDate, toOffice, toClient,
- toAccountTypeData, toAccount, fromOfficeOptions, fromClientOptions, fromAccountTypeOptions, fromAccountOptions,
- toOfficeOptions, toClientOptions, toAccountTypeOptions, toAccountOptions);
- }
+public class AccountTransfersReadPlatformServiceImpl implements
+ AccountTransfersReadPlatformService {
+
+ private final JdbcTemplate jdbcTemplate;
+ private final ClientReadPlatformService clientReadPlatformService;
+ private final OfficeReadPlatformService officeReadPlatformService;
+ private final PortfolioAccountReadPlatformService portfolioAccountReadPlatformService;
+
+ // mapper
+ private final AccountTransfersMapper accountTransfersMapper;
+
+ // pagination
+ private final PaginationHelper paginationHelper = new PaginationHelper<>();
+ private final DateTimeFormatter formatter = DateTimeFormat
+ .forPattern("yyyy-MM-dd");
+
+ @Autowired
+ public AccountTransfersReadPlatformServiceImpl(
+ final RoutingDataSource dataSource,
+ final ClientReadPlatformService clientReadPlatformService,
+ final OfficeReadPlatformService officeReadPlatformService,
+ final PortfolioAccountReadPlatformService portfolioAccountReadPlatformService) {
+ this.jdbcTemplate = new JdbcTemplate(dataSource);
+ this.clientReadPlatformService = clientReadPlatformService;
+ this.officeReadPlatformService = officeReadPlatformService;
+ this.portfolioAccountReadPlatformService = portfolioAccountReadPlatformService;
+
+ this.accountTransfersMapper = new AccountTransfersMapper();
+ }
+
+ @Override
+ public AccountTransferData retrieveTemplate(final Long fromOfficeId,
+ final Long fromClientId, final Long fromAccountId,
+ final Integer fromAccountType, final Long toOfficeId,
+ final Long toClientId, final Long toAccountId,
+ final Integer toAccountType) {
+
+ final EnumOptionData loanAccountType = AccountTransferEnumerations
+ .accountType(PortfolioAccountType.LOAN);
+ final EnumOptionData savingsAccountType = AccountTransferEnumerations
+ .accountType(PortfolioAccountType.SAVINGS);
+
+ final Integer mostRelevantFromAccountType = fromAccountType;
+ final Collection fromAccountTypeOptions = Arrays
+ .asList(savingsAccountType, loanAccountType);
+ final Collection toAccountTypeOptions;
+ if (mostRelevantFromAccountType != null
+ && mostRelevantFromAccountType == 1) {
+ // overpaid loan amt transfer to savings account
+ toAccountTypeOptions = Arrays.asList(savingsAccountType);
+ } else {
+ toAccountTypeOptions = Arrays.asList(loanAccountType,
+ savingsAccountType);
+ }
+ final Integer mostRelevantToAccountType = toAccountType;
+
+ final EnumOptionData fromAccountTypeData = AccountTransferEnumerations
+ .accountType(mostRelevantFromAccountType);
+ final EnumOptionData toAccountTypeData = AccountTransferEnumerations
+ .accountType(mostRelevantToAccountType);
+
+ // from settings
+ OfficeData fromOffice = null;
+ ClientData fromClient = null;
+ PortfolioAccountData fromAccount = null;
+
+ OfficeData toOffice = null;
+ ClientData toClient = null;
+ PortfolioAccountData toAccount = null;
+
+ // template
+ Collection fromAccountOptions = null;
+ Collection toAccountOptions = null;
+
+ Long mostRelevantFromOfficeId = fromOfficeId;
+ Long mostRelevantFromClientId = fromClientId;
+
+ Long mostRelevantToOfficeId = toOfficeId;
+ Long mostRelevantToClientId = toClientId;
+
+ if (fromAccountId != null) {
+ Integer accountType;
+ if (mostRelevantFromAccountType == 1) {
+ accountType = PortfolioAccountType.LOAN.getValue();
+ } else {
+ accountType = PortfolioAccountType.SAVINGS.getValue();
+ }
+ fromAccount = this.portfolioAccountReadPlatformService.retrieveOne(
+ fromAccountId, accountType);
+
+ // override provided fromClient with client of account
+ mostRelevantFromClientId = fromAccount.clientId();
+ }
+
+ if (mostRelevantFromClientId != null) {
+ fromClient = this.clientReadPlatformService
+ .retrieveOne(mostRelevantFromClientId);
+ mostRelevantFromOfficeId = fromClient.officeId();
+ long[] loanStatus = null;
+ if (mostRelevantFromAccountType == 1) {
+ loanStatus = new long[] { 300, 700 };
+ }
+ PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(
+ mostRelevantFromAccountType, mostRelevantFromClientId,
+ loanStatus);
+ fromAccountOptions = this.portfolioAccountReadPlatformService
+ .retrieveAllForLookup(portfolioAccountDTO);
+ }
+
+ Collection fromOfficeOptions = null;
+ Collection fromClientOptions = null;
+ if (mostRelevantFromOfficeId != null) {
+ fromOffice = this.officeReadPlatformService
+ .retrieveOffice(mostRelevantFromOfficeId);
+ fromOfficeOptions = this.officeReadPlatformService
+ .retrieveAllOfficesForDropdown();
+ fromClientOptions = this.clientReadPlatformService
+ .retrieveAllForLookupByOfficeId(mostRelevantFromOfficeId);
+ }
+
+ // defaults
+ final LocalDate transferDate = DateUtils.getLocalDateOfTenant();
+ Collection toOfficeOptions = fromOfficeOptions;
+ Collection toClientOptions = null;
+
+ if (toAccountId != null && fromAccount != null) {
+ toAccount = this.portfolioAccountReadPlatformService.retrieveOne(
+ toAccountId, mostRelevantToAccountType,
+ fromAccount.currencyCode());
+ mostRelevantToClientId = toAccount.clientId();
+ }
+
+ if (mostRelevantToClientId != null) {
+ toClient = this.clientReadPlatformService
+ .retrieveOne(mostRelevantToClientId);
+ mostRelevantToOfficeId = toClient.officeId();
+
+ toClientOptions = this.clientReadPlatformService
+ .retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
+
+ toAccountOptions = retrieveToAccounts(fromAccount,
+ mostRelevantToAccountType, mostRelevantToClientId);
+ }
+
+ if (mostRelevantToOfficeId != null) {
+ toOffice = this.officeReadPlatformService
+ .retrieveOffice(mostRelevantToOfficeId);
+ toOfficeOptions = this.officeReadPlatformService
+ .retrieveAllOfficesForDropdown();
+
+ toClientOptions = this.clientReadPlatformService
+ .retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
+ if (toClientOptions != null && toClientOptions.size() == 1) {
+ toClient = new ArrayList<>(toClientOptions).get(0);
+
+ toAccountOptions = retrieveToAccounts(fromAccount,
+ mostRelevantToAccountType, mostRelevantToClientId);
+ }
+ }
+
+ return AccountTransferData.template(fromOffice, fromClient,
+ fromAccountTypeData, fromAccount, transferDate, toOffice,
+ toClient, toAccountTypeData, toAccount, fromOfficeOptions,
+ fromClientOptions, fromAccountTypeOptions, fromAccountOptions,
+ toOfficeOptions, toClientOptions, toAccountTypeOptions,
+ toAccountOptions);
+ }
+
+ private Collection retrieveToAccounts(
+ final PortfolioAccountData excludeThisAccountFromOptions,
+ final Integer toAccountType, final Long toClientId) {
+
+ final String currencyCode = excludeThisAccountFromOptions != null ? excludeThisAccountFromOptions
+ .currencyCode() : null;
+
+ PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(
+ toAccountType, toClientId, currencyCode, null, null);
+ Collection accountOptions = this.portfolioAccountReadPlatformService
+ .retrieveAllForLookup(portfolioAccountDTO);
+ if (!CollectionUtils.isEmpty(accountOptions)) {
+ accountOptions.remove(excludeThisAccountFromOptions);
+ } else {
+ accountOptions = null;
+ }
+
+ return accountOptions;
+ }
+
+ @Override
+ public Page retrieveAll(
+ final SearchParameters searchParameters, final Long accountDetailId) {
+
+ final StringBuilder sqlBuilder = new StringBuilder(200);
+ sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
+ sqlBuilder.append(this.accountTransfersMapper.schema());
+ Object[] finalObjectArray = {};
+ if (accountDetailId != null) {
+ sqlBuilder.append(" where att.account_transfer_details_id=?");
+ finalObjectArray = new Object[] { accountDetailId };
+ }
+
+ if (searchParameters.isOrderByRequested()) {
+ sqlBuilder.append(" order by ").append(
+ searchParameters.getOrderBy());
+
+ if (searchParameters.isSortOrderProvided()) {
+ sqlBuilder.append(' ').append(searchParameters.getSortOrder());
+ }
+ }
+
+ if (searchParameters.isLimited()) {
+ sqlBuilder.append(" limit ").append(searchParameters.getLimit());
+ if (searchParameters.isOffset()) {
+ sqlBuilder.append(" offset ").append(
+ searchParameters.getOffset());
+ }
+ }
+
+ final String sqlCountRows = "SELECT FOUND_ROWS()";
+ return this.paginationHelper.fetchPage(this.jdbcTemplate, sqlCountRows,
+ sqlBuilder.toString(), finalObjectArray,
+ this.accountTransfersMapper);
+ }
+
+ @Override
+ public AccountTransferData retrieveOne(final Long transferId) {
+
+ try {
+ final String sql = "select " + this.accountTransfersMapper.schema()
+ + " where att.id = ?";
+
+ return this.jdbcTemplate.queryForObject(sql,
+ this.accountTransfersMapper, new Object[] { transferId });
+ } catch (final EmptyResultDataAccessException e) {
+ throw new AccountTransferNotFoundException(transferId);
+ }
+ }
+
+ @Override
+ public Collection 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 transactionId = this.jdbcTemplate.queryForList(sql,
+ Long.class, accountId,
+ AccountTransferType.INTEREST_TRANSFER.getValue());
+
+ return transactionId;
+ }
+
+ private static final class AccountTransfersMapper implements
+ RowMapper {
+
+ private final String schemaSql;
+
+ public AccountTransfersMapper() {
+ final StringBuilder sqlBuilder = new StringBuilder(400);
+ sqlBuilder.append("att.id as id, att.is_reversed as isReversed,");
+ sqlBuilder
+ .append("att.transaction_date as transferDate, att.amount as transferAmount,");
+ sqlBuilder.append("att.description as transferDescription,");
+ sqlBuilder
+ .append("att.currency_code as currencyCode, att.currency_digits as currencyDigits,");
+ sqlBuilder.append("att.currency_multiplesof as inMultiplesOf, ");
+ sqlBuilder
+ .append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
+ sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol, ");
+ sqlBuilder
+ .append("fromoff.id as fromOfficeId, fromoff.name as fromOfficeName,");
+ sqlBuilder
+ .append("tooff.id as toOfficeId, tooff.name as toOfficeName,");
+ sqlBuilder
+ .append("fromclient.id as fromClientId, fromclient.display_name as fromClientName,");
+ sqlBuilder
+ .append("toclient.id as toClientId, toclient.display_name as toClientName,");
+ sqlBuilder
+ .append("fromsavacc.id as fromSavingsAccountId, fromsavacc.account_no as fromSavingsAccountNo,");
+ sqlBuilder
+ .append("fromloanacc.id as fromLoanAccountId, fromloanacc.account_no as fromLoanAccountNo,");
+ sqlBuilder
+ .append("tosavacc.id as toSavingsAccountId, tosavacc.account_no as toSavingsAccountNo,");
+ sqlBuilder
+ .append("toloanacc.id as toLoanAccountId, toloanacc.account_no as toLoanAccountNo,");
+ sqlBuilder
+ .append("fromsavtran.id as fromSavingsAccountTransactionId,");
+ sqlBuilder
+ .append("fromsavtran.transaction_type_enum as fromSavingsAccountTransactionType,");
+ sqlBuilder.append("tosavtran.id as toSavingsAccountTransactionId,");
+ sqlBuilder
+ .append("tosavtran.transaction_type_enum as toSavingsAccountTransactionType");
+ sqlBuilder.append(" FROM m_account_transfer_transaction att ");
+ sqlBuilder
+ .append("left join m_account_transfer_details atd on atd.id = att.account_transfer_details_id ");
+ sqlBuilder
+ .append("join m_currency curr on curr.code = att.currency_code ");
+ sqlBuilder
+ .append("join m_office fromoff on fromoff.id = atd.from_office_id ");
+ sqlBuilder
+ .append("join m_office tooff on tooff.id = atd.to_office_id ");
+ sqlBuilder
+ .append("join m_client fromclient on fromclient.id = atd.from_client_id ");
+ sqlBuilder
+ .append("join m_client toclient on toclient.id = atd.to_client_id ");
+ sqlBuilder
+ .append("left join m_savings_account fromsavacc on fromsavacc.id = atd.from_savings_account_id ");
+ sqlBuilder
+ .append("left join m_loan fromloanacc on fromloanacc.id = atd.from_loan_account_id ");
+ sqlBuilder
+ .append("left join m_savings_account tosavacc on tosavacc.id = atd.to_savings_account_id ");
+ sqlBuilder
+ .append("left join m_loan toloanacc on toloanacc.id = atd.to_loan_account_id ");
+ sqlBuilder
+ .append("left join m_savings_account_transaction fromsavtran on fromsavtran.id = att.from_savings_transaction_id ");
+ sqlBuilder
+ .append("left join m_savings_account_transaction tosavtran on tosavtran.id = att.to_savings_transaction_id ");
+ sqlBuilder
+ .append("left join m_loan_transaction fromloantran on fromloantran.id = att.from_savings_transaction_id ");
+ sqlBuilder
+ .append("left join m_loan_transaction toloantran on toloantran.id = att.to_savings_transaction_id ");
+
+ this.schemaSql = sqlBuilder.toString();
+ }
+
+ public String schema() {
+ return this.schemaSql;
+ }
+
+ @Override
+ public AccountTransferData mapRow(final ResultSet rs,
+ @SuppressWarnings("unused") final int rowNum)
+ throws SQLException {
+
+ final Long id = rs.getLong("id");
+ final boolean reversed = rs.getBoolean("isReversed");
+
+ final LocalDate transferDate = JdbcSupport.getLocalDate(rs,
+ "transferDate");
+ final BigDecimal transferAmount = JdbcSupport
+ .getBigDecimalDefaultToZeroIfNull(rs, "transferAmount");
+ final String transferDescription = rs
+ .getString("transferDescription");
+
+ final String currencyCode = rs.getString("currencyCode");
+ final String currencyName = rs.getString("currencyName");
+ final String currencyNameCode = rs.getString("currencyNameCode");
+ final String currencyDisplaySymbol = rs
+ .getString("currencyDisplaySymbol");
+ final Integer currencyDigits = JdbcSupport.getInteger(rs,
+ "currencyDigits");
+ final Integer inMultiplesOf = JdbcSupport.getInteger(rs,
+ "inMultiplesOf");
+ final CurrencyData currency = new CurrencyData(currencyCode,
+ currencyName, currencyDigits, inMultiplesOf,
+ currencyDisplaySymbol, currencyNameCode);
+
+ final Long fromOfficeId = JdbcSupport.getLong(rs, "fromOfficeId");
+ final String fromOfficeName = rs.getString("fromOfficeName");
+ final OfficeData fromOffice = OfficeData.dropdown(fromOfficeId,
+ fromOfficeName, null);
+
+ final Long toOfficeId = JdbcSupport.getLong(rs, "toOfficeId");
+ final String toOfficeName = rs.getString("toOfficeName");
+ final OfficeData toOffice = OfficeData.dropdown(toOfficeId,
+ toOfficeName, null);
+
+ final Long fromClientId = JdbcSupport.getLong(rs, "fromClientId");
+ final String fromClientName = rs.getString("fromClientName");
+ final ClientData fromClient = ClientData.lookup(fromClientId,
+ fromClientName, fromOfficeId, fromOfficeName);
+
+ final Long toClientId = JdbcSupport.getLong(rs, "toClientId");
+ final String toClientName = rs.getString("toClientName");
+ final ClientData toClient = ClientData.lookup(toClientId,
+ toClientName, toOfficeId, toOfficeName);
+
+ final Long fromSavingsAccountId = JdbcSupport.getLong(rs,
+ "fromSavingsAccountId");
+ final String fromSavingsAccountNo = rs
+ .getString("fromSavingsAccountNo");
+ final Long fromLoanAccountId = JdbcSupport.getLong(rs,
+ "fromLoanAccountId");
+ final String fromLoanAccountNo = rs.getString("fromLoanAccountNo");
+ PortfolioAccountData fromAccount = null;
+ EnumOptionData fromAccountType = null;
+ if (fromSavingsAccountId != null) {
+ fromAccount = PortfolioAccountData.lookup(fromSavingsAccountId,
+ fromSavingsAccountNo);
+ fromAccountType = AccountTransferEnumerations
+ .accountType(PortfolioAccountType.SAVINGS);
+ } else if (fromLoanAccountId != null) {
+ fromAccount = PortfolioAccountData.lookup(fromLoanAccountId,
+ fromLoanAccountNo);
+ fromAccountType = AccountTransferEnumerations
+ .accountType(PortfolioAccountType.LOAN);
+ }
+
+ PortfolioAccountData toAccount = null;
+ EnumOptionData toAccountType = null;
+ final Long toSavingsAccountId = JdbcSupport.getLong(rs,
+ "toSavingsAccountId");
+ final String toSavingsAccountNo = rs
+ .getString("toSavingsAccountNo");
+ final Long toLoanAccountId = JdbcSupport.getLong(rs,
+ "toLoanAccountId");
+ final String toLoanAccountNo = rs.getString("toLoanAccountNo");
+
+ if (toSavingsAccountId != null) {
+ toAccount = PortfolioAccountData.lookup(toSavingsAccountId,
+ toSavingsAccountNo);
+ toAccountType = AccountTransferEnumerations
+ .accountType(PortfolioAccountType.SAVINGS);
+ } else if (toLoanAccountId != null) {
+ toAccount = PortfolioAccountData.lookup(toLoanAccountId,
+ toLoanAccountNo);
+ toAccountType = AccountTransferEnumerations
+ .accountType(PortfolioAccountType.LOAN);
+ }
+
+ return AccountTransferData.instance(id, reversed, transferDate,
+ currency, transferAmount, transferDescription, fromOffice,
+ toOffice, fromClient, toClient, fromAccountType,
+ fromAccount, toAccountType, toAccount);
+ }
+ }
+
+ @Override
+ public boolean isAccountTransfer(final Long transactionId,
+ final PortfolioAccountType accountType) {
+ final StringBuilder sql = new StringBuilder(
+ "select count(*) from m_account_transfer_transaction at where ");
+ if (accountType.isLoanAccount()) {
+ sql.append("at.from_loan_transaction_id=").append(transactionId)
+ .append(" or at.to_loan_transaction_id=")
+ .append(transactionId);
+ } else {
+ sql.append("at.from_savings_transaction_id=").append(transactionId)
+ .append(" or at.to_savings_transaction_id=")
+ .append(transactionId);
+ }
+
+ @SuppressWarnings("deprecation")
+ final int count = this.jdbcTemplate.queryForInt(sql.toString());
+ return count > 0;
+ }
+
+ @Override
+ public Page retrieveByStandingInstruction(
+ final Long id, final SearchParameters searchParameters) {
+
+ final StringBuilder sqlBuilder = new StringBuilder(200);
+ sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
+ sqlBuilder
+ .append(this.accountTransfersMapper.schema())
+ .append(" join m_account_transfer_standing_instructions atsi on atsi.account_transfer_details_id = att.account_transfer_details_id ");
+ sqlBuilder.append(" where atsi.id = ?");
+
+ if (searchParameters != null) {
+ if (searchParameters.isOrderByRequested()) {
+ sqlBuilder.append(" order by ").append(
+ searchParameters.getOrderBy());
+
+ if (searchParameters.isSortOrderProvided()) {
+ sqlBuilder.append(' ').append(
+ searchParameters.getSortOrder());
+ }
+ }
+
+ if (searchParameters.isLimited()) {
+ sqlBuilder.append(" limit ")
+ .append(searchParameters.getLimit());
+ if (searchParameters.isOffset()) {
+ sqlBuilder.append(" offset ").append(
+ searchParameters.getOffset());
+ }
+ }
+ }
+
+ final Object[] finalObjectArray = { id };
+ final String sqlCountRows = "SELECT FOUND_ROWS()";
+ return this.paginationHelper.fetchPage(this.jdbcTemplate, sqlCountRows,
+ sqlBuilder.toString(), finalObjectArray,
+ this.accountTransfersMapper);
+ }
+
+ @Override
+ public AccountTransferData retrieveRefundByTransferTemplate(
+ final Long fromOfficeId, final Long fromClientId,
+ final Long fromAccountId, final Integer fromAccountType,
+ final Long toOfficeId, final Long toClientId,
+ final Long toAccountId, final Integer toAccountType) {
+ // TODO Auto-generated method stub
+ final EnumOptionData loanAccountType = AccountTransferEnumerations
+ .accountType(PortfolioAccountType.LOAN);
+ final EnumOptionData savingsAccountType = AccountTransferEnumerations
+ .accountType(PortfolioAccountType.SAVINGS);
+
+ final Integer mostRelevantFromAccountType = fromAccountType;
+ final Collection fromAccountTypeOptions = Arrays
+ .asList(savingsAccountType, loanAccountType);
+ final Collection toAccountTypeOptions;
+ if (mostRelevantFromAccountType == 1) {
+ // overpaid loan amt transfer to savings account
+ toAccountTypeOptions = Arrays.asList(savingsAccountType);
+ } else {
+ toAccountTypeOptions = Arrays.asList(loanAccountType,
+ savingsAccountType);
+ }
+ final Integer mostRelevantToAccountType = toAccountType;
+
+ final EnumOptionData fromAccountTypeData = AccountTransferEnumerations
+ .accountType(mostRelevantFromAccountType);
+ final EnumOptionData toAccountTypeData = AccountTransferEnumerations
+ .accountType(mostRelevantToAccountType);
+
+ // from settings
+ OfficeData fromOffice = null;
+ ClientData fromClient = null;
+ PortfolioAccountData fromAccount = null;
+
+ OfficeData toOffice = null;
+ ClientData toClient = null;
+ PortfolioAccountData toAccount = null;
+
+ // template
+ Collection fromAccountOptions = null;
+ Collection toAccountOptions = null;
+
+ Long mostRelevantFromOfficeId = fromOfficeId;
+ Long mostRelevantFromClientId = fromClientId;
+
+ Long mostRelevantToOfficeId = toOfficeId;
+ Long mostRelevantToClientId = toClientId;
+
+ if (fromAccountId != null) {
+ Integer accountType;
+ if (mostRelevantFromAccountType == 1) {
+ accountType = PortfolioAccountType.LOAN.getValue();
+ } else {
+ accountType = PortfolioAccountType.SAVINGS.getValue();
+ }
+ fromAccount = this.portfolioAccountReadPlatformService
+ .retrieveOneByPaidInAdvance(fromAccountId, accountType);
+
+ // override provided fromClient with client of account
+ mostRelevantFromClientId = fromAccount.clientId();
+ }
+
+ if (mostRelevantFromClientId != null) {
+ fromClient = this.clientReadPlatformService
+ .retrieveOne(mostRelevantFromClientId);
+ mostRelevantFromOfficeId = fromClient.officeId();
+ long[] loanStatus = null;
+ if (mostRelevantFromAccountType == 1) {
+ loanStatus = new long[] { 300, 700 };
+ }
+ PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(
+ mostRelevantFromAccountType, mostRelevantFromClientId,
+ loanStatus);
+ fromAccountOptions = this.portfolioAccountReadPlatformService
+ .retrieveAllForLookup(portfolioAccountDTO);
+ }
+
+ Collection fromOfficeOptions = null;
+ Collection fromClientOptions = null;
+ if (mostRelevantFromOfficeId != null) {
+ fromOffice = this.officeReadPlatformService
+ .retrieveOffice(mostRelevantFromOfficeId);
+ fromOfficeOptions = this.officeReadPlatformService
+ .retrieveAllOfficesForDropdown();
+ fromClientOptions = this.clientReadPlatformService
+ .retrieveAllForLookupByOfficeId(mostRelevantFromOfficeId);
+ }
+
+ // defaults
+ final LocalDate transferDate = DateUtils.getLocalDateOfTenant();
+ Collection toOfficeOptions = fromOfficeOptions;
+ Collection toClientOptions = null;
+
+ if (toAccountId != null && fromAccount != null) {
+ toAccount = this.portfolioAccountReadPlatformService.retrieveOne(
+ toAccountId, mostRelevantToAccountType,
+ fromAccount.currencyCode());
+ mostRelevantToClientId = toAccount.clientId();
+ }
+
+ if (mostRelevantToClientId != null) {
+ toClient = this.clientReadPlatformService
+ .retrieveOne(mostRelevantToClientId);
+ mostRelevantToOfficeId = toClient.officeId();
+
+ toClientOptions = this.clientReadPlatformService
+ .retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
+
+ toAccountOptions = retrieveToAccounts(fromAccount,
+ mostRelevantToAccountType, mostRelevantToClientId);
+ }
+
+ if (mostRelevantToOfficeId != null) {
+ toOffice = this.officeReadPlatformService
+ .retrieveOffice(mostRelevantToOfficeId);
+ toOfficeOptions = this.officeReadPlatformService
+ .retrieveAllOfficesForDropdown();
+
+ toClientOptions = this.clientReadPlatformService
+ .retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
+ if (toClientOptions != null && toClientOptions.size() == 1) {
+ toClient = new ArrayList<>(toClientOptions).get(0);
+
+ toAccountOptions = retrieveToAccounts(fromAccount,
+ mostRelevantToAccountType, mostRelevantToClientId);
+ }
+ }
+
+ return AccountTransferData.template(fromOffice, fromClient,
+ fromAccountTypeData, fromAccount, transferDate, toOffice,
+ toClient, toAccountTypeData, toAccount, fromOfficeOptions,
+ fromClientOptions, fromAccountTypeOptions, fromAccountOptions,
+ toOfficeOptions, toClientOptions, toAccountTypeOptions,
+ toAccountOptions);
+ }
+
+ @Override
+ public BigDecimal getTotalTransactionAmount(Long accountId,
+ Integer accountType, LocalDate transactionDate) {
+ StringBuilder sqlBuilder = new StringBuilder(
+ " select sum(trans.amount) as totalTransactionAmount ");
+ sqlBuilder.append(" from m_account_transfer_details as det ");
+ sqlBuilder
+ .append(" inner join m_account_transfer_transaction as trans ");
+ sqlBuilder.append(" on det.id = trans.account_transfer_details_id ");
+ sqlBuilder.append(" where trans.is_reversed = 0 ");
+ sqlBuilder.append(" and trans.transaction_date = ? ");
+ sqlBuilder
+ .append(" and IF(1=?, det.from_loan_account_id = ?, det.from_savings_account_id = ?) ");
+
+ return this.jdbcTemplate.queryForObject(sqlBuilder.toString(),
+ new Object[] { this.formatter.print(transactionDate),
+ accountType, accountId, accountId }, BigDecimal.class);
+ }
}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java
index 845cc671c..b306d705c 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java
@@ -69,6 +69,8 @@ public interface LoanRepository extends JpaRepository, 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 getGroupLoansDisbursedAfter(@Param("disbursementDate") Date disbursementDate, @Param("groupId") Long groupId,
@Param("loanType") Integer loanType);
@@ -144,5 +146,7 @@ public interface LoanRepository extends JpaRepository, JpaSpecificat
@Query(DOES_PRODUCT_HAVE_NON_CLOSED_LOANS)
boolean doNonClosedLoanAccountsExistForProduct(@Param("productId") Long productId);
-
+
+ @Query(FIND_BY_ACCOUNT_NUMBER)
+ Loan findNonClosedLoanByAccountNumber(@Param("accountNumber") String accountNumber);
}
\ No newline at end of file
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepository.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepository.java
index b34e89794..b614b259e 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepository.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepository.java
@@ -45,4 +45,7 @@ public interface SavingsAccountRepository extends JpaRepository templateData = this.selfAccountTransferReadService
- .retrieveSelfAccountTemplateData(user);
-
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper
.process(uriInfo.getQueryParameters());
- return this.toApiJsonSerializer.serialize(settings,
- new SelfAccountTransferData(templateData));
+ Collection selfTemplateData = this.selfAccountTransferReadService
+ .retrieveSelfAccountTemplateData(user);
+
+ if (type.equals("tpt")) {
+ Collection tptTemplateData = this.tptBeneficiaryReadPlatformService
+ .retrieveTPTSelfAccountTemplateData(user);
+ return this.toApiJsonSerializer.serialize(settings,
+ 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 params = this.dataValidator.validateCreate(type,
+ apiRequestBodyAsJson);
+ if (type.equals("tpt")) {
+ checkForLimits(params);
+ }
return this.accountTransfersApiResource.create(apiRequestBodyAsJson);
}
+ private void checkForLimits(Map 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());
+ }
+ }
+ }
+ }
+ }
+
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/api/SelfBeneficiariesTPTApiConstants.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/api/SelfBeneficiariesTPTApiConstants.java
new file mode 100644
index 000000000..affe03b6c
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/api/SelfBeneficiariesTPTApiConstants.java
@@ -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 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 UPDATE_REQUEST_DATA_PARAMETERS = new HashSet<>(
+ Arrays.asList(NAME_PARAM_NAME, TRANSFER_LIMIT_PARAM_NAME));
+
+ public static final Set 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));
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/api/SelfBeneficiariesTPTApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/api/SelfBeneficiariesTPTApiResource.java
new file mode 100644
index 000000000..344d9916e
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/api/SelfBeneficiariesTPTApiResource.java
@@ -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 toApiJsonSerializer;
+ private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+ private final ApiRequestParameterHelper apiRequestParameterHelper;
+ private final SelfBeneficiariesTPTReadPlatformService readPlatformService;
+
+ @Autowired
+ public SelfBeneficiariesTPTApiResource(
+ final PlatformSecurityContext context,
+ final DefaultToApiJsonSerializer 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 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 beneficiaries = this.readPlatformService
+ .retrieveAll();
+
+ final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper
+ .process(uriInfo.getQueryParameters());
+ return this.toApiJsonSerializer.serialize(settings, beneficiaries,
+ SelfBeneficiariesTPTApiConstants.RESPONSE_DATA_PARAMETERS);
+ }
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/data/SelfAccountTemplateData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/data/SelfAccountTemplateData.java
index 03e872b4e..17b2ebe3c 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/data/SelfAccountTemplateData.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/data/SelfAccountTemplateData.java
@@ -103,4 +103,13 @@ public class SelfAccountTemplateData implements
.toHashCode();
}
+ public Long getAccountId() {
+ return this.accountId;
+ }
+
+ public Integer getAccountType() {
+ return this.accountType.getId().intValue();
+ }
+
+
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/data/SelfAccountTransferData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/data/SelfAccountTransferData.java
index b3d6669f8..5ca23c29f 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/data/SelfAccountTransferData.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/data/SelfAccountTransferData.java
@@ -23,11 +23,14 @@ import java.util.Collection;
@SuppressWarnings("unused")
public class SelfAccountTransferData {
- private final Collection accountOptions;
+ private final Collection fromAccountOptions;
+ private final Collection toAccountOptions;
public SelfAccountTransferData(
- final Collection accountOptions) {
- this.accountOptions = accountOptions;
+ final Collection fromAccountOptions,
+ Collection toAccountOptions) {
+ this.fromAccountOptions = fromAccountOptions;
+ this.toAccountOptions = toAccountOptions;
}
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/data/SelfAccountTransferDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/data/SelfAccountTransferDataValidator.java
index c78852fbd..f986a678e 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/data/SelfAccountTransferDataValidator.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/data/SelfAccountTransferDataValidator.java
@@ -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 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 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 userValidAccounts = this.selfAccountTransferReadService
+ Collection validFromAccounts = this.selfAccountTransferReadService
.retrieveSelfAccountTemplateData(user);
+ Collection 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;
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/data/SelfBeneficiariesTPTData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/data/SelfBeneficiariesTPTData.java
new file mode 100644
index 000000000..ff56606c1
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/data/SelfBeneficiariesTPTData.java
@@ -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 accountTypeOptions;
+
+ public SelfBeneficiariesTPTData(
+ final Collection 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;
+ }
+
+}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/data/SelfBeneficiariesTPTDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/data/SelfBeneficiariesTPTDataValidator.java
new file mode 100644
index 000000000..2ba289959
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/data/SelfBeneficiariesTPTDataValidator.java
@@ -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 validateForCreate(String json) {
+ if (StringUtils.isBlank(json)) {
+ throw new InvalidJsonException();
+ }
+
+ final Type typeOfMap = new TypeToken