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);