You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by na...@apache.org on 2016/05/04 09:51:09 UTC
[1/2] incubator-fineract git commit: Customer Self Service : APIs for
Third Party Beneficiary management and Third Party Account Transfers
Repository: incubator-fineract
Updated Branches:
refs/heads/develop 9d4d90121 -> 2bd3b0625
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/api/SelfAccountTransferApiResource.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/api/SelfAccountTransferApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/api/SelfAccountTransferApiResource.java
index 60b6e07..dad8da9 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/api/SelfAccountTransferApiResource.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/api/SelfAccountTransferApiResource.java
@@ -18,27 +18,37 @@
*/
package org.apache.fineract.portfolio.self.account.api;
+import java.math.BigDecimal;
import java.util.Collection;
+import java.util.Map;
import javax.ws.rs.Consumes;
+import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriInfo;
+import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.portfolio.account.api.AccountTransfersApiResource;
+import org.apache.fineract.portfolio.account.service.AccountTransfersReadPlatformService;
import org.apache.fineract.portfolio.self.account.data.SelfAccountTemplateData;
import org.apache.fineract.portfolio.self.account.data.SelfAccountTransferData;
import org.apache.fineract.portfolio.self.account.data.SelfAccountTransferDataValidator;
+import org.apache.fineract.portfolio.self.account.exception.BeneficiaryTransferLimitExceededException;
+import org.apache.fineract.portfolio.self.account.exception.DailyTPTTransactionAmountLimitExceededException;
import org.apache.fineract.portfolio.self.account.service.SelfAccountTransferReadService;
+import org.apache.fineract.portfolio.self.account.service.SelfBeneficiariesTPTReadPlatformService;
import org.apache.fineract.useradministration.domain.AppUser;
+import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@@ -54,6 +64,9 @@ public class SelfAccountTransferApiResource {
private final SelfAccountTransferReadService selfAccountTransferReadService;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final SelfAccountTransferDataValidator dataValidator;
+ private final SelfBeneficiariesTPTReadPlatformService tptBeneficiaryReadPlatformService;
+ private final ConfigurationDomainService configurationDomainService;
+ private final AccountTransfersReadPlatformService accountTransfersReadPlatformService;
@Autowired
public SelfAccountTransferApiResource(
@@ -62,37 +75,101 @@ public class SelfAccountTransferApiResource {
final AccountTransfersApiResource accountTransfersApiResource,
final SelfAccountTransferReadService selfAccountTransferReadService,
final ApiRequestParameterHelper apiRequestParameterHelper,
- final SelfAccountTransferDataValidator dataValidator) {
+ final SelfAccountTransferDataValidator dataValidator,
+ final SelfBeneficiariesTPTReadPlatformService tptBeneficiaryReadPlatformService,
+ final ConfigurationDomainService configurationDomainService,
+ final AccountTransfersReadPlatformService accountTransfersReadPlatformService) {
this.context = context;
this.toApiJsonSerializer = toApiJsonSerializer;
this.accountTransfersApiResource = accountTransfersApiResource;
this.selfAccountTransferReadService = selfAccountTransferReadService;
this.apiRequestParameterHelper = apiRequestParameterHelper;
this.dataValidator = dataValidator;
+ this.tptBeneficiaryReadPlatformService = tptBeneficiaryReadPlatformService;
+ this.configurationDomainService = configurationDomainService;
+ this.accountTransfersReadPlatformService = accountTransfersReadPlatformService;
}
@GET
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
- public String template(@Context final UriInfo uriInfo) {
+ public String template(
+ @DefaultValue("") @QueryParam("type") final String type,
+ @Context final UriInfo uriInfo) {
AppUser user = this.context.authenticatedUser();
- Collection<SelfAccountTemplateData> templateData = this.selfAccountTransferReadService
- .retrieveSelfAccountTemplateData(user);
-
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper
.process(uriInfo.getQueryParameters());
- return this.toApiJsonSerializer.serialize(settings,
- new SelfAccountTransferData(templateData));
+ Collection<SelfAccountTemplateData> selfTemplateData = this.selfAccountTransferReadService
+ .retrieveSelfAccountTemplateData(user);
+
+ if (type.equals("tpt")) {
+ Collection<SelfAccountTemplateData> tptTemplateData = this.tptBeneficiaryReadPlatformService
+ .retrieveTPTSelfAccountTemplateData(user);
+ return this.toApiJsonSerializer.serialize(settings,
+ new SelfAccountTransferData(selfTemplateData,
+ tptTemplateData));
+ }
+
+ return this.toApiJsonSerializer
+ .serialize(settings, new SelfAccountTransferData(
+ selfTemplateData, selfTemplateData));
}
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
- public String create(final String apiRequestBodyAsJson) {
- this.dataValidator.validateCreate(apiRequestBodyAsJson);
+ public String create(
+ @DefaultValue("") @QueryParam("type") final String type,
+ final String apiRequestBodyAsJson) {
+ Map<String, Object> params = this.dataValidator.validateCreate(type,
+ apiRequestBodyAsJson);
+ if (type.equals("tpt")) {
+ checkForLimits(params);
+ }
return this.accountTransfersApiResource.create(apiRequestBodyAsJson);
}
+ private void checkForLimits(Map<String, Object> params) {
+ SelfAccountTemplateData fromAccount = (SelfAccountTemplateData) params
+ .get("fromAccount");
+ SelfAccountTemplateData toAccount = (SelfAccountTemplateData) params
+ .get("toAccount");
+ LocalDate transactionDate = (LocalDate) params.get("transactionDate");
+ BigDecimal transactionAmount = (BigDecimal) params
+ .get("transactionAmount");
+
+ AppUser user = this.context.authenticatedUser();
+ Long transferLimit = this.tptBeneficiaryReadPlatformService
+ .getTransferLimit(user.getId(), toAccount.getAccountId(),
+ toAccount.getAccountType());
+ if (transferLimit != null && transferLimit > 0) {
+ if (transactionAmount.compareTo(new BigDecimal(transferLimit)) > 0) {
+ throw new BeneficiaryTransferLimitExceededException();
+ }
+ }
+
+ if (this.configurationDomainService.isDailyTPTLimitEnabled()) {
+ Long dailyTPTLimit = this.configurationDomainService
+ .getDailyTPTLimit();
+ if (dailyTPTLimit != null && dailyTPTLimit > 0) {
+ BigDecimal dailyTPTLimitBD = new BigDecimal(dailyTPTLimit);
+ BigDecimal totTransactionAmount = this.accountTransfersReadPlatformService
+ .getTotalTransactionAmount(fromAccount.getAccountId(),
+ fromAccount.getAccountType(), transactionDate);
+ if (totTransactionAmount != null
+ && totTransactionAmount.compareTo(BigDecimal.ZERO) > 0) {
+ if (dailyTPTLimitBD.compareTo(totTransactionAmount) <= 0
+ || dailyTPTLimitBD.compareTo(totTransactionAmount
+ .add(transactionAmount)) < 0) {
+ throw new DailyTPTTransactionAmountLimitExceededException(
+ fromAccount.getAccountId(),
+ fromAccount.getAccountType());
+ }
+ }
+ }
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/api/SelfBeneficiariesTPTApiConstants.java
----------------------------------------------------------------------
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 0000000..affe03b
--- /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<String> CREATE_REQUEST_DATA_PARAMETERS = new HashSet<>(
+ Arrays.asList(LOCALE, NAME_PARAM_NAME, OFFICE_NAME_PARAM_NAME,
+ ACCOUNT_NUMBER_PARAM_NAME, ACCOUNT_TYPE_PARAM_NAME,
+ TRANSFER_LIMIT_PARAM_NAME));
+
+ public static final Set<String> UPDATE_REQUEST_DATA_PARAMETERS = new HashSet<>(
+ Arrays.asList(NAME_PARAM_NAME, TRANSFER_LIMIT_PARAM_NAME));
+
+ public static final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(
+ Arrays.asList(NAME_PARAM_NAME, OFFICE_NAME_PARAM_NAME,
+ ACCOUNT_NUMBER_PARAM_NAME, ACCOUNT_TYPE_PARAM_NAME,
+ TRANSFER_LIMIT_PARAM_NAME, ID_PARAM_NAME,
+ CLIENT_NAME_PARAM_NAME, ACCOUNT_TYPE_OPTIONS_PARAM_NAME));
+}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/api/SelfBeneficiariesTPTApiResource.java
----------------------------------------------------------------------
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 0000000..344d991
--- /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<SelfBeneficiariesTPTData> toApiJsonSerializer;
+ private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
+ private final ApiRequestParameterHelper apiRequestParameterHelper;
+ private final SelfBeneficiariesTPTReadPlatformService readPlatformService;
+
+ @Autowired
+ public SelfBeneficiariesTPTApiResource(
+ final PlatformSecurityContext context,
+ final DefaultToApiJsonSerializer<SelfBeneficiariesTPTData> toApiJsonSerializer,
+ final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
+ final ApiRequestParameterHelper apiRequestParameterHelper,
+ final SelfBeneficiariesTPTReadPlatformService readPlatformService) {
+ this.context = context;
+ this.toApiJsonSerializer = toApiJsonSerializer;
+ this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
+ this.apiRequestParameterHelper = apiRequestParameterHelper;
+ this.readPlatformService = readPlatformService;
+ }
+
+ @GET
+ @Path("template")
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ public String template(@Context final UriInfo uriInfo) {
+
+ final EnumOptionData loanAccountType = AccountTransferEnumerations
+ .accountType(PortfolioAccountType.LOAN);
+ final EnumOptionData savingsAccountType = AccountTransferEnumerations
+ .accountType(PortfolioAccountType.SAVINGS);
+
+ final Collection<EnumOptionData> accountTypeOptions = Arrays.asList(
+ savingsAccountType, loanAccountType);
+
+ SelfBeneficiariesTPTData templateData = new SelfBeneficiariesTPTData(
+ accountTypeOptions);
+
+ final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper
+ .process(uriInfo.getQueryParameters());
+ return this.toApiJsonSerializer.serialize(settings, templateData,
+ SelfBeneficiariesTPTApiConstants.RESPONSE_DATA_PARAMETERS);
+ }
+
+ @POST
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ public String add(final String apiRequestBodyAsJson) {
+
+ final CommandWrapper commandRequest = new CommandWrapperBuilder()
+ .addSelfServiceBeneficiaryTPT().withJson(apiRequestBodyAsJson)
+ .build();
+ final CommandProcessingResult result = this.commandsSourceWritePlatformService
+ .logCommandSource(commandRequest);
+ return this.toApiJsonSerializer.serialize(result);
+ }
+
+ @PUT
+ @Path("{beneficiaryId}")
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ public String update(@PathParam("beneficiaryId") final Long beneficiaryId,
+ final String apiRequestBodyAsJson) {
+
+ final CommandWrapper commandRequest = new CommandWrapperBuilder()
+ .updateSelfServiceBeneficiaryTPT(beneficiaryId)
+ .withJson(apiRequestBodyAsJson).build();
+ final CommandProcessingResult result = this.commandsSourceWritePlatformService
+ .logCommandSource(commandRequest);
+ return this.toApiJsonSerializer.serialize(result);
+ }
+
+ @DELETE
+ @Path("{beneficiaryId}")
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ public String delete(@PathParam("beneficiaryId") final Long beneficiaryId,
+ final String apiRequestBodyAsJson) {
+
+ final CommandWrapper commandRequest = new CommandWrapperBuilder()
+ .deleteSelfServiceBeneficiaryTPT(beneficiaryId)
+ .withJson(apiRequestBodyAsJson).build();
+ final CommandProcessingResult result = this.commandsSourceWritePlatformService
+ .logCommandSource(commandRequest);
+ return this.toApiJsonSerializer.serialize(result);
+ }
+
+ @GET
+ @Consumes({ MediaType.APPLICATION_JSON })
+ @Produces({ MediaType.APPLICATION_JSON })
+ public String retrieveAll(@Context final UriInfo uriInfo) {
+
+ this.context.authenticatedUser().validateHasReadPermission(
+ SelfBeneficiariesTPTApiConstants.BENEFICIARY_ENTITY_NAME);
+
+ final Collection<SelfBeneficiariesTPTData> beneficiaries = this.readPlatformService
+ .retrieveAll();
+
+ final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper
+ .process(uriInfo.getQueryParameters());
+ return this.toApiJsonSerializer.serialize(settings, beneficiaries,
+ SelfBeneficiariesTPTApiConstants.RESPONSE_DATA_PARAMETERS);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/data/SelfAccountTemplateData.java
----------------------------------------------------------------------
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 03e872b..17b2ebe 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();
+ }
+
+
}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/data/SelfAccountTransferData.java
----------------------------------------------------------------------
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 b3d6669..5ca23c2 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<SelfAccountTemplateData> accountOptions;
+ private final Collection<SelfAccountTemplateData> fromAccountOptions;
+ private final Collection<SelfAccountTemplateData> toAccountOptions;
public SelfAccountTransferData(
- final Collection<SelfAccountTemplateData> accountOptions) {
- this.accountOptions = accountOptions;
+ final Collection<SelfAccountTemplateData> fromAccountOptions,
+ Collection<SelfAccountTemplateData> toAccountOptions) {
+ this.fromAccountOptions = fromAccountOptions;
+ this.toAccountOptions = toAccountOptions;
}
}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/data/SelfAccountTransferDataValidator.java
----------------------------------------------------------------------
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 c78852f..f986a67 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<String,Object> validateCreate(String type, String apiRequestBodyAsJson) {
if (StringUtils.isBlank(apiRequestBodyAsJson)) {
throw new InvalidJsonException();
}
@@ -126,6 +137,16 @@ public class SelfAccountTransferDataValidator {
"Cannot transfer from Loan account to another Loan account.");
}
+ final LocalDate transactionDate = this.fromApiJsonHelper.extractLocalDateNamed(transferDateParamName, element);
+ baseDataValidator.reset().parameter(transferDateParamName).value(transactionDate).notNull();
+
+ final BigDecimal transactionAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(transferAmountParamName, element);
+ baseDataValidator.reset().parameter(transferAmountParamName).value(transactionAmount).notNull().positiveAmount();
+
+ final String transactionDescription = this.fromApiJsonHelper.extractStringNamed(transferDescriptionParamName, element);
+ baseDataValidator.reset().parameter(transferDescriptionParamName).value(transactionDescription).notBlank()
+ .notExceedingLengthOf(200);
+
throwExceptionIfValidationWarningsExist(dataValidationErrors);
SelfAccountTemplateData fromAccount = new SelfAccountTemplateData(
@@ -133,21 +154,35 @@ public class SelfAccountTransferDataValidator {
SelfAccountTemplateData toAccount = new SelfAccountTemplateData(
toAccountId, toAccountType, toClientId, toOfficeId);
- validateSelfUserAccounts(fromAccount, toAccount, baseDataValidator);
+ validateUserAccounts(fromAccount, toAccount, baseDataValidator, type);
throwExceptionIfValidationWarningsExist(dataValidationErrors);
+
+ Map<String, Object> ret = new HashMap<>();
+ ret.put("fromAccount", fromAccount);
+ ret.put("toAccount", toAccount);
+ ret.put("transactionDate", transactionDate);
+ ret.put("transactionAmount", transactionAmount);
+
+ return ret;
}
- private void validateSelfUserAccounts(
+ private void validateUserAccounts(
final SelfAccountTemplateData fromAccount,
final SelfAccountTemplateData toAccount,
- final DataValidatorBuilder baseDataValidator) {
+ final DataValidatorBuilder baseDataValidator, final String type) {
AppUser user = this.context.authenticatedUser();
- Collection<SelfAccountTemplateData> userValidAccounts = this.selfAccountTransferReadService
+ Collection<SelfAccountTemplateData> validFromAccounts = this.selfAccountTransferReadService
.retrieveSelfAccountTemplateData(user);
+ Collection<SelfAccountTemplateData> validToAccounts = validFromAccounts;
+ if (type.equals("tpt")) {
+ validToAccounts = this.tptBeneficiaryReadPlatformService
+ .retrieveTPTSelfAccountTemplateData(user);
+ }
+
boolean validFromAccount = false;
- for (SelfAccountTemplateData validAccount : userValidAccounts) {
+ for (SelfAccountTemplateData validAccount : validFromAccounts) {
if (validAccount.equals(fromAccount)) {
validFromAccount = true;
break;
@@ -155,7 +190,7 @@ public class SelfAccountTransferDataValidator {
}
boolean validToAccount = false;
- for (SelfAccountTemplateData validAccount : userValidAccounts) {
+ for (SelfAccountTemplateData validAccount : validToAccounts) {
if (validAccount.equals(toAccount)) {
validToAccount = true;
break;
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/data/SelfBeneficiariesTPTData.java
----------------------------------------------------------------------
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 0000000..ff56606
--- /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<EnumOptionData> accountTypeOptions;
+
+ public SelfBeneficiariesTPTData(
+ final Collection<EnumOptionData> accountTypeOptions) {
+ this.accountTypeOptions = accountTypeOptions;
+ this.id = null;
+ this.name = null;
+ this.officeName = null;
+ this.clientName = null;
+ this.accountType = null;
+ this.accountNumber = null;
+ this.transferLimit = null;
+ }
+
+ public SelfBeneficiariesTPTData(final Long id, final String name,
+ final String officeName, final String clientName,
+ final EnumOptionData accountType, final String accountNumber,
+ final Long transferLimit) {
+ this.accountTypeOptions = null;
+ this.id = id;
+ this.name = name;
+ this.officeName = officeName;
+ this.clientName = clientName;
+ this.accountType = accountType;
+ this.accountNumber = accountNumber;
+ this.transferLimit = transferLimit;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/data/SelfBeneficiariesTPTDataValidator.java
----------------------------------------------------------------------
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 0000000..2ba2899
--- /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<String, Object> validateForCreate(String json) {
+ if (StringUtils.isBlank(json)) {
+ throw new InvalidJsonException();
+ }
+
+ final Type typeOfMap = new TypeToken<Map<String, Object>>() {
+ }.getType();
+ this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json,
+ CREATE_REQUEST_DATA_PARAMETERS);
+
+ final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+ final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(
+ dataValidationErrors).resource(RESOURCE_NAME);
+ final JsonElement element = this.fromApiJsonHelper.parse(json);
+
+ final String name = this.fromApiJsonHelper.extractStringNamed(
+ NAME_PARAM_NAME, element);
+ baseDataValidator.reset().parameter(NAME_PARAM_NAME).value(name)
+ .notBlank().notExceedingLengthOf(50);
+
+ final String officeName = this.fromApiJsonHelper.extractStringNamed(
+ OFFICE_NAME_PARAM_NAME, element);
+ baseDataValidator.reset().parameter(OFFICE_NAME_PARAM_NAME)
+ .value(officeName).notBlank()
+ .notExceedingLengthOf(50);
+
+ final String accountNo = this.fromApiJsonHelper.extractStringNamed(
+ ACCOUNT_NUMBER_PARAM_NAME, element);
+ baseDataValidator.reset().parameter(ACCOUNT_NUMBER_PARAM_NAME)
+ .value(accountNo).notBlank().notExceedingLengthOf(20);
+
+ final Integer accountType = this.fromApiJsonHelper.extractIntegerNamed(
+ ACCOUNT_TYPE_PARAM_NAME, element, this.fromApiJsonHelper
+ .extractLocaleParameter(element.getAsJsonObject()));
+ baseDataValidator
+ .reset()
+ .parameter(ACCOUNT_TYPE_PARAM_NAME)
+ .value(accountType)
+ .notNull()
+ .isOneOfTheseValues(PortfolioAccountType.LOAN.getValue(),
+ PortfolioAccountType.SAVINGS.getValue());
+
+ final Long transferLimit = this.fromApiJsonHelper.extractLongNamed(
+ TRANSFER_LIMIT_PARAM_NAME, element);
+ baseDataValidator.reset().parameter(TRANSFER_LIMIT_PARAM_NAME)
+ .value(transferLimit).ignoreIfNull().longGreaterThanZero();
+
+ throwExceptionIfValidationWarningsExist(dataValidationErrors);
+
+ HashMap<String, Object> ret = new HashMap<>();
+ ret.put(NAME_PARAM_NAME, name);
+ ret.put(OFFICE_NAME_PARAM_NAME, officeName);
+ ret.put(ACCOUNT_NUMBER_PARAM_NAME, accountNo);
+ ret.put(ACCOUNT_TYPE_PARAM_NAME, accountType);
+ ret.put(TRANSFER_LIMIT_PARAM_NAME, transferLimit);
+
+ return ret;
+ }
+
+ public HashMap<String, Object> validateForUpdate(String json) {
+ if (StringUtils.isBlank(json)) {
+ throw new InvalidJsonException();
+ }
+
+ final Type typeOfMap = new TypeToken<Map<String, Object>>() {
+ }.getType();
+ this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json,
+ UPDATE_REQUEST_DATA_PARAMETERS);
+
+ final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+ final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(
+ dataValidationErrors).resource(RESOURCE_NAME);
+ final JsonElement element = this.fromApiJsonHelper.parse(json);
+
+ HashMap<String, Object> ret = new HashMap<>();
+
+ if (this.fromApiJsonHelper.parameterExists(NAME_PARAM_NAME, element)) {
+ final String name = this.fromApiJsonHelper.extractStringNamed(
+ NAME_PARAM_NAME, element);
+ baseDataValidator.reset().parameter(NAME_PARAM_NAME).value(name)
+ .notBlank().notExceedingLengthOf(50);
+ ret.put(NAME_PARAM_NAME, name);
+ }
+
+ if (this.fromApiJsonHelper.parameterExists(TRANSFER_LIMIT_PARAM_NAME,
+ element)) {
+ final Long transferLimit = this.fromApiJsonHelper.extractLongNamed(
+ TRANSFER_LIMIT_PARAM_NAME, element);
+ baseDataValidator.reset().parameter(TRANSFER_LIMIT_PARAM_NAME)
+ .value(transferLimit).ignoreIfNull().longGreaterThanZero();
+ ret.put(TRANSFER_LIMIT_PARAM_NAME, transferLimit);
+ }
+
+ throwExceptionIfValidationWarningsExist(dataValidationErrors);
+
+ return ret;
+ }
+
+ private void throwExceptionIfValidationWarningsExist(
+ final List<ApiParameterError> dataValidationErrors) {
+ if (!dataValidationErrors.isEmpty()) {
+ throw new PlatformApiDataValidationException(dataValidationErrors);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/domain/SelfBeneficiariesTPT.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/domain/SelfBeneficiariesTPT.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/domain/SelfBeneficiariesTPT.java
new file mode 100644
index 0000000..76d0432
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/domain/SelfBeneficiariesTPT.java
@@ -0,0 +1,136 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.self.account.domain;
+
+import static org.apache.fineract.portfolio.self.account.api.SelfBeneficiariesTPTApiConstants.NAME_PARAM_NAME;
+import static org.apache.fineract.portfolio.self.account.api.SelfBeneficiariesTPTApiConstants.TRANSFER_LIMIT_PARAM_NAME;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import org.springframework.data.jpa.domain.AbstractPersistable;
+
+@Entity
+@Table(name = "m_selfservice_beneficiaries_tpt", uniqueConstraints = { @UniqueConstraint(columnNames = {
+ "name", "app_user_id", "is_active" }, name = "name") })
+public class SelfBeneficiariesTPT extends AbstractPersistable<Long> {
+
+ @Column(name = "app_user_id", nullable = false)
+ private Long appUserId;
+
+ @Column(name = "name", length = 50, nullable = false)
+ private String name;
+
+ @Column(name = "office_id", nullable = false)
+ private Long officeId;
+
+ @Column(name = "client_id", nullable = false)
+ private Long clientId;
+
+ @Column(name = "account_id", nullable = false)
+ private Long accountId;
+
+ @Column(name = "account_type", nullable = false)
+ private Integer accountType;
+
+ @Column(name = "transfer_limit", nullable = true)
+ private Long transferLimit;
+
+ @Column(name = "is_active", nullable = false)
+ private boolean isActive = true;
+
+ protected SelfBeneficiariesTPT() {
+ //
+ }
+
+ public SelfBeneficiariesTPT(Long appUserId, String name, Long officeId,
+ Long clientId, Long accountId, Integer accountType,
+ Long transferLimit) {
+ this.appUserId = appUserId;
+ this.name = name;
+ this.officeId = officeId;
+ this.clientId = clientId;
+ this.accountId = accountId;
+ this.accountType = accountType;
+ this.transferLimit = transferLimit;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Long getTransferLimit() {
+ return this.transferLimit;
+ }
+
+ public void setTransferLimit(Long transferLimit) {
+ this.transferLimit = transferLimit;
+ }
+
+ public boolean isActive() {
+ return this.isActive;
+ }
+
+ public void setActive(boolean isActive) {
+ this.isActive = isActive;
+ }
+
+ public Long getAppUserId() {
+ return this.appUserId;
+ }
+
+ public Long getOfficeId() {
+ return this.officeId;
+ }
+
+ public Long getClientId() {
+ return this.clientId;
+ }
+
+ public Long getAccountId() {
+ return this.accountId;
+ }
+
+ public Integer getAccountType() {
+ return this.accountType;
+ }
+
+ public Map<String, Object> update(String newName, Long newTransferLimit) {
+ Map<String, Object> changes = new HashMap<>();
+ if (!this.name.equals(newName)) {
+ this.name = newName;
+ changes.put(NAME_PARAM_NAME, newName);
+ }
+ if ((this.transferLimit !=null && !this.transferLimit.equals(newTransferLimit))
+ || (this.transferLimit == null && newTransferLimit != null)) {
+ this.transferLimit = newTransferLimit;
+ changes.put(TRANSFER_LIMIT_PARAM_NAME, newTransferLimit);
+ }
+ return changes;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/domain/SelfBeneficiariesTPTRepository.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/domain/SelfBeneficiariesTPTRepository.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/domain/SelfBeneficiariesTPTRepository.java
new file mode 100644
index 0000000..a74ebea
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/domain/SelfBeneficiariesTPTRepository.java
@@ -0,0 +1,28 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.self.account.domain;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+public interface SelfBeneficiariesTPTRepository extends
+ JpaRepository<SelfBeneficiariesTPT, Long>,
+ JpaSpecificationExecutor<SelfBeneficiariesTPT> {
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/exception/BeneficiaryTransferLimitExceededException.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/exception/BeneficiaryTransferLimitExceededException.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/exception/BeneficiaryTransferLimitExceededException.java
new file mode 100644
index 0000000..3623d33
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/exception/BeneficiaryTransferLimitExceededException.java
@@ -0,0 +1,30 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.self.account.exception;
+
+import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
+
+public class BeneficiaryTransferLimitExceededException extends AbstractPlatformDomainRuleException {
+
+ public BeneficiaryTransferLimitExceededException() {
+ super("error.msg.beneficiary.transfer.amount.limit.for.beneficiary.exceeded",
+ "Transfer amount limit for beneficiary exceeded");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/exception/DailyTPTTransactionAmountLimitExceededException.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/exception/DailyTPTTransactionAmountLimitExceededException.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/exception/DailyTPTTransactionAmountLimitExceededException.java
new file mode 100644
index 0000000..fb365f8
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/exception/DailyTPTTransactionAmountLimitExceededException.java
@@ -0,0 +1,31 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.self.account.exception;
+
+import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
+
+public class DailyTPTTransactionAmountLimitExceededException extends AbstractPlatformDomainRuleException {
+
+ public DailyTPTTransactionAmountLimitExceededException(Long accountId,
+ Integer accountType) {
+ super("error.msg.beneficiary.daily.tpt.transfer.limit.for.fromaccountid."+accountId+".fromaccounttype."+accountType+".exceeded",
+ "Daily third party transfer limit for the source account excceeded");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/exception/InvalidAccountInformationException.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/exception/InvalidAccountInformationException.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/exception/InvalidAccountInformationException.java
new file mode 100644
index 0000000..7362077
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/exception/InvalidAccountInformationException.java
@@ -0,0 +1,32 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.self.account.exception;
+
+import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
+
+public class InvalidAccountInformationException extends
+ AbstractPlatformDomainRuleException {
+ public InvalidAccountInformationException(final String officeName,
+ final String accountNumber, final String accountType) {
+ super("error.msg.beneficiary.invalid.account.details.with.officeName."
+ + officeName + ".accountNumber." + accountNumber
+ + ".accountType." + accountType,
+ "Invalid Office Name, Account Number, Account Type combination");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/exception/InvalidBeneficiaryException.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/exception/InvalidBeneficiaryException.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/exception/InvalidBeneficiaryException.java
new file mode 100644
index 0000000..daac892
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/exception/InvalidBeneficiaryException.java
@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.self.account.exception;
+
+import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
+
+public class InvalidBeneficiaryException extends
+ AbstractPlatformDomainRuleException {
+ public InvalidBeneficiaryException(final Long beneficiaryId) {
+ super("error.msg.beneficiary.invalid.beneficiary.id." + beneficiaryId,
+ "Beneficiary ID doesn't belong to the User");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/handler/AddSelfBeneficiariesTPTCommandHandler.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/handler/AddSelfBeneficiariesTPTCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/handler/AddSelfBeneficiariesTPTCommandHandler.java
new file mode 100644
index 0000000..cd88fa1
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/handler/AddSelfBeneficiariesTPTCommandHandler.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.self.account.handler;
+
+import org.apache.fineract.commands.annotation.CommandType;
+import org.apache.fineract.commands.handler.NewCommandSourceHandler;
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.portfolio.self.account.service.SelfBeneficiariesTPTWritePlatformService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+@CommandType(entity = "SSBENEFICIARYTPT", action = "CREATE")
+public class AddSelfBeneficiariesTPTCommandHandler implements
+ NewCommandSourceHandler {
+ private final SelfBeneficiariesTPTWritePlatformService writePlatformService;
+
+ @Autowired
+ public AddSelfBeneficiariesTPTCommandHandler(
+ final SelfBeneficiariesTPTWritePlatformService writePlatformService) {
+ this.writePlatformService = writePlatformService;
+ }
+
+ @Override
+ public CommandProcessingResult processCommand(final JsonCommand command) {
+ return this.writePlatformService.add(command);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/handler/DeleteSelfBeneficiariesTPTCommandHandler.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/handler/DeleteSelfBeneficiariesTPTCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/handler/DeleteSelfBeneficiariesTPTCommandHandler.java
new file mode 100644
index 0000000..46f3780
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/handler/DeleteSelfBeneficiariesTPTCommandHandler.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.self.account.handler;
+
+import org.apache.fineract.commands.annotation.CommandType;
+import org.apache.fineract.commands.handler.NewCommandSourceHandler;
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.portfolio.self.account.service.SelfBeneficiariesTPTWritePlatformService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+@CommandType(entity = "SSBENEFICIARYTPT", action = "DELETE")
+public class DeleteSelfBeneficiariesTPTCommandHandler implements
+ NewCommandSourceHandler {
+ private final SelfBeneficiariesTPTWritePlatformService writePlatformService;
+
+ @Autowired
+ public DeleteSelfBeneficiariesTPTCommandHandler(
+ final SelfBeneficiariesTPTWritePlatformService writePlatformService) {
+ this.writePlatformService = writePlatformService;
+ }
+
+ @Override
+ public CommandProcessingResult processCommand(final JsonCommand command) {
+ return this.writePlatformService.delete(command);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/handler/UpdateSelfBeneficiariesTPTCommandHandler.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/handler/UpdateSelfBeneficiariesTPTCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/handler/UpdateSelfBeneficiariesTPTCommandHandler.java
new file mode 100644
index 0000000..e92123e
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/handler/UpdateSelfBeneficiariesTPTCommandHandler.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.self.account.handler;
+
+import org.apache.fineract.commands.annotation.CommandType;
+import org.apache.fineract.commands.handler.NewCommandSourceHandler;
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.portfolio.self.account.service.SelfBeneficiariesTPTWritePlatformService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+@CommandType(entity = "SSBENEFICIARYTPT", action = "UPDATE")
+public class UpdateSelfBeneficiariesTPTCommandHandler implements
+ NewCommandSourceHandler {
+ private final SelfBeneficiariesTPTWritePlatformService writePlatformService;
+
+ @Autowired
+ public UpdateSelfBeneficiariesTPTCommandHandler(
+ final SelfBeneficiariesTPTWritePlatformService writePlatformService) {
+ this.writePlatformService = writePlatformService;
+ }
+
+ @Override
+ public CommandProcessingResult processCommand(final JsonCommand command) {
+ return this.writePlatformService.update(command);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/service/SelfBeneficiariesTPTReadPlatformService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/service/SelfBeneficiariesTPTReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/service/SelfBeneficiariesTPTReadPlatformService.java
new file mode 100644
index 0000000..d60b47f
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/service/SelfBeneficiariesTPTReadPlatformService.java
@@ -0,0 +1,36 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.self.account.service;
+
+import java.util.Collection;
+
+import org.apache.fineract.portfolio.self.account.data.SelfAccountTemplateData;
+import org.apache.fineract.portfolio.self.account.data.SelfBeneficiariesTPTData;
+import org.apache.fineract.useradministration.domain.AppUser;
+
+public interface SelfBeneficiariesTPTReadPlatformService {
+
+ Collection<SelfBeneficiariesTPTData> retrieveAll();
+
+ Collection<SelfAccountTemplateData> retrieveTPTSelfAccountTemplateData(
+ AppUser user);
+
+ Long getTransferLimit(Long id, Long accountId, Integer accountType);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/service/SelfBeneficiariesTPTReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/service/SelfBeneficiariesTPTReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/service/SelfBeneficiariesTPTReadPlatformServiceImpl.java
new file mode 100644
index 0000000..c209a4d
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/service/SelfBeneficiariesTPTReadPlatformServiceImpl.java
@@ -0,0 +1,222 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.self.account.service;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collection;
+
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
+import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import org.apache.fineract.portfolio.account.PortfolioAccountType;
+import org.apache.fineract.portfolio.account.service.AccountTransferEnumerations;
+import org.apache.fineract.portfolio.self.account.data.SelfAccountTemplateData;
+import org.apache.fineract.portfolio.self.account.data.SelfBeneficiariesTPTData;
+import org.apache.fineract.useradministration.domain.AppUser;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Service;
+
+@Service
+public class SelfBeneficiariesTPTReadPlatformServiceImpl implements
+ SelfBeneficiariesTPTReadPlatformService {
+
+ private final PlatformSecurityContext context;
+ private final JdbcTemplate jdbcTemplate;
+ private final BeneficiaryMapper mapper;
+ private final AccountTemplateMapper accountTemplateMapper;
+
+ @Autowired
+ public SelfBeneficiariesTPTReadPlatformServiceImpl(
+ final PlatformSecurityContext context,
+ final RoutingDataSource dataSource) {
+ this.context = context;
+ this.jdbcTemplate = new JdbcTemplate(dataSource);
+ this.mapper = new BeneficiaryMapper();
+ this.accountTemplateMapper = new AccountTemplateMapper();
+ }
+
+ @Override
+ public Collection<SelfBeneficiariesTPTData> retrieveAll() {
+ AppUser user = this.context.authenticatedUser();
+ return this.jdbcTemplate.query(this.mapper.schema(), this.mapper,
+ new Object[] { user.getId(), user.getId() });
+ }
+
+ @Override
+ public Collection<SelfAccountTemplateData> retrieveTPTSelfAccountTemplateData(
+ AppUser user) {
+ return this.jdbcTemplate.query(this.accountTemplateMapper.schema(),
+ this.accountTemplateMapper,
+ new Object[] { user.getId(), user.getId() });
+ }
+
+ private static final class BeneficiaryMapper implements
+ RowMapper<SelfBeneficiariesTPTData> {
+
+ private final String schemaSql;
+
+ public BeneficiaryMapper() {
+ final StringBuilder sqlBuilder = new StringBuilder(
+ "(select b.id as id, ");
+ sqlBuilder.append(" b.name as name, ");
+ sqlBuilder.append(" o.name as officeName, ");
+ sqlBuilder.append(" c.display_name as clientName, ");
+ sqlBuilder.append(" b.account_type as accountType, ");
+ sqlBuilder.append(" s.account_no as accountNumber, ");
+ sqlBuilder.append(" b.transfer_limit as transferLimit ");
+ sqlBuilder.append(" from m_selfservice_beneficiaries_tpt as b ");
+ sqlBuilder
+ .append(" inner join m_office as o on b.office_id = o.id ");
+ sqlBuilder
+ .append(" inner join m_client as c on b.client_id = c.id ");
+ sqlBuilder
+ .append(" inner join m_savings_account as s on b.account_id = s.id ");
+ sqlBuilder.append(" where b.is_active = 1 ");
+ sqlBuilder.append(" and b.account_type = 2 ");
+ sqlBuilder.append(" and b.app_user_id = ?) ");
+ sqlBuilder.append(" union all ");
+ sqlBuilder.append(" (select b.id as id, ");
+ sqlBuilder.append(" b.name as name, ");
+ sqlBuilder.append(" o.name as officeName, ");
+ sqlBuilder.append(" c.display_name as clientName, ");
+ sqlBuilder.append(" b.account_type as accountType, ");
+ sqlBuilder.append(" l.account_no as accountNumber, ");
+ sqlBuilder.append(" b.transfer_limit as transferLimit ");
+ sqlBuilder.append(" from m_selfservice_beneficiaries_tpt as b ");
+ sqlBuilder
+ .append(" inner join m_office as o on b.office_id = o.id ");
+ sqlBuilder
+ .append(" inner join m_client as c on b.client_id = c.id ");
+ sqlBuilder
+ .append(" inner join m_loan as l on b.account_id = l.id ");
+ sqlBuilder.append(" where b.is_active = 1 ");
+ sqlBuilder.append(" and b.account_type = 1 ");
+ sqlBuilder.append(" and b.app_user_id = ?) ");
+
+ this.schemaSql = sqlBuilder.toString();
+ }
+
+ public String schema() {
+ return this.schemaSql;
+ }
+
+ @Override
+ public SelfBeneficiariesTPTData mapRow(final ResultSet rs,
+ @SuppressWarnings("unused") final int rowNum)
+ throws SQLException {
+
+ final Long id = rs.getLong("id");
+ final String name = rs.getString("name");
+ final String officeName = rs.getString("officeName");
+ final String clientName = rs.getString("clientName");
+ final Integer accountTypeId = rs.getInt("accountType");
+ final EnumOptionData accountType = AccountTransferEnumerations
+ .accountType(PortfolioAccountType.fromInt(accountTypeId));
+ final String accountNumber = rs.getString("accountNumber");
+ final Long transferLimit = rs.getLong("transferLimit");
+
+ return new SelfBeneficiariesTPTData(id, name, officeName,
+ clientName, accountType, accountNumber, transferLimit);
+ }
+ }
+
+ private static final class AccountTemplateMapper implements
+ RowMapper<SelfAccountTemplateData> {
+
+ private final String schemaSql;
+
+ public AccountTemplateMapper() {
+ final StringBuilder sqlBuilder = new StringBuilder(
+ "(select o.name as officeName, ");
+ sqlBuilder.append(" o.id as officeId, ");
+ sqlBuilder.append(" c.display_name as clientName, ");
+ sqlBuilder.append(" c.id as clientId, ");
+ sqlBuilder.append(" b.account_type as accountType, ");
+ sqlBuilder.append(" s.account_no as accountNumber, ");
+ sqlBuilder.append(" s.id as accountId ");
+ sqlBuilder.append(" from m_selfservice_beneficiaries_tpt as b ");
+ sqlBuilder
+ .append(" inner join m_office as o on b.office_id = o.id ");
+ sqlBuilder
+ .append(" inner join m_client as c on b.client_id = c.id ");
+ sqlBuilder
+ .append(" inner join m_savings_account as s on b.account_id = s.id ");
+ sqlBuilder.append(" where b.is_active = 1 ");
+ sqlBuilder.append(" and b.account_type = 2 ");
+ sqlBuilder.append(" and b.app_user_id = ?) ");
+ sqlBuilder.append(" union all ");
+ sqlBuilder.append(" (select o.name as officeName, ");
+ sqlBuilder.append(" o.id as officeId, ");
+ sqlBuilder.append(" c.display_name as clientName, ");
+ sqlBuilder.append(" c.id as clientId, ");
+ sqlBuilder.append(" b.account_type as accountType, ");
+ sqlBuilder.append(" l.account_no as accountNumber, ");
+ sqlBuilder.append(" l.id as accountId ");
+ sqlBuilder.append(" from m_selfservice_beneficiaries_tpt as b ");
+ sqlBuilder
+ .append(" inner join m_office as o on b.office_id = o.id ");
+ sqlBuilder
+ .append(" inner join m_client as c on b.client_id = c.id ");
+ sqlBuilder
+ .append(" inner join m_loan as l on b.account_id = l.id ");
+ sqlBuilder.append(" where b.is_active = 1 ");
+ sqlBuilder.append(" and b.account_type = 1 ");
+ sqlBuilder.append(" and b.app_user_id = ?) ");
+
+ this.schemaSql = sqlBuilder.toString();
+ }
+
+ public String schema() {
+ return this.schemaSql;
+ }
+
+ @Override
+ public SelfAccountTemplateData mapRow(final ResultSet rs,
+ @SuppressWarnings("unused") final int rowNum)
+ throws SQLException {
+
+ final String officeName = rs.getString("officeName");
+ final Long officeId = rs.getLong("officeId");
+ final String clientName = rs.getString("clientName");
+ final Long clientId = rs.getLong("clientId");
+ final Integer accountTypeId = rs.getInt("accountType");
+ final String accountNumber = rs.getString("accountNumber");
+ final Long accountId = rs.getLong("accountId");
+
+ return new SelfAccountTemplateData(accountId, accountNumber,
+ accountTypeId, clientId, clientName, officeId, officeName);
+ }
+ }
+
+ @Override
+ public Long getTransferLimit(Long appUserId, Long accountId, Integer accountType) {
+ final StringBuilder sqlBuilder = new StringBuilder("select b.transfer_limit ");
+ sqlBuilder.append(" from m_selfservice_beneficiaries_tpt as b ");
+ sqlBuilder.append(" where b.app_user_id = ? ");
+ sqlBuilder.append(" and b.account_id = ? ");
+ sqlBuilder.append(" and b.account_type = ? ");
+ sqlBuilder.append(" and b.is_active = 1; ");
+
+ return this.jdbcTemplate.queryForObject(sqlBuilder.toString(),
+ new Object[]{appUserId, accountId, accountType}, Long.class);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/service/SelfBeneficiariesTPTWritePlatformService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/service/SelfBeneficiariesTPTWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/service/SelfBeneficiariesTPTWritePlatformService.java
new file mode 100644
index 0000000..5d4519b
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/service/SelfBeneficiariesTPTWritePlatformService.java
@@ -0,0 +1,32 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.self.account.service;
+
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+
+public interface SelfBeneficiariesTPTWritePlatformService {
+
+ CommandProcessingResult add(JsonCommand command);
+
+ CommandProcessingResult update(JsonCommand command);
+
+ CommandProcessingResult delete(JsonCommand command);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/service/SelfBeneficiariesTPTWritePlatformServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/service/SelfBeneficiariesTPTWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/service/SelfBeneficiariesTPTWritePlatformServiceImpl.java
new file mode 100644
index 0000000..9a4e8fd
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/service/SelfBeneficiariesTPTWritePlatformServiceImpl.java
@@ -0,0 +1,212 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.self.account.service;
+
+import static org.apache.fineract.portfolio.self.account.api.SelfBeneficiariesTPTApiConstants.ACCOUNT_NUMBER_PARAM_NAME;
+import static org.apache.fineract.portfolio.self.account.api.SelfBeneficiariesTPTApiConstants.ACCOUNT_TYPE_PARAM_NAME;
+import static org.apache.fineract.portfolio.self.account.api.SelfBeneficiariesTPTApiConstants.NAME_PARAM_NAME;
+import static org.apache.fineract.portfolio.self.account.api.SelfBeneficiariesTPTApiConstants.OFFICE_NAME_PARAM_NAME;
+import static org.apache.fineract.portfolio.self.account.api.SelfBeneficiariesTPTApiConstants.TRANSFER_LIMIT_PARAM_NAME;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
+import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
+import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import org.apache.fineract.portfolio.account.PortfolioAccountType;
+import org.apache.fineract.portfolio.loanaccount.domain.Loan;
+import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
+import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
+import org.apache.fineract.portfolio.savings.domain.SavingsAccountRepository;
+import org.apache.fineract.portfolio.self.account.data.SelfBeneficiariesTPTDataValidator;
+import org.apache.fineract.portfolio.self.account.domain.SelfBeneficiariesTPT;
+import org.apache.fineract.portfolio.self.account.domain.SelfBeneficiariesTPTRepository;
+import org.apache.fineract.portfolio.self.account.exception.InvalidAccountInformationException;
+import org.apache.fineract.portfolio.self.account.exception.InvalidBeneficiaryException;
+import org.apache.fineract.useradministration.domain.AppUser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataAccessException;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+public class SelfBeneficiariesTPTWritePlatformServiceImpl implements
+ SelfBeneficiariesTPTWritePlatformService {
+
+ private final Logger logger;
+ private final PlatformSecurityContext context;
+ private final SelfBeneficiariesTPTRepository repository;
+ private final SelfBeneficiariesTPTDataValidator validator;
+ private final LoanRepository loanRepo;
+ private final SavingsAccountRepository savingRepo;
+
+ @Autowired
+ public SelfBeneficiariesTPTWritePlatformServiceImpl(
+ final PlatformSecurityContext context,
+ final SelfBeneficiariesTPTRepository repository,
+ final SelfBeneficiariesTPTDataValidator validator,
+ final LoanRepository loanRepo,
+ final SavingsAccountRepository savingRepo) {
+ this.context = context;
+ this.repository = repository;
+ this.validator = validator;
+ this.loanRepo = loanRepo;
+ this.savingRepo = savingRepo;
+ this.logger = LoggerFactory
+ .getLogger(SelfBeneficiariesTPTWritePlatformServiceImpl.class);
+ }
+
+ @Transactional
+ @Override
+ public CommandProcessingResult add(JsonCommand command) {
+ HashMap<String, Object> params = this.validator
+ .validateForCreate(command.json());
+
+ String name = (String) params.get(NAME_PARAM_NAME);
+ Integer accountType = (Integer) params.get(ACCOUNT_TYPE_PARAM_NAME);
+ String accountNumber = (String) params.get(ACCOUNT_NUMBER_PARAM_NAME);
+ String officeName = (String) params.get(OFFICE_NAME_PARAM_NAME);
+ Long transferLimit = (Long) params.get(TRANSFER_LIMIT_PARAM_NAME);
+
+ Long accountId = null;
+ Long clientId = null;
+ Long officeId = null;
+
+ boolean validAccountDetails = true;
+ if (accountType.equals(PortfolioAccountType.LOAN)) {
+ Loan loan = this.loanRepo
+ .findNonClosedLoanByAccountNumber(accountNumber);
+ if (loan != null && loan.getClientId() != null
+ && loan.getOffice().getName().equals(officeName)) {
+ accountId = loan.getId();
+ officeId = loan.getOfficeId();
+ clientId = loan.getClientId();
+ } else {
+ validAccountDetails = false;
+ }
+ } else {
+ SavingsAccount savings = this.savingRepo
+ .findNonClosedAccountByAccountNumber(accountNumber);
+ if (savings != null
+ && savings.getClient() != null
+ && savings.getClient().getOffice().getName()
+ .equals(officeName)) {
+ accountId = savings.getId();
+ clientId = savings.getClient().getId();
+ officeId = savings.getClient().getOffice().getId();
+ } else {
+ validAccountDetails = false;
+ }
+ }
+
+ if (validAccountDetails) {
+ try {
+ AppUser user = this.context.authenticatedUser();
+ SelfBeneficiariesTPT beneficiary = new SelfBeneficiariesTPT(
+ user.getId(), name, officeId, clientId, accountId,
+ accountType, transferLimit);
+ this.repository.save(beneficiary);
+ return new CommandProcessingResultBuilder().withEntityId(
+ beneficiary.getId()).build();
+ } catch (DataAccessException dae) {
+ handleDataIntegrityIssues(command, dae);
+ }
+ }
+ throw new InvalidAccountInformationException(officeName, accountNumber,
+ PortfolioAccountType.fromInt(accountType).getCode());
+
+ }
+
+ @Transactional
+ @Override
+ public CommandProcessingResult update(JsonCommand command) {
+ HashMap<String, Object> params = this.validator
+ .validateForUpdate(command.json());
+ AppUser user = this.context.authenticatedUser();
+ Long beneficiaryId = command.entityId();
+ SelfBeneficiariesTPT beneficiary = this.repository
+ .findOne(beneficiaryId);
+ if (beneficiary != null
+ && beneficiary.getAppUserId().equals(user.getId())) {
+ String name = (String) params.get(NAME_PARAM_NAME);
+ Long transferLimit = (Long) params.get(TRANSFER_LIMIT_PARAM_NAME);
+
+ Map<String, Object> changes = beneficiary.update(name,
+ transferLimit);
+ if (!changes.isEmpty()) {
+ try {
+ this.repository.save(beneficiary);
+
+ return new CommandProcessingResultBuilder() //
+ .withEntityId(beneficiary.getId()) //
+ .with(changes).build();
+ } catch (DataAccessException dae) {
+ handleDataIntegrityIssues(command, dae);
+ }
+
+ }
+ }
+ throw new InvalidBeneficiaryException(beneficiaryId);
+ }
+
+ @Transactional
+ @Override
+ public CommandProcessingResult delete(JsonCommand command) {
+ AppUser user = this.context.authenticatedUser();
+ Long beneficiaryId = command.entityId();
+ SelfBeneficiariesTPT beneficiary = this.repository
+ .findOne(beneficiaryId);
+ if (beneficiary != null
+ && beneficiary.getAppUserId().equals(user.getId())) {
+
+ beneficiary.setActive(false);
+ this.repository.save(beneficiary);
+
+ return new CommandProcessingResultBuilder() //
+ .withEntityId(beneficiary.getId()) //
+ .build();
+ }
+ throw new InvalidBeneficiaryException(beneficiaryId);
+ }
+
+ private void handleDataIntegrityIssues(final JsonCommand command,
+ final DataAccessException dae) {
+
+ final Throwable realCause = dae.getMostSpecificCause();
+ if (realCause.getMessage().contains("name")) {
+
+ final String name = command
+ .stringValueOfParameterNamed(NAME_PARAM_NAME);
+ throw new PlatformDataIntegrityException(
+ "error.msg.beneficiary.duplicate.name",
+ "Beneficiary with name `" + name + "` already exists",
+ NAME_PARAM_NAME, name);
+ }
+
+ this.logger.error(dae.getMessage(), dae);
+ throw new PlatformDataIntegrityException(
+ "error.msg.beneficiary.unknown.data.integrity.issue",
+ "Unknown data integrity issue with resource.");
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/resources/sql/migrations/core_db/V304__customer_self_service_third_party_transfers.sql
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V304__customer_self_service_third_party_transfers.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V304__customer_self_service_third_party_transfers.sql
new file mode 100644
index 0000000..fc6be77
--- /dev/null
+++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V304__customer_self_service_third_party_transfers.sql
@@ -0,0 +1,24 @@
+INSERT INTO `c_configuration` (`name`, `value`, `date_value`, `enabled`, `is_trap_door`, `description`) VALUES ( 'daily-tpt-limit', 0, NULL, 0, 0, 'Daily limit for third party transfers');
+
+CREATE TABLE `m_selfservice_beneficiaries_tpt` (
+ `id` BIGINT NOT NULL AUTO_INCREMENT,
+ `app_user_id` BIGINT NOT NULL,
+ `name` VARCHAR(50) NOT NULL,
+ `office_id` BIGINT NOT NULL,
+ `client_id` BIGINT NOT NULL,
+ `account_id` BIGINT NOT NULL,
+ `account_type` SMALLINT(4) NOT NULL,
+ `transfer_limit` BIGINT NULL DEFAULT 0,
+ `is_active` BIT(1) NOT NULL DEFAULT 0,
+ PRIMARY KEY (`id`),
+ UNIQUE INDEX `name` (`name`, `app_user_id`, `is_active`)
+)
+COLLATE='utf8_general_ci'
+ENGINE=InnoDB
+;
+
+INSERT INTO `m_permission`(`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES
+('SSBENEFICIARYTPT', 'READ_SSBENEFICIARYTPT', 'SSBENEFICIARYTPT', 'READ', 0),
+('SSBENEFICIARYTPT', 'CREATE_SSBENEFICIARYTPT', 'SSBENEFICIARYTPT', 'CREATE', 0),
+('SSBENEFICIARYTPT', 'UPDATE_SSBENEFICIARYTPT', 'SSBENEFICIARYTPT', 'UPDATE', 0),
+('SSBENEFICIARYTPT', 'DELETE_SSBENEFICIARYTPT', 'SSBENEFICIARYTPT', 'DELETE', 0);
[2/2] incubator-fineract git commit: Customer Self Service : APIs for
Third Party Beneficiary management and Third Party Account Transfers
Posted by na...@apache.org.
Customer Self Service : APIs for Third Party Beneficiary management and Third Party Account Transfers
Project: http://git-wip-us.apache.org/repos/asf/incubator-fineract/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-fineract/commit/2bd3b062
Tree: http://git-wip-us.apache.org/repos/asf/incubator-fineract/tree/2bd3b062
Diff: http://git-wip-us.apache.org/repos/asf/incubator-fineract/diff/2bd3b062
Branch: refs/heads/develop
Commit: 2bd3b0625a182a9e4b300f096c45a2585445e556
Parents: 9d4d901
Author: Adi Narayana Raju <ad...@confluxtechnologies.com>
Authored: Wed May 4 13:00:41 2016 +0530
Committer: Adi Narayana Raju <ad...@confluxtechnologies.com>
Committed: Wed May 4 13:01:25 2016 +0530
----------------------------------------------------------------------
api-docs/apiLive.htm | 379 +++++-
.../commands/service/CommandWrapperBuilder.java | 25 +
.../domain/ConfigurationDomainService.java | 4 +
.../domain/ConfigurationDomainServiceJpa.java | 16 +
.../service/TenantDatabaseUpgradeService.java | 2 +-
...arWritePlatformServiceJpaRepositoryImpl.java | 4 +-
.../AccountTransfersReadPlatformService.java | 5 +
...AccountTransfersReadPlatformServiceImpl.java | 1120 ++++++++++--------
.../loanaccount/domain/LoanRepository.java | 6 +-
.../domain/SavingsAccountRepository.java | 3 +
.../api/SelfAccountTransferApiResource.java | 95 +-
.../api/SelfBeneficiariesTPTApiConstants.java | 53 +
.../api/SelfBeneficiariesTPTApiResource.java | 161 +++
.../account/data/SelfAccountTemplateData.java | 9 +
.../account/data/SelfAccountTransferData.java | 9 +-
.../data/SelfAccountTransferDataValidator.java | 49 +-
.../account/data/SelfBeneficiariesTPTData.java | 69 ++
.../data/SelfBeneficiariesTPTDataValidator.java | 165 +++
.../account/domain/SelfBeneficiariesTPT.java | 136 +++
.../domain/SelfBeneficiariesTPTRepository.java | 28 +
...neficiaryTransferLimitExceededException.java | 30 +
...TransactionAmountLimitExceededException.java | 31 +
.../InvalidAccountInformationException.java | 32 +
.../exception/InvalidBeneficiaryException.java | 29 +
.../AddSelfBeneficiariesTPTCommandHandler.java | 46 +
...eleteSelfBeneficiariesTPTCommandHandler.java | 46 +
...pdateSelfBeneficiariesTPTCommandHandler.java | 46 +
...SelfBeneficiariesTPTReadPlatformService.java | 36 +
...BeneficiariesTPTReadPlatformServiceImpl.java | 222 ++++
...elfBeneficiariesTPTWritePlatformService.java | 32 +
...eneficiariesTPTWritePlatformServiceImpl.java | 212 ++++
...tomer_self_service_third_party_transfers.sql | 24 +
32 files changed, 2620 insertions(+), 504 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/api-docs/apiLive.htm
----------------------------------------------------------------------
diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm
index c2fa328..3139b1a 100644
--- a/api-docs/apiLive.htm
+++ b/api-docs/apiLive.htm
@@ -3312,6 +3312,38 @@
<td></td>
<td></td>
</tr>
+ <tr>
+ <td><a href="#selfbentemplate">Beneficiary for Third Party Transfer</a></td>
+ <td>/self/beneficiaries/tpt/template</td>
+ <td></td>
+ <td><a href="#selfbentemplate">Beneficiary TPT Template</a></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>/self/beneficiaries/tpt</td>
+ <td><a href="#selfaddtpt">Add TPT Beneficiary</a></td>
+ <td><a href="#selfgettpt">Get TPT Beneficiary List</a></td>
+ <td><a href="#selfputtpt">Update TPT Beneficiary</a></td>
+ <td><a href="#selfdeletetpt">Delete TPT Beneficiary</a></td>
+ </tr>
+ <tr>
+ <td><a href="#selftpttransfertemplate">Third Party Account Transfers</a></td>
+ <td>self/accounttransfers/template?type="tpt"</td>
+ <td></td>
+ <td><a href="#selftpttransfertemplate">Third Party Account Transfer Template</a></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>self/accounttransfers?type="tpt"</td>
+ <td><a href="#selftpttransfer">Third Party Account Transfer</a></td>
+ <td></td>
+ <td></td>
+ <td></td>
+ </tr>
</table>
</div>
</div>
@@ -42193,7 +42225,35 @@ GET https://DomainName/api/v1/self/savingsaccounts/{accountId}/charges/{savingsA
</code>
<code class="method-response">
{
- "accountOptions": [
+ "fromAccountOptions": [
+ {
+ "accountId": 1,
+ "accountNo": "00000001",
+ "accountType": {
+ "id": 2,
+ "code": "accountType.savings",
+ "value": "Savings Account"
+ },
+ "clientId": 1,
+ "clientName": "ABC",
+ "officeId": 1,
+ "officeName": "HEAD OFFICE"
+ },
+ {
+ "accountId": 5,
+ "accountNo": "00000005",
+ "accountType": {
+ "id": 1,
+ "code": "accountType.loan",
+ "value": "Loan Account"
+ },
+ "clientId": 2,
+ "clientName": "XYZ",
+ "officeId": 3,
+ "officeName": "REGIONAL OFFICE"
+ }
+ ],
+ "toAccountOptions": [
{
"accountId": 1,
"accountNo": "00000001",
@@ -42221,6 +42281,7 @@ GET https://DomainName/api/v1/self/savingsaccounts/{accountId}/charges/{savingsA
"officeName": "REGIONAL OFFICE"
}
]
+
}
</code>
</div>
@@ -42262,6 +42323,322 @@ No Request Body:
</div>
</div>
+ <a id="selfbentemplate" name="selfbentemplate" class="old-syle-anchor"> </a>
+ <div class="method-section">
+ <div class="method-description">
+ <h2>Beneficiary Third Party Transfer Template</h2>
+ <p>Returns Account Type enumerations. Self User is expected to know office name and account number to be able to add beneficiary.</p>
+ <p>Example Requests:</p>
+ <div class=apiClick>/self/beneficiaries/tpt/template</div>
+ </div>
+ <div class="method-example">
+ <code class="method-declaration">GET https://DomainName/api/v1/self/beneficiaries/tpt/template
+ </code>
+ <code class="method-response">
+ {
+ "accountTypeOptions":
+ [
+ {
+ "id": 2,
+ "code": "accountType.savings",
+ "value": "Savings Account"
+ },
+ {
+ "id": 1,
+ "code": "accountType.loan",
+ "value": "Loan Account"
+ }
+ ]
+ }
+ </code>
+ </div>
+ </div>
+
+ <a id="selfaddtpt" name="selfaddtpt" class="old-syle-anchor"> </a>
+ <div class="method-section">
+ <div class="method-description">
+ <h2>Add TPT Beneficiary</h2>
+ <p>Api to add third party beneficiary linked to current user.</p>
+ <p>Parameter Definitions</p>
+ <p>name : Nick name for beneficiary, should be unique for an self service user</p>
+ <p>officeName : Office Name of beneficiary(not id)</p>
+ <p>accountNumber : Account Number of beneficiary(not id)</p>
+ <p>transferLimit : Each transfer initiated to this account will not exceed this amount</p>
+ <p>Example Requests:</p>
+ <div class=apiClick>/self/beneficiaries/tpt</div>
+ <table class=matrixHeading>
+ <tr class="matrixHeadingBG">
+ <td><div class="fineractHeading2">Mandatory Fields</div></td>
+ </tr>
+ <tr class=alt>
+ <td>name, officeName, accountNumber, accountType</td>
+ </tr>
+ </table>
+ <br/>
+ <table class=matrixHeading>
+ <tr class="matrixHeadingBG">
+ <td><div class="fineractHeading2">Optional Fields</div></td>
+ </tr>
+ <tr class=alt>
+ <td>transferLimit
+ </td>
+ </tr>
+ </table>
+ </div>
+
+ <div class="method-example">
+ <code class="method-declaration">POST https://DomainName/api/v1/self/beneficiaries/tpt
+ </code>
+ <code class="method-request">
+POST self/beneficiaries/tpt
+Content-Type: application/json
+Request Body:
+{
+ "locale": "en_GB",
+ "name": "beneficiary nick name",
+ "officeName": "HEAD OFFICE",
+ "accountNumber": "0000001",
+ "accountType": 1,
+ "transferLimit": 1000
+
+}
+ </code>
+ <code class="method-response">
+{
+ "resourceId": 5
+}
+ </code>
+ </div>
+ </div>
+
+ <a id="selfgettpt" name="selfgettpt" class="old-syle-anchor"> </a>
+ <div class="method-section">
+ <div class="method-description">
+ <h2>Get All TPT Beneficiary</h2>
+ <p>Api to get all third party beneficiary linked to current user.</p>
+ <p>Example Requests:</p>
+ <div class=apiClick>/self/beneficiaries/tpt</div>
+ </div>
+
+ <div class="method-example">
+ <code class="method-declaration">GET https://DomainName/api/v1/self/beneficiaries/tpt
+ </code>
+ <code class="method-request">
+GET self/beneficiaries/tpt
+Content-Type: application/json
+ </code>
+ <code class="method-response">
+{
+[
+ {
+ "id": 1,
+ "name": "Client2Savings",
+ "officeName": "Test Office",
+ "clientName": "FN2 LN2",
+ "accountType": {
+ "id": 2,
+ "code": "accountType.savings",
+ "value": "Savings Account"
+ },
+ "accountNumber": "000000002",
+ "transferLimit": 0
+ },
+ {
+ "id": 4,
+ "name": "Client2Loan",
+ "officeName": "Test Office",
+ "clientName": "FN2 LN2",
+ "accountType": {
+ "id": 1,
+ "code": "accountType.loan",
+ "value": "Loan Account"
+ },
+ "accountNumber": "000000002",
+ "transferLimit": 1000
+ }]
+}
+ </code>
+ </div>
+ </div>
+
+ <a id="selfputtpt" name="selfputtpt" class="old-syle-anchor"> </a>
+ <div class="method-section">
+ <div class="method-description">
+ <h2>Update TPT Beneficiary</h2>
+ <p>Api to update third party beneficiary linked to current user.</p>
+ <p>Example Requests:</p>
+ <div class=apiClick>/self/beneficiaries/tpt/{beneficiaryId}</div>
+ <br/>
+ <table class=matrixHeading>
+ <tr class="matrixHeadingBG">
+ <td><div class="fineractHeading2">Optional Fields</div></td>
+ </tr>
+ <tr class=alt>
+ <td>name, transferLimit
+ </td>
+ </tr>
+ </table>
+ </div>
+
+ <div class="method-example">
+ <code class="method-declaration">PUT https://DomainName/api/v1/self/beneficiaries/tpt/{beneficiaryId}
+ </code>
+ <code class="method-request">
+PUT self/beneficiaries/tpt/5
+Content-Type: application/json
+Request Body:
+{
+ "name": "beneficiary nick name",
+ "transferLimit": 1000
+
+}
+ </code>
+ <code class="method-response">
+{
+ "resourceId": 5,
+ "changes": {
+ "transferLimit": 1000,
+ "name": "Client22"
+ }
+}
+ </code>
+ </div>
+ </div>
+
+ <a id="selfdeletetpt" name="selfdeletetpt" class="old-syle-anchor"> </a>
+ <div class="method-section">
+ <div class="method-description">
+ <h2>Delete TPT Beneficiary</h2>
+ <p>Api to delete third party beneficiary linked to current user.</p>
+ <p>Example Requests:</p>
+ <div class=apiClick>/self/beneficiaries/tpt/{beneficiaryId}</div>
+ </div>
+
+ <div class="method-example">
+ <code class="method-declaration">DELETE https://DomainName/api/v1/self/beneficiaries/tpt/{beneficiaryId}
+ </code>
+ <code class="method-request">
+DELETE self/beneficiaries/tpt/5
+Content-Type: application/json
+ </code>
+ <code class="method-response">
+{
+ "resourceId": 5
+}
+ </code>
+ </div>
+ </div>
+
+ <a id="selftpttransfertemplate" name="selftpttransfertemplate" class="old-syle-anchor"> </a>
+ <div class="method-section">
+ <div class="method-description">
+ <h2>Third Party Account Transfer Template</h2>
+ <p>Returns list of loan/savings accounts that can be used for third party account transfer</p>
+ <p>Example Requests:</p>
+ <div class=apiClick>self/accounttransfers/template?type="tpt"</div>
+ </div>
+ <div class="method-example">
+ <code class="method-declaration">GET https://DomainName/api/v1/self/accounttransfers/template?type="tpt"
+ </code>
+ <code class="method-response">
+{
+ "fromAccountOptions": [
+ {
+ "accountId": 1,
+ "accountNo": "00000001",
+ "accountType": {
+ "id": 2,
+ "code": "accountType.savings",
+ "value": "Savings Account"
+ },
+ "clientId": 1,
+ "clientName": "ABC",
+ "officeId": 1,
+ "officeName": "HEAD OFFICE"
+ },
+ {
+ "accountId": 5,
+ "accountNo": "00000005",
+ "accountType": {
+ "id": 1,
+ "code": "accountType.loan",
+ "value": "Loan Account"
+ },
+ "clientId": 2,
+ "clientName": "XYZ",
+ "officeId": 3,
+ "officeName": "REGIONAL OFFICE"
+ }
+ ],
+ "toAccountOptions": [
+ {
+ "accountId": 2,
+ "accountNo": "00000002",
+ "accountType": {
+ "id": 2,
+ "code": "accountType.savings",
+ "value": "Savings Account"
+ },
+ "clientId": 2,
+ "clientName": "ABC",
+ "officeId": 1,
+ "officeName": "HEAD OFFICE"
+ },
+ {
+ "accountId": 6,
+ "accountNo": "00000006",
+ "accountType": {
+ "id": 1,
+ "code": "accountType.loan",
+ "value": "Loan Account"
+ },
+ "clientId": 3,
+ "clientName": "XYZ",
+ "officeId": 4,
+ "officeName": "REGIONAL OFFICE"
+ }
+ ]
+
+}
+ </code>
+ </div>
+ </div>
+
+ <a id="selftpttransfer" name="selftpttransfer" class="old-syle-anchor"> </a>
+ <div class="method-section">
+ <div class="method-description">
+ <h2>Third Party Account Transfer</h2>
+ <p>Ability to create new third party transfer of monetary funds from one account to another.</p>
+ </div>
+ <div class="method-example">
+ <code class="method-declaration">POST https://DomainName/api/v1/self/accounttransfers?type="tpt"</code>
+ <code class="method-request">POST self/accounttransfers?type="tpt"
+Content-Type: application/json
+No Request Body:
+{
+"fromOfficeId": 1,
+"fromClientId": 1,
+"fromAccountType": 2,
+"fromAccountId": 1,
+"toOfficeId": 1,
+"toClientId": 2,
+"toAccountType": 2,
+"toAccountId": 2,
+"dateFormat": "dd MMMM yyyy",
+"locale": "en",
+"transferDate": "01 August 2011",
+"transferAmount": "112.45",
+"transferDescription": "A description of the transfer"
+}
+ </code>
+ <code class="method-response">
+{
+ "savingsId": 1,
+ "resourceId": 1
+}
+ </code>
+ </div>
+ </div>
<!-- end of Customer Self Service APIs-->
</div>
<!-- main-content-wrapper -->
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
index bd13574..5751e0e 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java
@@ -2702,4 +2702,29 @@ public class CommandWrapperBuilder {
this.href = "/savingsaccounts/" + accountId + "?commad=updateTaxWithHoldTax";
return this;
}
+
+ public CommandWrapperBuilder addSelfServiceBeneficiaryTPT() {
+ this.actionName = "CREATE";
+ this.entityName = "SSBENEFICIARYTPT";
+ this.entityId = null;
+ this.href = "/self/beneficiaries/tpt";
+ return this;
+ }
+
+ public CommandWrapperBuilder updateSelfServiceBeneficiaryTPT(final Long beneficiaryId) {
+ this.actionName = "UPDATE";
+ this.entityName = "SSBENEFICIARYTPT";
+ this.entityId = beneficiaryId;
+ this.href = "/self/beneficiaries/tpt/"+beneficiaryId;
+ return this;
+ }
+
+ public CommandWrapperBuilder deleteSelfServiceBeneficiaryTPT(final Long beneficiaryId) {
+ this.actionName = "DELETE";
+ this.entityName = "SSBENEFICIARYTPT";
+ this.entityId = beneficiaryId;
+ this.href = "/self/beneficiaries/tpt/"+beneficiaryId;
+ return this;
+ }
+
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java
index 75aefb2..58494c2 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainService.java
@@ -79,4 +79,8 @@ public interface ConfigurationDomainService {
boolean isChangeEmiIfRepaymentDateSameAsDisbursementDateEnabled();
+ boolean isDailyTPTLimitEnabled();
+
+ Long getDailyTPTLimit();
+
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java
index 356d098..67ebdc5 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/configuration/domain/ConfigurationDomainServiceJpa.java
@@ -19,6 +19,7 @@
package org.apache.fineract.infrastructure.configuration.domain;
import java.util.Date;
+
import org.apache.commons.lang.StringUtils;
import org.apache.fineract.infrastructure.cache.domain.CacheType;
import org.apache.fineract.infrastructure.cache.domain.PlatformCache;
@@ -209,6 +210,7 @@ public class ConfigurationDomainServiceJpa implements ConfigurationDomainService
return defaultValue;
}
+ @Override
public boolean isBackdatePenaltiesEnabled() {
final String propertyName = "backdate-penalties-enabled";
final GlobalConfigurationProperty property = this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
@@ -263,5 +265,19 @@ public class ConfigurationDomainServiceJpa implements ConfigurationDomainService
return property.isEnabled();
}
+ @Override
+ public boolean isDailyTPTLimitEnabled() {
+ final String propertyName = "daily-tpt-limit";
+ final GlobalConfigurationProperty property = this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+ return property.isEnabled();
+ }
+
+ @Override
+ public Long getDailyTPTLimit() {
+ final String propertyName = "daily-tpt-limit";
+ final GlobalConfigurationProperty property = this.globalConfigurationRepository.findOneByNameWithNotFoundDetection(propertyName);
+ return property.getValue();
+ }
+
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/TenantDatabaseUpgradeService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/TenantDatabaseUpgradeService.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/TenantDatabaseUpgradeService.java
index 8bf9199..740dcb5 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/TenantDatabaseUpgradeService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/service/TenantDatabaseUpgradeService.java
@@ -74,7 +74,7 @@ public class TenantDatabaseUpgradeService {
flyway.migrate();
} catch (FlywayException e) {
String betterMessage = e.getMessage() + "; for Tenant DB URL: " + connectionProtocol + ", username: "
- + connection.getSchemaPassword();
+ + connection.getSchemaUsername();
throw new FlywayException(betterMessage, e.getCause());
}
}
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/SchedularWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/SchedularWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/SchedularWritePlatformServiceJpaRepositoryImpl.java
index f4ac6ac..7e5d5de 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/SchedularWritePlatformServiceJpaRepositoryImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/service/SchedularWritePlatformServiceJpaRepositoryImpl.java
@@ -136,11 +136,11 @@ public class SchedularWritePlatformServiceJpaRepositoryImpl implements Schedular
boolean isStopExecution = false;
final ScheduledJobDetail scheduledJobDetail = this.scheduledJobDetailsRepository.findByJobKeyWithLock(jobKey);
if (scheduledJobDetail.isCurrentlyRunning()
- || (triggerType == SchedulerServiceConstants.TRIGGER_TYPE_CRON && (scheduledJobDetail.getNextRunTime().after(new Date())))) {
+ || (triggerType.equals(SchedulerServiceConstants.TRIGGER_TYPE_CRON) && (scheduledJobDetail.getNextRunTime().after(new Date())))) {
isStopExecution = true;
}
final SchedulerDetail schedulerDetail = retriveSchedulerDetail();
- if (triggerType == SchedulerServiceConstants.TRIGGER_TYPE_CRON && schedulerDetail.isSuspended()) {
+ if (triggerType.equals(SchedulerServiceConstants.TRIGGER_TYPE_CRON) && schedulerDetail.isSuspended()) {
scheduledJobDetail.updateTriggerMisfired(true);
isStopExecution = true;
} else if (!isStopExecution) {
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformService.java
index c053b01..0434261 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformService.java
@@ -18,12 +18,14 @@
*/
package org.apache.fineract.portfolio.account.service;
+import java.math.BigDecimal;
import java.util.Collection;
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.portfolio.account.PortfolioAccountType;
import org.apache.fineract.portfolio.account.data.AccountTransferData;
+import org.joda.time.LocalDate;
public interface AccountTransfersReadPlatformService {
@@ -42,4 +44,7 @@ public interface AccountTransfersReadPlatformService {
AccountTransferData retrieveRefundByTransferTemplate(Long fromOfficeId, Long fromClientId, Long fromAccountId, Integer fromAccountType,
Long toOfficeId, Long toClientId, Long toAccountId, Integer toAccountType);
+
+ BigDecimal getTotalTransactionAmount(Long accountId, Integer accountType,
+ LocalDate transactionDate);
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformServiceImpl.java
index 9dbe4c9..08af091 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTransfersReadPlatformServiceImpl.java
@@ -45,6 +45,8 @@ import org.apache.fineract.portfolio.account.exception.AccountTransferNotFoundEx
import org.apache.fineract.portfolio.client.data.ClientData;
import org.apache.fineract.portfolio.client.service.ClientReadPlatformService;
import org.joda.time.LocalDate;
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.DateTimeFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
@@ -53,485 +55,643 @@ import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
@Service
-public class AccountTransfersReadPlatformServiceImpl implements AccountTransfersReadPlatformService {
-
- private final JdbcTemplate jdbcTemplate;
- private final ClientReadPlatformService clientReadPlatformService;
- private final OfficeReadPlatformService officeReadPlatformService;
- private final PortfolioAccountReadPlatformService portfolioAccountReadPlatformService;
-
- // mapper
- private final AccountTransfersMapper accountTransfersMapper;
-
- // pagination
- private final PaginationHelper<AccountTransferData> paginationHelper = new PaginationHelper<>();
-
- @Autowired
- public AccountTransfersReadPlatformServiceImpl(final RoutingDataSource dataSource,
- final ClientReadPlatformService clientReadPlatformService, final OfficeReadPlatformService officeReadPlatformService,
- final PortfolioAccountReadPlatformService portfolioAccountReadPlatformService) {
- this.jdbcTemplate = new JdbcTemplate(dataSource);
- this.clientReadPlatformService = clientReadPlatformService;
- this.officeReadPlatformService = officeReadPlatformService;
- this.portfolioAccountReadPlatformService = portfolioAccountReadPlatformService;
-
- this.accountTransfersMapper = new AccountTransfersMapper();
- }
-
- @Override
- public AccountTransferData retrieveTemplate(final Long fromOfficeId, final Long fromClientId, final Long fromAccountId,
- final Integer fromAccountType, final Long toOfficeId, final Long toClientId, final Long toAccountId, final Integer toAccountType) {
-
- final EnumOptionData loanAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.LOAN);
- final EnumOptionData savingsAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.SAVINGS);
-
- final Integer mostRelevantFromAccountType = fromAccountType;
- final Collection<EnumOptionData> fromAccountTypeOptions = Arrays.asList(savingsAccountType, loanAccountType);
- final Collection<EnumOptionData> toAccountTypeOptions;
- if (mostRelevantFromAccountType != null && mostRelevantFromAccountType == 1) {
- // overpaid loan amt transfer to savings account
- toAccountTypeOptions = Arrays.asList(savingsAccountType);
- } else {
- toAccountTypeOptions = Arrays.asList(loanAccountType, savingsAccountType);
- }
- final Integer mostRelevantToAccountType = toAccountType;
-
- final EnumOptionData fromAccountTypeData = AccountTransferEnumerations.accountType(mostRelevantFromAccountType);
- final EnumOptionData toAccountTypeData = AccountTransferEnumerations.accountType(mostRelevantToAccountType);
-
- // from settings
- OfficeData fromOffice = null;
- ClientData fromClient = null;
- PortfolioAccountData fromAccount = null;
-
- OfficeData toOffice = null;
- ClientData toClient = null;
- PortfolioAccountData toAccount = null;
-
- // template
- Collection<PortfolioAccountData> fromAccountOptions = null;
- Collection<PortfolioAccountData> toAccountOptions = null;
-
- Long mostRelevantFromOfficeId = fromOfficeId;
- Long mostRelevantFromClientId = fromClientId;
-
- Long mostRelevantToOfficeId = toOfficeId;
- Long mostRelevantToClientId = toClientId;
-
- if (fromAccountId != null) {
- Integer accountType;
- if (mostRelevantFromAccountType == 1) {
- accountType = PortfolioAccountType.LOAN.getValue();
- } else {
- accountType = PortfolioAccountType.SAVINGS.getValue();
- }
- fromAccount = this.portfolioAccountReadPlatformService.retrieveOne(fromAccountId, accountType);
-
- // override provided fromClient with client of account
- mostRelevantFromClientId = fromAccount.clientId();
- }
-
- if (mostRelevantFromClientId != null) {
- fromClient = this.clientReadPlatformService.retrieveOne(mostRelevantFromClientId);
- mostRelevantFromOfficeId = fromClient.officeId();
- long[] loanStatus = null;
- if (mostRelevantFromAccountType == 1) {
- loanStatus = new long[] { 300, 700 };
- }
- PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(mostRelevantFromAccountType, mostRelevantFromClientId,
- loanStatus);
- fromAccountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(portfolioAccountDTO);
- }
-
- Collection<OfficeData> fromOfficeOptions = null;
- Collection<ClientData> fromClientOptions = null;
- if (mostRelevantFromOfficeId != null) {
- fromOffice = this.officeReadPlatformService.retrieveOffice(mostRelevantFromOfficeId);
- fromOfficeOptions = this.officeReadPlatformService.retrieveAllOfficesForDropdown();
- fromClientOptions = this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantFromOfficeId);
- }
-
- // defaults
- final LocalDate transferDate = DateUtils.getLocalDateOfTenant();
- Collection<OfficeData> toOfficeOptions = fromOfficeOptions;
- Collection<ClientData> toClientOptions = null;
-
- if (toAccountId != null && fromAccount != null) {
- toAccount = this.portfolioAccountReadPlatformService.retrieveOne(toAccountId, mostRelevantToAccountType,
- fromAccount.currencyCode());
- mostRelevantToClientId = toAccount.clientId();
- }
-
- if (mostRelevantToClientId != null) {
- toClient = this.clientReadPlatformService.retrieveOne(mostRelevantToClientId);
- mostRelevantToOfficeId = toClient.officeId();
-
- toClientOptions = this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
-
- toAccountOptions = retrieveToAccounts(fromAccount, mostRelevantToAccountType, mostRelevantToClientId);
- }
-
- if (mostRelevantToOfficeId != null) {
- toOffice = this.officeReadPlatformService.retrieveOffice(mostRelevantToOfficeId);
- toOfficeOptions = this.officeReadPlatformService.retrieveAllOfficesForDropdown();
-
- toClientOptions = this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
- if (toClientOptions != null && toClientOptions.size() == 1) {
- toClient = new ArrayList<>(toClientOptions).get(0);
-
- toAccountOptions = retrieveToAccounts(fromAccount, mostRelevantToAccountType, mostRelevantToClientId);
- }
- }
-
- return AccountTransferData.template(fromOffice, fromClient, fromAccountTypeData, fromAccount, transferDate, toOffice, toClient,
- toAccountTypeData, toAccount, fromOfficeOptions, fromClientOptions, fromAccountTypeOptions, fromAccountOptions,
- toOfficeOptions, toClientOptions, toAccountTypeOptions, toAccountOptions);
- }
-
- private Collection<PortfolioAccountData> retrieveToAccounts(final PortfolioAccountData excludeThisAccountFromOptions,
- final Integer toAccountType, final Long toClientId) {
-
- final String currencyCode = excludeThisAccountFromOptions != null ? excludeThisAccountFromOptions.currencyCode() : null;
-
- PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(toAccountType, toClientId, currencyCode, null, null);
- Collection<PortfolioAccountData> accountOptions = this.portfolioAccountReadPlatformService
- .retrieveAllForLookup(portfolioAccountDTO);
- if (!CollectionUtils.isEmpty(accountOptions)) {
- accountOptions.remove(excludeThisAccountFromOptions);
- } else {
- accountOptions = null;
- }
-
- return accountOptions;
- }
-
- @Override
- public Page<AccountTransferData> retrieveAll(final SearchParameters searchParameters, final Long accountDetailId) {
-
- final StringBuilder sqlBuilder = new StringBuilder(200);
- sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
- sqlBuilder.append(this.accountTransfersMapper.schema());
- Object[] finalObjectArray = {};
- if (accountDetailId != null) {
- sqlBuilder.append(" where att.account_transfer_details_id=?");
- finalObjectArray = new Object[] { accountDetailId };
- }
-
- if (searchParameters.isOrderByRequested()) {
- sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
-
- if (searchParameters.isSortOrderProvided()) {
- sqlBuilder.append(' ').append(searchParameters.getSortOrder());
- }
- }
-
- if (searchParameters.isLimited()) {
- sqlBuilder.append(" limit ").append(searchParameters.getLimit());
- if (searchParameters.isOffset()) {
- sqlBuilder.append(" offset ").append(searchParameters.getOffset());
- }
- }
-
- final String sqlCountRows = "SELECT FOUND_ROWS()";
- return this.paginationHelper.fetchPage(this.jdbcTemplate, sqlCountRows, sqlBuilder.toString(), finalObjectArray,
- this.accountTransfersMapper);
- }
-
- @Override
- public AccountTransferData retrieveOne(final Long transferId) {
-
- try {
- final String sql = "select " + this.accountTransfersMapper.schema() + " where att.id = ?";
-
- return this.jdbcTemplate.queryForObject(sql, this.accountTransfersMapper, new Object[] { transferId });
- } catch (final EmptyResultDataAccessException e) {
- throw new AccountTransferNotFoundException(transferId);
- }
- }
-
- @Override
- public Collection<Long> fetchPostInterestTransactionIds(final Long accountId) {
- final String sql = "select att.from_savings_transaction_id from m_account_transfer_transaction att inner join m_account_transfer_details atd on atd.id = att.account_transfer_details_id where atd.from_savings_account_id=? and att.is_reversed =0 and atd.transfer_type = ?";
-
- final List<Long> transactionId = this.jdbcTemplate.queryForList(sql, Long.class, accountId,
- AccountTransferType.INTEREST_TRANSFER.getValue());
-
- return transactionId;
- }
-
- private static final class AccountTransfersMapper implements RowMapper<AccountTransferData> {
-
- private final String schemaSql;
-
- public AccountTransfersMapper() {
- final StringBuilder sqlBuilder = new StringBuilder(400);
- sqlBuilder.append("att.id as id, att.is_reversed as isReversed,");
- sqlBuilder.append("att.transaction_date as transferDate, att.amount as transferAmount,");
- sqlBuilder.append("att.description as transferDescription,");
- sqlBuilder.append("att.currency_code as currencyCode, att.currency_digits as currencyDigits,");
- sqlBuilder.append("att.currency_multiplesof as inMultiplesOf, ");
- sqlBuilder.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
- sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol, ");
- sqlBuilder.append("fromoff.id as fromOfficeId, fromoff.name as fromOfficeName,");
- sqlBuilder.append("tooff.id as toOfficeId, tooff.name as toOfficeName,");
- sqlBuilder.append("fromclient.id as fromClientId, fromclient.display_name as fromClientName,");
- sqlBuilder.append("toclient.id as toClientId, toclient.display_name as toClientName,");
- sqlBuilder.append("fromsavacc.id as fromSavingsAccountId, fromsavacc.account_no as fromSavingsAccountNo,");
- sqlBuilder.append("fromloanacc.id as fromLoanAccountId, fromloanacc.account_no as fromLoanAccountNo,");
- sqlBuilder.append("tosavacc.id as toSavingsAccountId, tosavacc.account_no as toSavingsAccountNo,");
- sqlBuilder.append("toloanacc.id as toLoanAccountId, toloanacc.account_no as toLoanAccountNo,");
- sqlBuilder.append("fromsavtran.id as fromSavingsAccountTransactionId,");
- sqlBuilder.append("fromsavtran.transaction_type_enum as fromSavingsAccountTransactionType,");
- sqlBuilder.append("tosavtran.id as toSavingsAccountTransactionId,");
- sqlBuilder.append("tosavtran.transaction_type_enum as toSavingsAccountTransactionType");
- sqlBuilder.append(" FROM m_account_transfer_transaction att ");
- sqlBuilder.append("left join m_account_transfer_details atd on atd.id = att.account_transfer_details_id ");
- sqlBuilder.append("join m_currency curr on curr.code = att.currency_code ");
- sqlBuilder.append("join m_office fromoff on fromoff.id = atd.from_office_id ");
- sqlBuilder.append("join m_office tooff on tooff.id = atd.to_office_id ");
- sqlBuilder.append("join m_client fromclient on fromclient.id = atd.from_client_id ");
- sqlBuilder.append("join m_client toclient on toclient.id = atd.to_client_id ");
- sqlBuilder.append("left join m_savings_account fromsavacc on fromsavacc.id = atd.from_savings_account_id ");
- sqlBuilder.append("left join m_loan fromloanacc on fromloanacc.id = atd.from_loan_account_id ");
- sqlBuilder.append("left join m_savings_account tosavacc on tosavacc.id = atd.to_savings_account_id ");
- sqlBuilder.append("left join m_loan toloanacc on toloanacc.id = atd.to_loan_account_id ");
- sqlBuilder.append("left join m_savings_account_transaction fromsavtran on fromsavtran.id = att.from_savings_transaction_id ");
- sqlBuilder.append("left join m_savings_account_transaction tosavtran on tosavtran.id = att.to_savings_transaction_id ");
- sqlBuilder.append("left join m_loan_transaction fromloantran on fromloantran.id = att.from_savings_transaction_id ");
- sqlBuilder.append("left join m_loan_transaction toloantran on toloantran.id = att.to_savings_transaction_id ");
-
- this.schemaSql = sqlBuilder.toString();
- }
-
- public String schema() {
- return this.schemaSql;
- }
-
- @Override
- public AccountTransferData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
-
- final Long id = rs.getLong("id");
- final boolean reversed = rs.getBoolean("isReversed");
-
- final LocalDate transferDate = JdbcSupport.getLocalDate(rs, "transferDate");
- final BigDecimal transferAmount = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "transferAmount");
- final String transferDescription = rs.getString("transferDescription");
-
- final String currencyCode = rs.getString("currencyCode");
- final String currencyName = rs.getString("currencyName");
- final String currencyNameCode = rs.getString("currencyNameCode");
- final String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
- final Integer currencyDigits = JdbcSupport.getInteger(rs, "currencyDigits");
- final Integer inMultiplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf");
- final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, inMultiplesOf,
- currencyDisplaySymbol, currencyNameCode);
-
- final Long fromOfficeId = JdbcSupport.getLong(rs, "fromOfficeId");
- final String fromOfficeName = rs.getString("fromOfficeName");
- final OfficeData fromOffice = OfficeData.dropdown(fromOfficeId, fromOfficeName, null);
-
- final Long toOfficeId = JdbcSupport.getLong(rs, "toOfficeId");
- final String toOfficeName = rs.getString("toOfficeName");
- final OfficeData toOffice = OfficeData.dropdown(toOfficeId, toOfficeName, null);
-
- final Long fromClientId = JdbcSupport.getLong(rs, "fromClientId");
- final String fromClientName = rs.getString("fromClientName");
- final ClientData fromClient = ClientData.lookup(fromClientId, fromClientName, fromOfficeId, fromOfficeName);
-
- final Long toClientId = JdbcSupport.getLong(rs, "toClientId");
- final String toClientName = rs.getString("toClientName");
- final ClientData toClient = ClientData.lookup(toClientId, toClientName, toOfficeId, toOfficeName);
-
- final Long fromSavingsAccountId = JdbcSupport.getLong(rs, "fromSavingsAccountId");
- final String fromSavingsAccountNo = rs.getString("fromSavingsAccountNo");
- final Long fromLoanAccountId = JdbcSupport.getLong(rs, "fromLoanAccountId");
- final String fromLoanAccountNo = rs.getString("fromLoanAccountNo");
- PortfolioAccountData fromAccount = null;
- EnumOptionData fromAccountType = null;
- if (fromSavingsAccountId != null) {
- fromAccount = PortfolioAccountData.lookup(fromSavingsAccountId, fromSavingsAccountNo);
- fromAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.SAVINGS);
- } else if (fromLoanAccountId != null) {
- fromAccount = PortfolioAccountData.lookup(fromLoanAccountId, fromLoanAccountNo);
- fromAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.LOAN);
- }
-
- PortfolioAccountData toAccount = null;
- EnumOptionData toAccountType = null;
- final Long toSavingsAccountId = JdbcSupport.getLong(rs, "toSavingsAccountId");
- final String toSavingsAccountNo = rs.getString("toSavingsAccountNo");
- final Long toLoanAccountId = JdbcSupport.getLong(rs, "toLoanAccountId");
- final String toLoanAccountNo = rs.getString("toLoanAccountNo");
-
- if (toSavingsAccountId != null) {
- toAccount = PortfolioAccountData.lookup(toSavingsAccountId, toSavingsAccountNo);
- toAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.SAVINGS);
- } else if (toLoanAccountId != null) {
- toAccount = PortfolioAccountData.lookup(toLoanAccountId, toLoanAccountNo);
- toAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.LOAN);
- }
-
- return AccountTransferData.instance(id, reversed, transferDate, currency, transferAmount, transferDescription, fromOffice,
- toOffice, fromClient, toClient, fromAccountType, fromAccount, toAccountType, toAccount);
- }
- }
-
- @Override
- public boolean isAccountTransfer(final Long transactionId, final PortfolioAccountType accountType) {
- final StringBuilder sql = new StringBuilder("select count(*) from m_account_transfer_transaction at where ");
- if (accountType.isLoanAccount()) {
- sql.append("at.from_loan_transaction_id=").append(transactionId).append(" or at.to_loan_transaction_id=").append(transactionId);
- } else {
- sql.append("at.from_savings_transaction_id=").append(transactionId).append(" or at.to_savings_transaction_id=")
- .append(transactionId);
- }
-
- @SuppressWarnings("deprecation")
- final int count = this.jdbcTemplate.queryForInt(sql.toString());
- return count > 0;
- }
-
- @Override
- public Page<AccountTransferData> retrieveByStandingInstruction(final Long id, final SearchParameters searchParameters) {
-
- final StringBuilder sqlBuilder = new StringBuilder(200);
- sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
- sqlBuilder
- .append(this.accountTransfersMapper.schema())
- .append(" join m_account_transfer_standing_instructions atsi on atsi.account_transfer_details_id = att.account_transfer_details_id ");
- sqlBuilder.append(" where atsi.id = ?");
-
- if (searchParameters != null) {
- if (searchParameters.isOrderByRequested()) {
- sqlBuilder.append(" order by ").append(searchParameters.getOrderBy());
-
- if (searchParameters.isSortOrderProvided()) {
- sqlBuilder.append(' ').append(searchParameters.getSortOrder());
- }
- }
-
- if (searchParameters.isLimited()) {
- sqlBuilder.append(" limit ").append(searchParameters.getLimit());
- if (searchParameters.isOffset()) {
- sqlBuilder.append(" offset ").append(searchParameters.getOffset());
- }
- }
- }
-
- final Object[] finalObjectArray = { id };
- final String sqlCountRows = "SELECT FOUND_ROWS()";
- return this.paginationHelper.fetchPage(this.jdbcTemplate, sqlCountRows, sqlBuilder.toString(), finalObjectArray,
- this.accountTransfersMapper);
- }
-
- @Override
- public AccountTransferData retrieveRefundByTransferTemplate(final Long fromOfficeId, final Long fromClientId, final Long fromAccountId,
- final Integer fromAccountType, final Long toOfficeId, final Long toClientId, final Long toAccountId, final Integer toAccountType) {
- // TODO Auto-generated method stub
- final EnumOptionData loanAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.LOAN);
- final EnumOptionData savingsAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.SAVINGS);
-
- final Integer mostRelevantFromAccountType = fromAccountType;
- final Collection<EnumOptionData> fromAccountTypeOptions = Arrays.asList(savingsAccountType, loanAccountType);
- final Collection<EnumOptionData> toAccountTypeOptions;
- if (mostRelevantFromAccountType == 1) {
- // overpaid loan amt transfer to savings account
- toAccountTypeOptions = Arrays.asList(savingsAccountType);
- } else {
- toAccountTypeOptions = Arrays.asList(loanAccountType, savingsAccountType);
- }
- final Integer mostRelevantToAccountType = toAccountType;
-
- final EnumOptionData fromAccountTypeData = AccountTransferEnumerations.accountType(mostRelevantFromAccountType);
- final EnumOptionData toAccountTypeData = AccountTransferEnumerations.accountType(mostRelevantToAccountType);
-
- // from settings
- OfficeData fromOffice = null;
- ClientData fromClient = null;
- PortfolioAccountData fromAccount = null;
-
- OfficeData toOffice = null;
- ClientData toClient = null;
- PortfolioAccountData toAccount = null;
-
- // template
- Collection<PortfolioAccountData> fromAccountOptions = null;
- Collection<PortfolioAccountData> toAccountOptions = null;
-
- Long mostRelevantFromOfficeId = fromOfficeId;
- Long mostRelevantFromClientId = fromClientId;
-
- Long mostRelevantToOfficeId = toOfficeId;
- Long mostRelevantToClientId = toClientId;
-
- if (fromAccountId != null) {
- Integer accountType;
- if (mostRelevantFromAccountType == 1) {
- accountType = PortfolioAccountType.LOAN.getValue();
- } else {
- accountType = PortfolioAccountType.SAVINGS.getValue();
- }
- fromAccount = this.portfolioAccountReadPlatformService.retrieveOneByPaidInAdvance(fromAccountId, accountType);
-
- // override provided fromClient with client of account
- mostRelevantFromClientId = fromAccount.clientId();
- }
-
- if (mostRelevantFromClientId != null) {
- fromClient = this.clientReadPlatformService.retrieveOne(mostRelevantFromClientId);
- mostRelevantFromOfficeId = fromClient.officeId();
- long[] loanStatus = null;
- if (mostRelevantFromAccountType == 1) {
- loanStatus = new long[] { 300, 700 };
- }
- PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(mostRelevantFromAccountType, mostRelevantFromClientId,
- loanStatus);
- fromAccountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(portfolioAccountDTO);
- }
-
- Collection<OfficeData> fromOfficeOptions = null;
- Collection<ClientData> fromClientOptions = null;
- if (mostRelevantFromOfficeId != null) {
- fromOffice = this.officeReadPlatformService.retrieveOffice(mostRelevantFromOfficeId);
- fromOfficeOptions = this.officeReadPlatformService.retrieveAllOfficesForDropdown();
- fromClientOptions = this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantFromOfficeId);
- }
-
- // defaults
- final LocalDate transferDate = DateUtils.getLocalDateOfTenant();
- Collection<OfficeData> toOfficeOptions = fromOfficeOptions;
- Collection<ClientData> toClientOptions = null;
-
- if (toAccountId != null && fromAccount != null) {
- toAccount = this.portfolioAccountReadPlatformService.retrieveOne(toAccountId, mostRelevantToAccountType,
- fromAccount.currencyCode());
- mostRelevantToClientId = toAccount.clientId();
- }
-
- if (mostRelevantToClientId != null) {
- toClient = this.clientReadPlatformService.retrieveOne(mostRelevantToClientId);
- mostRelevantToOfficeId = toClient.officeId();
-
- toClientOptions = this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
-
- toAccountOptions = retrieveToAccounts(fromAccount, mostRelevantToAccountType, mostRelevantToClientId);
- }
-
- if (mostRelevantToOfficeId != null) {
- toOffice = this.officeReadPlatformService.retrieveOffice(mostRelevantToOfficeId);
- toOfficeOptions = this.officeReadPlatformService.retrieveAllOfficesForDropdown();
-
- toClientOptions = this.clientReadPlatformService.retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
- if (toClientOptions != null && toClientOptions.size() == 1) {
- toClient = new ArrayList<>(toClientOptions).get(0);
-
- toAccountOptions = retrieveToAccounts(fromAccount, mostRelevantToAccountType, mostRelevantToClientId);
- }
- }
-
- return AccountTransferData.template(fromOffice, fromClient, fromAccountTypeData, fromAccount, transferDate, toOffice, toClient,
- toAccountTypeData, toAccount, fromOfficeOptions, fromClientOptions, fromAccountTypeOptions, fromAccountOptions,
- toOfficeOptions, toClientOptions, toAccountTypeOptions, toAccountOptions);
- }
+public class AccountTransfersReadPlatformServiceImpl implements
+ AccountTransfersReadPlatformService {
+
+ private final JdbcTemplate jdbcTemplate;
+ private final ClientReadPlatformService clientReadPlatformService;
+ private final OfficeReadPlatformService officeReadPlatformService;
+ private final PortfolioAccountReadPlatformService portfolioAccountReadPlatformService;
+
+ // mapper
+ private final AccountTransfersMapper accountTransfersMapper;
+
+ // pagination
+ private final PaginationHelper<AccountTransferData> paginationHelper = new PaginationHelper<>();
+ private final DateTimeFormatter formatter = DateTimeFormat
+ .forPattern("yyyy-MM-dd");
+
+ @Autowired
+ public AccountTransfersReadPlatformServiceImpl(
+ final RoutingDataSource dataSource,
+ final ClientReadPlatformService clientReadPlatformService,
+ final OfficeReadPlatformService officeReadPlatformService,
+ final PortfolioAccountReadPlatformService portfolioAccountReadPlatformService) {
+ this.jdbcTemplate = new JdbcTemplate(dataSource);
+ this.clientReadPlatformService = clientReadPlatformService;
+ this.officeReadPlatformService = officeReadPlatformService;
+ this.portfolioAccountReadPlatformService = portfolioAccountReadPlatformService;
+
+ this.accountTransfersMapper = new AccountTransfersMapper();
+ }
+
+ @Override
+ public AccountTransferData retrieveTemplate(final Long fromOfficeId,
+ final Long fromClientId, final Long fromAccountId,
+ final Integer fromAccountType, final Long toOfficeId,
+ final Long toClientId, final Long toAccountId,
+ final Integer toAccountType) {
+
+ final EnumOptionData loanAccountType = AccountTransferEnumerations
+ .accountType(PortfolioAccountType.LOAN);
+ final EnumOptionData savingsAccountType = AccountTransferEnumerations
+ .accountType(PortfolioAccountType.SAVINGS);
+
+ final Integer mostRelevantFromAccountType = fromAccountType;
+ final Collection<EnumOptionData> fromAccountTypeOptions = Arrays
+ .asList(savingsAccountType, loanAccountType);
+ final Collection<EnumOptionData> toAccountTypeOptions;
+ if (mostRelevantFromAccountType != null
+ && mostRelevantFromAccountType == 1) {
+ // overpaid loan amt transfer to savings account
+ toAccountTypeOptions = Arrays.asList(savingsAccountType);
+ } else {
+ toAccountTypeOptions = Arrays.asList(loanAccountType,
+ savingsAccountType);
+ }
+ final Integer mostRelevantToAccountType = toAccountType;
+
+ final EnumOptionData fromAccountTypeData = AccountTransferEnumerations
+ .accountType(mostRelevantFromAccountType);
+ final EnumOptionData toAccountTypeData = AccountTransferEnumerations
+ .accountType(mostRelevantToAccountType);
+
+ // from settings
+ OfficeData fromOffice = null;
+ ClientData fromClient = null;
+ PortfolioAccountData fromAccount = null;
+
+ OfficeData toOffice = null;
+ ClientData toClient = null;
+ PortfolioAccountData toAccount = null;
+
+ // template
+ Collection<PortfolioAccountData> fromAccountOptions = null;
+ Collection<PortfolioAccountData> toAccountOptions = null;
+
+ Long mostRelevantFromOfficeId = fromOfficeId;
+ Long mostRelevantFromClientId = fromClientId;
+
+ Long mostRelevantToOfficeId = toOfficeId;
+ Long mostRelevantToClientId = toClientId;
+
+ if (fromAccountId != null) {
+ Integer accountType;
+ if (mostRelevantFromAccountType == 1) {
+ accountType = PortfolioAccountType.LOAN.getValue();
+ } else {
+ accountType = PortfolioAccountType.SAVINGS.getValue();
+ }
+ fromAccount = this.portfolioAccountReadPlatformService.retrieveOne(
+ fromAccountId, accountType);
+
+ // override provided fromClient with client of account
+ mostRelevantFromClientId = fromAccount.clientId();
+ }
+
+ if (mostRelevantFromClientId != null) {
+ fromClient = this.clientReadPlatformService
+ .retrieveOne(mostRelevantFromClientId);
+ mostRelevantFromOfficeId = fromClient.officeId();
+ long[] loanStatus = null;
+ if (mostRelevantFromAccountType == 1) {
+ loanStatus = new long[] { 300, 700 };
+ }
+ PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(
+ mostRelevantFromAccountType, mostRelevantFromClientId,
+ loanStatus);
+ fromAccountOptions = this.portfolioAccountReadPlatformService
+ .retrieveAllForLookup(portfolioAccountDTO);
+ }
+
+ Collection<OfficeData> fromOfficeOptions = null;
+ Collection<ClientData> fromClientOptions = null;
+ if (mostRelevantFromOfficeId != null) {
+ fromOffice = this.officeReadPlatformService
+ .retrieveOffice(mostRelevantFromOfficeId);
+ fromOfficeOptions = this.officeReadPlatformService
+ .retrieveAllOfficesForDropdown();
+ fromClientOptions = this.clientReadPlatformService
+ .retrieveAllForLookupByOfficeId(mostRelevantFromOfficeId);
+ }
+
+ // defaults
+ final LocalDate transferDate = DateUtils.getLocalDateOfTenant();
+ Collection<OfficeData> toOfficeOptions = fromOfficeOptions;
+ Collection<ClientData> toClientOptions = null;
+
+ if (toAccountId != null && fromAccount != null) {
+ toAccount = this.portfolioAccountReadPlatformService.retrieveOne(
+ toAccountId, mostRelevantToAccountType,
+ fromAccount.currencyCode());
+ mostRelevantToClientId = toAccount.clientId();
+ }
+
+ if (mostRelevantToClientId != null) {
+ toClient = this.clientReadPlatformService
+ .retrieveOne(mostRelevantToClientId);
+ mostRelevantToOfficeId = toClient.officeId();
+
+ toClientOptions = this.clientReadPlatformService
+ .retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
+
+ toAccountOptions = retrieveToAccounts(fromAccount,
+ mostRelevantToAccountType, mostRelevantToClientId);
+ }
+
+ if (mostRelevantToOfficeId != null) {
+ toOffice = this.officeReadPlatformService
+ .retrieveOffice(mostRelevantToOfficeId);
+ toOfficeOptions = this.officeReadPlatformService
+ .retrieveAllOfficesForDropdown();
+
+ toClientOptions = this.clientReadPlatformService
+ .retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
+ if (toClientOptions != null && toClientOptions.size() == 1) {
+ toClient = new ArrayList<>(toClientOptions).get(0);
+
+ toAccountOptions = retrieveToAccounts(fromAccount,
+ mostRelevantToAccountType, mostRelevantToClientId);
+ }
+ }
+
+ return AccountTransferData.template(fromOffice, fromClient,
+ fromAccountTypeData, fromAccount, transferDate, toOffice,
+ toClient, toAccountTypeData, toAccount, fromOfficeOptions,
+ fromClientOptions, fromAccountTypeOptions, fromAccountOptions,
+ toOfficeOptions, toClientOptions, toAccountTypeOptions,
+ toAccountOptions);
+ }
+
+ private Collection<PortfolioAccountData> retrieveToAccounts(
+ final PortfolioAccountData excludeThisAccountFromOptions,
+ final Integer toAccountType, final Long toClientId) {
+
+ final String currencyCode = excludeThisAccountFromOptions != null ? excludeThisAccountFromOptions
+ .currencyCode() : null;
+
+ PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(
+ toAccountType, toClientId, currencyCode, null, null);
+ Collection<PortfolioAccountData> accountOptions = this.portfolioAccountReadPlatformService
+ .retrieveAllForLookup(portfolioAccountDTO);
+ if (!CollectionUtils.isEmpty(accountOptions)) {
+ accountOptions.remove(excludeThisAccountFromOptions);
+ } else {
+ accountOptions = null;
+ }
+
+ return accountOptions;
+ }
+
+ @Override
+ public Page<AccountTransferData> retrieveAll(
+ final SearchParameters searchParameters, final Long accountDetailId) {
+
+ final StringBuilder sqlBuilder = new StringBuilder(200);
+ sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
+ sqlBuilder.append(this.accountTransfersMapper.schema());
+ Object[] finalObjectArray = {};
+ if (accountDetailId != null) {
+ sqlBuilder.append(" where att.account_transfer_details_id=?");
+ finalObjectArray = new Object[] { accountDetailId };
+ }
+
+ if (searchParameters.isOrderByRequested()) {
+ sqlBuilder.append(" order by ").append(
+ searchParameters.getOrderBy());
+
+ if (searchParameters.isSortOrderProvided()) {
+ sqlBuilder.append(' ').append(searchParameters.getSortOrder());
+ }
+ }
+
+ if (searchParameters.isLimited()) {
+ sqlBuilder.append(" limit ").append(searchParameters.getLimit());
+ if (searchParameters.isOffset()) {
+ sqlBuilder.append(" offset ").append(
+ searchParameters.getOffset());
+ }
+ }
+
+ final String sqlCountRows = "SELECT FOUND_ROWS()";
+ return this.paginationHelper.fetchPage(this.jdbcTemplate, sqlCountRows,
+ sqlBuilder.toString(), finalObjectArray,
+ this.accountTransfersMapper);
+ }
+
+ @Override
+ public AccountTransferData retrieveOne(final Long transferId) {
+
+ try {
+ final String sql = "select " + this.accountTransfersMapper.schema()
+ + " where att.id = ?";
+
+ return this.jdbcTemplate.queryForObject(sql,
+ this.accountTransfersMapper, new Object[] { transferId });
+ } catch (final EmptyResultDataAccessException e) {
+ throw new AccountTransferNotFoundException(transferId);
+ }
+ }
+
+ @Override
+ public Collection<Long> fetchPostInterestTransactionIds(final Long accountId) {
+ final String sql = "select att.from_savings_transaction_id from m_account_transfer_transaction att inner join m_account_transfer_details atd on atd.id = att.account_transfer_details_id where atd.from_savings_account_id=? and att.is_reversed =0 and atd.transfer_type = ?";
+
+ final List<Long> transactionId = this.jdbcTemplate.queryForList(sql,
+ Long.class, accountId,
+ AccountTransferType.INTEREST_TRANSFER.getValue());
+
+ return transactionId;
+ }
+
+ private static final class AccountTransfersMapper implements
+ RowMapper<AccountTransferData> {
+
+ private final String schemaSql;
+
+ public AccountTransfersMapper() {
+ final StringBuilder sqlBuilder = new StringBuilder(400);
+ sqlBuilder.append("att.id as id, att.is_reversed as isReversed,");
+ sqlBuilder
+ .append("att.transaction_date as transferDate, att.amount as transferAmount,");
+ sqlBuilder.append("att.description as transferDescription,");
+ sqlBuilder
+ .append("att.currency_code as currencyCode, att.currency_digits as currencyDigits,");
+ sqlBuilder.append("att.currency_multiplesof as inMultiplesOf, ");
+ sqlBuilder
+ .append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
+ sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol, ");
+ sqlBuilder
+ .append("fromoff.id as fromOfficeId, fromoff.name as fromOfficeName,");
+ sqlBuilder
+ .append("tooff.id as toOfficeId, tooff.name as toOfficeName,");
+ sqlBuilder
+ .append("fromclient.id as fromClientId, fromclient.display_name as fromClientName,");
+ sqlBuilder
+ .append("toclient.id as toClientId, toclient.display_name as toClientName,");
+ sqlBuilder
+ .append("fromsavacc.id as fromSavingsAccountId, fromsavacc.account_no as fromSavingsAccountNo,");
+ sqlBuilder
+ .append("fromloanacc.id as fromLoanAccountId, fromloanacc.account_no as fromLoanAccountNo,");
+ sqlBuilder
+ .append("tosavacc.id as toSavingsAccountId, tosavacc.account_no as toSavingsAccountNo,");
+ sqlBuilder
+ .append("toloanacc.id as toLoanAccountId, toloanacc.account_no as toLoanAccountNo,");
+ sqlBuilder
+ .append("fromsavtran.id as fromSavingsAccountTransactionId,");
+ sqlBuilder
+ .append("fromsavtran.transaction_type_enum as fromSavingsAccountTransactionType,");
+ sqlBuilder.append("tosavtran.id as toSavingsAccountTransactionId,");
+ sqlBuilder
+ .append("tosavtran.transaction_type_enum as toSavingsAccountTransactionType");
+ sqlBuilder.append(" FROM m_account_transfer_transaction att ");
+ sqlBuilder
+ .append("left join m_account_transfer_details atd on atd.id = att.account_transfer_details_id ");
+ sqlBuilder
+ .append("join m_currency curr on curr.code = att.currency_code ");
+ sqlBuilder
+ .append("join m_office fromoff on fromoff.id = atd.from_office_id ");
+ sqlBuilder
+ .append("join m_office tooff on tooff.id = atd.to_office_id ");
+ sqlBuilder
+ .append("join m_client fromclient on fromclient.id = atd.from_client_id ");
+ sqlBuilder
+ .append("join m_client toclient on toclient.id = atd.to_client_id ");
+ sqlBuilder
+ .append("left join m_savings_account fromsavacc on fromsavacc.id = atd.from_savings_account_id ");
+ sqlBuilder
+ .append("left join m_loan fromloanacc on fromloanacc.id = atd.from_loan_account_id ");
+ sqlBuilder
+ .append("left join m_savings_account tosavacc on tosavacc.id = atd.to_savings_account_id ");
+ sqlBuilder
+ .append("left join m_loan toloanacc on toloanacc.id = atd.to_loan_account_id ");
+ sqlBuilder
+ .append("left join m_savings_account_transaction fromsavtran on fromsavtran.id = att.from_savings_transaction_id ");
+ sqlBuilder
+ .append("left join m_savings_account_transaction tosavtran on tosavtran.id = att.to_savings_transaction_id ");
+ sqlBuilder
+ .append("left join m_loan_transaction fromloantran on fromloantran.id = att.from_savings_transaction_id ");
+ sqlBuilder
+ .append("left join m_loan_transaction toloantran on toloantran.id = att.to_savings_transaction_id ");
+
+ this.schemaSql = sqlBuilder.toString();
+ }
+
+ public String schema() {
+ return this.schemaSql;
+ }
+
+ @Override
+ public AccountTransferData mapRow(final ResultSet rs,
+ @SuppressWarnings("unused") final int rowNum)
+ throws SQLException {
+
+ final Long id = rs.getLong("id");
+ final boolean reversed = rs.getBoolean("isReversed");
+
+ final LocalDate transferDate = JdbcSupport.getLocalDate(rs,
+ "transferDate");
+ final BigDecimal transferAmount = JdbcSupport
+ .getBigDecimalDefaultToZeroIfNull(rs, "transferAmount");
+ final String transferDescription = rs
+ .getString("transferDescription");
+
+ final String currencyCode = rs.getString("currencyCode");
+ final String currencyName = rs.getString("currencyName");
+ final String currencyNameCode = rs.getString("currencyNameCode");
+ final String currencyDisplaySymbol = rs
+ .getString("currencyDisplaySymbol");
+ final Integer currencyDigits = JdbcSupport.getInteger(rs,
+ "currencyDigits");
+ final Integer inMultiplesOf = JdbcSupport.getInteger(rs,
+ "inMultiplesOf");
+ final CurrencyData currency = new CurrencyData(currencyCode,
+ currencyName, currencyDigits, inMultiplesOf,
+ currencyDisplaySymbol, currencyNameCode);
+
+ final Long fromOfficeId = JdbcSupport.getLong(rs, "fromOfficeId");
+ final String fromOfficeName = rs.getString("fromOfficeName");
+ final OfficeData fromOffice = OfficeData.dropdown(fromOfficeId,
+ fromOfficeName, null);
+
+ final Long toOfficeId = JdbcSupport.getLong(rs, "toOfficeId");
+ final String toOfficeName = rs.getString("toOfficeName");
+ final OfficeData toOffice = OfficeData.dropdown(toOfficeId,
+ toOfficeName, null);
+
+ final Long fromClientId = JdbcSupport.getLong(rs, "fromClientId");
+ final String fromClientName = rs.getString("fromClientName");
+ final ClientData fromClient = ClientData.lookup(fromClientId,
+ fromClientName, fromOfficeId, fromOfficeName);
+
+ final Long toClientId = JdbcSupport.getLong(rs, "toClientId");
+ final String toClientName = rs.getString("toClientName");
+ final ClientData toClient = ClientData.lookup(toClientId,
+ toClientName, toOfficeId, toOfficeName);
+
+ final Long fromSavingsAccountId = JdbcSupport.getLong(rs,
+ "fromSavingsAccountId");
+ final String fromSavingsAccountNo = rs
+ .getString("fromSavingsAccountNo");
+ final Long fromLoanAccountId = JdbcSupport.getLong(rs,
+ "fromLoanAccountId");
+ final String fromLoanAccountNo = rs.getString("fromLoanAccountNo");
+ PortfolioAccountData fromAccount = null;
+ EnumOptionData fromAccountType = null;
+ if (fromSavingsAccountId != null) {
+ fromAccount = PortfolioAccountData.lookup(fromSavingsAccountId,
+ fromSavingsAccountNo);
+ fromAccountType = AccountTransferEnumerations
+ .accountType(PortfolioAccountType.SAVINGS);
+ } else if (fromLoanAccountId != null) {
+ fromAccount = PortfolioAccountData.lookup(fromLoanAccountId,
+ fromLoanAccountNo);
+ fromAccountType = AccountTransferEnumerations
+ .accountType(PortfolioAccountType.LOAN);
+ }
+
+ PortfolioAccountData toAccount = null;
+ EnumOptionData toAccountType = null;
+ final Long toSavingsAccountId = JdbcSupport.getLong(rs,
+ "toSavingsAccountId");
+ final String toSavingsAccountNo = rs
+ .getString("toSavingsAccountNo");
+ final Long toLoanAccountId = JdbcSupport.getLong(rs,
+ "toLoanAccountId");
+ final String toLoanAccountNo = rs.getString("toLoanAccountNo");
+
+ if (toSavingsAccountId != null) {
+ toAccount = PortfolioAccountData.lookup(toSavingsAccountId,
+ toSavingsAccountNo);
+ toAccountType = AccountTransferEnumerations
+ .accountType(PortfolioAccountType.SAVINGS);
+ } else if (toLoanAccountId != null) {
+ toAccount = PortfolioAccountData.lookup(toLoanAccountId,
+ toLoanAccountNo);
+ toAccountType = AccountTransferEnumerations
+ .accountType(PortfolioAccountType.LOAN);
+ }
+
+ return AccountTransferData.instance(id, reversed, transferDate,
+ currency, transferAmount, transferDescription, fromOffice,
+ toOffice, fromClient, toClient, fromAccountType,
+ fromAccount, toAccountType, toAccount);
+ }
+ }
+
+ @Override
+ public boolean isAccountTransfer(final Long transactionId,
+ final PortfolioAccountType accountType) {
+ final StringBuilder sql = new StringBuilder(
+ "select count(*) from m_account_transfer_transaction at where ");
+ if (accountType.isLoanAccount()) {
+ sql.append("at.from_loan_transaction_id=").append(transactionId)
+ .append(" or at.to_loan_transaction_id=")
+ .append(transactionId);
+ } else {
+ sql.append("at.from_savings_transaction_id=").append(transactionId)
+ .append(" or at.to_savings_transaction_id=")
+ .append(transactionId);
+ }
+
+ @SuppressWarnings("deprecation")
+ final int count = this.jdbcTemplate.queryForInt(sql.toString());
+ return count > 0;
+ }
+
+ @Override
+ public Page<AccountTransferData> retrieveByStandingInstruction(
+ final Long id, final SearchParameters searchParameters) {
+
+ final StringBuilder sqlBuilder = new StringBuilder(200);
+ sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
+ sqlBuilder
+ .append(this.accountTransfersMapper.schema())
+ .append(" join m_account_transfer_standing_instructions atsi on atsi.account_transfer_details_id = att.account_transfer_details_id ");
+ sqlBuilder.append(" where atsi.id = ?");
+
+ if (searchParameters != null) {
+ if (searchParameters.isOrderByRequested()) {
+ sqlBuilder.append(" order by ").append(
+ searchParameters.getOrderBy());
+
+ if (searchParameters.isSortOrderProvided()) {
+ sqlBuilder.append(' ').append(
+ searchParameters.getSortOrder());
+ }
+ }
+
+ if (searchParameters.isLimited()) {
+ sqlBuilder.append(" limit ")
+ .append(searchParameters.getLimit());
+ if (searchParameters.isOffset()) {
+ sqlBuilder.append(" offset ").append(
+ searchParameters.getOffset());
+ }
+ }
+ }
+
+ final Object[] finalObjectArray = { id };
+ final String sqlCountRows = "SELECT FOUND_ROWS()";
+ return this.paginationHelper.fetchPage(this.jdbcTemplate, sqlCountRows,
+ sqlBuilder.toString(), finalObjectArray,
+ this.accountTransfersMapper);
+ }
+
+ @Override
+ public AccountTransferData retrieveRefundByTransferTemplate(
+ final Long fromOfficeId, final Long fromClientId,
+ final Long fromAccountId, final Integer fromAccountType,
+ final Long toOfficeId, final Long toClientId,
+ final Long toAccountId, final Integer toAccountType) {
+ // TODO Auto-generated method stub
+ final EnumOptionData loanAccountType = AccountTransferEnumerations
+ .accountType(PortfolioAccountType.LOAN);
+ final EnumOptionData savingsAccountType = AccountTransferEnumerations
+ .accountType(PortfolioAccountType.SAVINGS);
+
+ final Integer mostRelevantFromAccountType = fromAccountType;
+ final Collection<EnumOptionData> fromAccountTypeOptions = Arrays
+ .asList(savingsAccountType, loanAccountType);
+ final Collection<EnumOptionData> toAccountTypeOptions;
+ if (mostRelevantFromAccountType == 1) {
+ // overpaid loan amt transfer to savings account
+ toAccountTypeOptions = Arrays.asList(savingsAccountType);
+ } else {
+ toAccountTypeOptions = Arrays.asList(loanAccountType,
+ savingsAccountType);
+ }
+ final Integer mostRelevantToAccountType = toAccountType;
+
+ final EnumOptionData fromAccountTypeData = AccountTransferEnumerations
+ .accountType(mostRelevantFromAccountType);
+ final EnumOptionData toAccountTypeData = AccountTransferEnumerations
+ .accountType(mostRelevantToAccountType);
+
+ // from settings
+ OfficeData fromOffice = null;
+ ClientData fromClient = null;
+ PortfolioAccountData fromAccount = null;
+
+ OfficeData toOffice = null;
+ ClientData toClient = null;
+ PortfolioAccountData toAccount = null;
+
+ // template
+ Collection<PortfolioAccountData> fromAccountOptions = null;
+ Collection<PortfolioAccountData> toAccountOptions = null;
+
+ Long mostRelevantFromOfficeId = fromOfficeId;
+ Long mostRelevantFromClientId = fromClientId;
+
+ Long mostRelevantToOfficeId = toOfficeId;
+ Long mostRelevantToClientId = toClientId;
+
+ if (fromAccountId != null) {
+ Integer accountType;
+ if (mostRelevantFromAccountType == 1) {
+ accountType = PortfolioAccountType.LOAN.getValue();
+ } else {
+ accountType = PortfolioAccountType.SAVINGS.getValue();
+ }
+ fromAccount = this.portfolioAccountReadPlatformService
+ .retrieveOneByPaidInAdvance(fromAccountId, accountType);
+
+ // override provided fromClient with client of account
+ mostRelevantFromClientId = fromAccount.clientId();
+ }
+
+ if (mostRelevantFromClientId != null) {
+ fromClient = this.clientReadPlatformService
+ .retrieveOne(mostRelevantFromClientId);
+ mostRelevantFromOfficeId = fromClient.officeId();
+ long[] loanStatus = null;
+ if (mostRelevantFromAccountType == 1) {
+ loanStatus = new long[] { 300, 700 };
+ }
+ PortfolioAccountDTO portfolioAccountDTO = new PortfolioAccountDTO(
+ mostRelevantFromAccountType, mostRelevantFromClientId,
+ loanStatus);
+ fromAccountOptions = this.portfolioAccountReadPlatformService
+ .retrieveAllForLookup(portfolioAccountDTO);
+ }
+
+ Collection<OfficeData> fromOfficeOptions = null;
+ Collection<ClientData> fromClientOptions = null;
+ if (mostRelevantFromOfficeId != null) {
+ fromOffice = this.officeReadPlatformService
+ .retrieveOffice(mostRelevantFromOfficeId);
+ fromOfficeOptions = this.officeReadPlatformService
+ .retrieveAllOfficesForDropdown();
+ fromClientOptions = this.clientReadPlatformService
+ .retrieveAllForLookupByOfficeId(mostRelevantFromOfficeId);
+ }
+
+ // defaults
+ final LocalDate transferDate = DateUtils.getLocalDateOfTenant();
+ Collection<OfficeData> toOfficeOptions = fromOfficeOptions;
+ Collection<ClientData> toClientOptions = null;
+
+ if (toAccountId != null && fromAccount != null) {
+ toAccount = this.portfolioAccountReadPlatformService.retrieveOne(
+ toAccountId, mostRelevantToAccountType,
+ fromAccount.currencyCode());
+ mostRelevantToClientId = toAccount.clientId();
+ }
+
+ if (mostRelevantToClientId != null) {
+ toClient = this.clientReadPlatformService
+ .retrieveOne(mostRelevantToClientId);
+ mostRelevantToOfficeId = toClient.officeId();
+
+ toClientOptions = this.clientReadPlatformService
+ .retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
+
+ toAccountOptions = retrieveToAccounts(fromAccount,
+ mostRelevantToAccountType, mostRelevantToClientId);
+ }
+
+ if (mostRelevantToOfficeId != null) {
+ toOffice = this.officeReadPlatformService
+ .retrieveOffice(mostRelevantToOfficeId);
+ toOfficeOptions = this.officeReadPlatformService
+ .retrieveAllOfficesForDropdown();
+
+ toClientOptions = this.clientReadPlatformService
+ .retrieveAllForLookupByOfficeId(mostRelevantToOfficeId);
+ if (toClientOptions != null && toClientOptions.size() == 1) {
+ toClient = new ArrayList<>(toClientOptions).get(0);
+
+ toAccountOptions = retrieveToAccounts(fromAccount,
+ mostRelevantToAccountType, mostRelevantToClientId);
+ }
+ }
+
+ return AccountTransferData.template(fromOffice, fromClient,
+ fromAccountTypeData, fromAccount, transferDate, toOffice,
+ toClient, toAccountTypeData, toAccount, fromOfficeOptions,
+ fromClientOptions, fromAccountTypeOptions, fromAccountOptions,
+ toOfficeOptions, toClientOptions, toAccountTypeOptions,
+ toAccountOptions);
+ }
+
+ @Override
+ public BigDecimal getTotalTransactionAmount(Long accountId,
+ Integer accountType, LocalDate transactionDate) {
+ StringBuilder sqlBuilder = new StringBuilder(
+ " select sum(trans.amount) as totalTransactionAmount ");
+ sqlBuilder.append(" from m_account_transfer_details as det ");
+ sqlBuilder
+ .append(" inner join m_account_transfer_transaction as trans ");
+ sqlBuilder.append(" on det.id = trans.account_transfer_details_id ");
+ sqlBuilder.append(" where trans.is_reversed = 0 ");
+ sqlBuilder.append(" and trans.transaction_date = ? ");
+ sqlBuilder
+ .append(" and IF(1=?, det.from_loan_account_id = ?, det.from_savings_account_id = ?) ");
+
+ return this.jdbcTemplate.queryForObject(sqlBuilder.toString(),
+ new Object[] { this.formatter.print(transactionDate),
+ accountType, accountId, accountId }, BigDecimal.class);
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java
index 845cc67..b306d70 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java
@@ -69,6 +69,8 @@ public interface LoanRepository extends JpaRepository<Loan, Long>, JpaSpecificat
public static final String DOES_PRODUCT_HAVE_NON_CLOSED_LOANS = "select case when (count (loan) > 0) then true else false end from Loan loan where loan.loanProduct.id = :productId and loan.loanStatus in (100,200,300,303,304,700)";
+ public static final String FIND_BY_ACCOUNT_NUMBER = "from Loan loan where loan.accountNumber = :accountNumber and loan.loanStatus in (100,200,300,303,304)";
+
@Query(FIND_GROUP_LOANS_DISBURSED_AFTER)
List<Loan> getGroupLoansDisbursedAfter(@Param("disbursementDate") Date disbursementDate, @Param("groupId") Long groupId,
@Param("loanType") Integer loanType);
@@ -144,5 +146,7 @@ public interface LoanRepository extends JpaRepository<Loan, Long>, JpaSpecificat
@Query(DOES_PRODUCT_HAVE_NON_CLOSED_LOANS)
boolean doNonClosedLoanAccountsExistForProduct(@Param("productId") Long productId);
-
+
+ @Query(FIND_BY_ACCOUNT_NUMBER)
+ Loan findNonClosedLoanByAccountNumber(@Param("accountNumber") String accountNumber);
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/2bd3b062/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepository.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepository.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepository.java
index b34e897..b614b25 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepository.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountRepository.java
@@ -45,4 +45,7 @@ public interface SavingsAccountRepository extends JpaRepository<SavingsAccount,
@Query("from SavingsAccount sa where sa.id = :accountId and sa.depositType = :depositAccountTypeId")
SavingsAccount findByIdAndDepositAccountType(@Param("accountId") Long accountId,
@Param("depositAccountTypeId") Integer depositAccountTypeId);
+
+ @Query("from SavingsAccount sa where sa.accountNumber = :accountNumber and sa.status in (100, 200, 300, 303, 304) ")
+ SavingsAccount findNonClosedAccountByAccountNumber(@Param("accountNumber") String accountNumber);
}
\ No newline at end of file