feat: current account standing instructions - full backend support
- StandingInstructionData: rename conflicting Lombok getters (getInstructionType,
getRecurrenceType, getRecurrenceFrequency, getFromAccountType, getToAccountType,
getTransferType) to domain enum methods so Jackson serializes EnumOptionData fields
as {id, code, value} objects instead of plain strings
- AccountTransfersWritePlatformServiceImpl: add current account transfer support for
all 4 missing cases (Current->Savings, Savings->Current, Current->Current,
Current->Loan) with performCurrentWithdrawal/performCurrentDeposit helpers
- AccountConfiguration: wire CurrentAccountRepository and CurrentAccountTransactionRepository
into AccountTransfersWritePlatformService bean
- StandingInstructionApiResource: fix getValue() type mismatch after getter rename
- ExecuteStandingInstructionsTasklet: update to use renamed enum accessor methods
- PortfolioAccountType: add CURRENT(3) type support
- DB migration: 0301_add_current_account_to_transfer_details.xml adds
from_current_account_id and to_current_account_id columns to transfer details table
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
45585ecc10
commit
2251fd2259
+79
-71
@@ -1,71 +1,79 @@
|
||||
/**
|
||||
* 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.account;
|
||||
|
||||
public enum PortfolioAccountType {
|
||||
|
||||
INVALID(0, "accountType.invalid"), //
|
||||
LOAN(1, "accountType.loan"), //
|
||||
SAVINGS(2, "accountType.savings"), //
|
||||
;
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
PortfolioAccountType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public static PortfolioAccountType fromInt(final Integer type) {
|
||||
|
||||
PortfolioAccountType enumType = INVALID;
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
case 1:
|
||||
enumType = LOAN;
|
||||
break;
|
||||
case 2:
|
||||
enumType = SAVINGS;
|
||||
break;
|
||||
default:
|
||||
enumType = INVALID;
|
||||
}
|
||||
}
|
||||
return enumType;
|
||||
}
|
||||
|
||||
// TODO: bad practice and unnecessary code! why not just use the enum values themselves!?!
|
||||
public boolean isSavingsAccount() {
|
||||
return this.equals(SAVINGS);
|
||||
}
|
||||
|
||||
// TODO: bad practice and unnecessary code! why not just use the enum values themselves!?!
|
||||
public boolean isLoanAccount() {
|
||||
return this.equals(LOAN);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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.account;
|
||||
|
||||
public enum PortfolioAccountType {
|
||||
|
||||
INVALID(0, "accountType.invalid"), //
|
||||
LOAN(1, "accountType.loan"), //
|
||||
SAVINGS(2, "accountType.savings"), //
|
||||
CURRENT(3, "accountType.current"), //
|
||||
;
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
PortfolioAccountType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public static PortfolioAccountType fromInt(final Integer type) {
|
||||
|
||||
PortfolioAccountType enumType = INVALID;
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
case 1:
|
||||
enumType = LOAN;
|
||||
break;
|
||||
case 2:
|
||||
enumType = SAVINGS;
|
||||
break;
|
||||
case 3:
|
||||
enumType = CURRENT;
|
||||
break;
|
||||
default:
|
||||
enumType = INVALID;
|
||||
}
|
||||
}
|
||||
return enumType;
|
||||
}
|
||||
|
||||
// TODO: bad practice and unnecessary code! why not just use the enum values themselves!?!
|
||||
public boolean isSavingsAccount() {
|
||||
return this.equals(SAVINGS);
|
||||
}
|
||||
|
||||
// TODO: bad practice and unnecessary code! why not just use the enum values themselves!?!
|
||||
public boolean isLoanAccount() {
|
||||
return this.equals(LOAN);
|
||||
}
|
||||
|
||||
public boolean isCurrentAccount() {
|
||||
return this.equals(CURRENT);
|
||||
}
|
||||
}
|
||||
|
||||
+220
-220
@@ -1,220 +1,220 @@
|
||||
/**
|
||||
* 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.account.api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.ws.rs.BeanParam;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.PUT;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.UriInfo;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.batch.command.CommandHandlerRegistry;
|
||||
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.ApiParameterHelper;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.exception.UnrecognizedQueryParamException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||
import org.apache.fineract.infrastructure.core.service.CommandParameterUtil;
|
||||
import org.apache.fineract.infrastructure.core.service.Page;
|
||||
import org.apache.fineract.infrastructure.core.service.SearchParameters;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.infrastructure.security.service.SqlValidator;
|
||||
import org.apache.fineract.portfolio.account.data.AccountTransferData;
|
||||
import org.apache.fineract.portfolio.account.data.StandingInstructionDTO;
|
||||
import org.apache.fineract.portfolio.account.data.StandingInstructionData;
|
||||
import org.apache.fineract.portfolio.account.data.request.StandingInstructionCreationRequest;
|
||||
import org.apache.fineract.portfolio.account.data.request.StandingInstructionSearchParam;
|
||||
import org.apache.fineract.portfolio.account.data.request.StandingInstructionUpdatesRequest;
|
||||
import org.apache.fineract.portfolio.account.service.AccountTransfersReadPlatformService;
|
||||
import org.apache.fineract.portfolio.account.service.StandingInstructionReadPlatformService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Path("/v1/standinginstructions")
|
||||
@Component
|
||||
@Tag(name = "Standing Instructions", description = "Standing instructions (or standing orders) refer to instructions a bank account holder (\"the payer\") gives to his or her bank to pay a set amount at regular intervals to another's (\"the payee's\") account.\n"
|
||||
+ "\n" + "Note: At present only savings account to savings account and savings account to Loan account transfers are permitted.")
|
||||
@RequiredArgsConstructor
|
||||
public class StandingInstructionApiResource {
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final DefaultToApiJsonSerializer<StandingInstructionData> toApiJsonSerializer;
|
||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||
private final StandingInstructionReadPlatformService standingInstructionReadPlatformService;
|
||||
private final AccountTransfersReadPlatformService accountTransfersReadPlatformService;
|
||||
private final SqlValidator sqlValidator;
|
||||
|
||||
private static final CommandHandlerRegistry<String, Long, String, CommandWrapper> COMMAND_HANDLER_REGISTRY = new CommandHandlerRegistry<>(
|
||||
Map.of(CommandParameterUtil.UPDATE_COMMAND_VALUE,
|
||||
(id, json) -> new CommandWrapperBuilder().updateStandingInstruction(id).withJson(json).build(),
|
||||
CommandParameterUtil.DELETE_COMMAND_VALUE,
|
||||
(id, json) -> new CommandWrapperBuilder().deleteStandingInstruction(id).withJson(json).build()));
|
||||
|
||||
@GET
|
||||
@Path("template")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve Standing Instruction Template", description = "This is a convenience resource. "
|
||||
+ "It can be useful when building maintenance user interface screens for client applications. "
|
||||
+ "The template data returned consists of any or all of:\n" + "\n" + "Field Defaults\n" + "Allowed Value Lists\n"
|
||||
+ "Example Requests:\n" + "\n" + "standinginstructions/template?fromAccountType=2&fromOfficeId=1\n" + "\n"
|
||||
+ "standinginstructions/template?fromAccountType=2&fromOfficeId=1&fromClientId=1&transferType=1\n" + "\n"
|
||||
+ "standinginstructions/template?fromClientId=1&fromAccountType=2&fromAccountId=1&transferType=1")
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = StandingInstructionApiResourceSwagger.GetStandingInstructionsTemplateResponse.class)))
|
||||
public StandingInstructionData template(@BeanParam StandingInstructionSearchParam instructionParam) {
|
||||
context.authenticatedUser().validateHasReadPermission(StandingInstructionApiConstants.STANDING_INSTRUCTION_RESOURCE_NAME);
|
||||
|
||||
return standingInstructionReadPlatformService.retrieveTemplate(instructionParam.getFromOfficeId(),
|
||||
instructionParam.getFromClientId(), instructionParam.getFromAccountId(), instructionParam.getFromAccountType(),
|
||||
instructionParam.getToOfficeId(), instructionParam.getToClientId(), instructionParam.getToAccountId(),
|
||||
instructionParam.getToAccountType(), instructionParam.getTransferType());
|
||||
}
|
||||
|
||||
@POST
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Create new Standing Instruction", description = "Ability to create new instruction for transfer of monetary funds from one account to another")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = StandingInstructionCreationRequest.class)))
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = StandingInstructionApiResourceSwagger.PostStandingInstructionsResponse.class)))
|
||||
public CommandProcessingResult create(@Parameter(hidden = true) StandingInstructionCreationRequest creationRequest) {
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().createStandingInstruction()
|
||||
.withJson(toApiJsonSerializer.serialize(creationRequest)).build();
|
||||
|
||||
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("{standingInstructionId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Update Standing Instruction | Delete Standing Instruction", description = "Ability to modify existing instruction for transfer of monetary funds from one account to another.\n"
|
||||
+ "\n" + "PUT https://DomainName/api/v1/standinginstructions/1?command=update\n" + "\n\n"
|
||||
+ "Ability to modify existing instruction for transfer of monetary funds from one account to another.\n" + "\n"
|
||||
+ "PUT https://DomainName/api/v1/standinginstructions/1?command=delete")
|
||||
@RequestBody(content = @Content(schema = @Schema(implementation = StandingInstructionUpdatesRequest.class)))
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = StandingInstructionApiResourceSwagger.PutStandingInstructionsStandingInstructionIdResponse.class)))
|
||||
public CommandProcessingResult update(
|
||||
@PathParam("standingInstructionId") @Parameter(description = "standingInstructionId") final Long standingInstructionId,
|
||||
@Parameter(hidden = true) StandingInstructionUpdatesRequest updatesRequest,
|
||||
@QueryParam("command") @Parameter(description = "command") final String commandParam) {
|
||||
|
||||
final String serializedUpdatesRequest = toApiJsonSerializer.serialize(updatesRequest);
|
||||
final CommandWrapper commandRequest = COMMAND_HANDLER_REGISTRY.execute(commandParam, standingInstructionId,
|
||||
serializedUpdatesRequest, new UnrecognizedQueryParamException("command", commandParam));
|
||||
|
||||
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "List Standing Instructions", description = "Example Requests:\n" + "\n" + "standinginstructions")
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = StandingInstructionApiResourceSwagger.GetStandingInstructionsResponse.class)))
|
||||
public Page<StandingInstructionData> retrieveAll(
|
||||
@QueryParam("externalId") @Parameter(description = "externalId") final String externalId,
|
||||
@QueryParam("offset") @Parameter(description = "offset") final Integer offset,
|
||||
@QueryParam("limit") @Parameter(description = "limit") final Integer limit,
|
||||
@QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy,
|
||||
@QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder,
|
||||
@QueryParam("transferType") @Parameter(description = "transferType") final Integer transferType,
|
||||
@QueryParam("clientName") @Parameter(description = "clientName") final String clientName,
|
||||
@QueryParam("clientId") @Parameter(description = "clientId") final Long clientId,
|
||||
@QueryParam("fromAccountId") @Parameter(description = "fromAccountId") final Long fromAccount,
|
||||
@QueryParam("fromAccountType") @Parameter(description = "fromAccountType") final Integer fromAccountType) {
|
||||
|
||||
context.authenticatedUser().validateHasReadPermission(StandingInstructionApiConstants.STANDING_INSTRUCTION_RESOURCE_NAME);
|
||||
|
||||
sqlValidator.validate(orderBy);
|
||||
sqlValidator.validate(sortOrder);
|
||||
sqlValidator.validate(externalId);
|
||||
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).externalId(externalId).offset(offset)
|
||||
.orderBy(orderBy).sortOrder(sortOrder).build();
|
||||
|
||||
final LocalDate startDateRange = null;
|
||||
final LocalDate endDateRange = null;
|
||||
StandingInstructionDTO standingInstructionDTO = new StandingInstructionDTO(searchParameters, transferType, clientName, clientId,
|
||||
fromAccount, fromAccountType, startDateRange, endDateRange);
|
||||
|
||||
return standingInstructionReadPlatformService.retrieveAll(standingInstructionDTO);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{standingInstructionId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve Standing Instruction", description = "Example Requests :\n" + "\n" + "standinginstructions/1")
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = StandingInstructionApiResourceSwagger.GetStandingInstructionsStandingInstructionIdResponse.class)))
|
||||
public StandingInstructionData retrieveOne(
|
||||
@PathParam("standingInstructionId") @Parameter(description = "standingInstructionId") final Long standingInstructionId,
|
||||
@Context final UriInfo uriInfo, @QueryParam("externalId") @Parameter(description = "externalId") final String externalId,
|
||||
@QueryParam("offset") @Parameter(description = "offset") final Integer offset,
|
||||
@QueryParam("limit") @Parameter(description = "limit") final Integer limit,
|
||||
@QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy,
|
||||
@QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) {
|
||||
|
||||
context.authenticatedUser().validateHasReadPermission(StandingInstructionApiConstants.STANDING_INSTRUCTION_RESOURCE_NAME);
|
||||
|
||||
sqlValidator.validate(orderBy);
|
||||
sqlValidator.validate(sortOrder);
|
||||
StandingInstructionData standingInstructionData = standingInstructionReadPlatformService.retrieveOne(standingInstructionId);
|
||||
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).externalId(externalId).offset(offset)
|
||||
.orderBy(orderBy).sortOrder(sortOrder).build();
|
||||
final Set<String> associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters());
|
||||
if (!associationParameters.isEmpty()) {
|
||||
if (associationParameters.contains("all")) {
|
||||
associationParameters.addAll(Arrays.asList("transactions", "template"));
|
||||
}
|
||||
if (associationParameters.contains("transactions")) {
|
||||
Page<AccountTransferData> transfers = accountTransfersReadPlatformService
|
||||
.retrieveByStandingInstruction(standingInstructionId, searchParameters);
|
||||
standingInstructionData = StandingInstructionData.withTransferData(standingInstructionData, transfers);
|
||||
}
|
||||
if (associationParameters.contains("template")) {
|
||||
final StandingInstructionData templateData = standingInstructionReadPlatformService.retrieveTemplate(
|
||||
standingInstructionData.getFromClient().getOfficeId(), standingInstructionData.getFromClient().getId(),
|
||||
standingInstructionData.getFromAccount().getId(), standingInstructionData.getFromAccountType().getValue(),
|
||||
standingInstructionData.getToClient().getOfficeId(), standingInstructionData.getToClient().getId(),
|
||||
standingInstructionData.getToAccount().getId(), standingInstructionData.getToAccountType().getValue(),
|
||||
standingInstructionData.getTransferType().getValue());
|
||||
standingInstructionData = StandingInstructionData.withTemplateData(standingInstructionData, templateData);
|
||||
}
|
||||
}
|
||||
|
||||
return standingInstructionData;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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.account.api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.ws.rs.BeanParam;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.PUT;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.UriInfo;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.batch.command.CommandHandlerRegistry;
|
||||
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.ApiParameterHelper;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.exception.UnrecognizedQueryParamException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||
import org.apache.fineract.infrastructure.core.service.CommandParameterUtil;
|
||||
import org.apache.fineract.infrastructure.core.service.Page;
|
||||
import org.apache.fineract.infrastructure.core.service.SearchParameters;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.infrastructure.security.service.SqlValidator;
|
||||
import org.apache.fineract.portfolio.account.data.AccountTransferData;
|
||||
import org.apache.fineract.portfolio.account.data.StandingInstructionDTO;
|
||||
import org.apache.fineract.portfolio.account.data.StandingInstructionData;
|
||||
import org.apache.fineract.portfolio.account.data.request.StandingInstructionCreationRequest;
|
||||
import org.apache.fineract.portfolio.account.data.request.StandingInstructionSearchParam;
|
||||
import org.apache.fineract.portfolio.account.data.request.StandingInstructionUpdatesRequest;
|
||||
import org.apache.fineract.portfolio.account.service.AccountTransfersReadPlatformService;
|
||||
import org.apache.fineract.portfolio.account.service.StandingInstructionReadPlatformService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Path("/v1/standinginstructions")
|
||||
@Component
|
||||
@Tag(name = "Standing Instructions", description = "Standing instructions (or standing orders) refer to instructions a bank account holder (\"the payer\") gives to his or her bank to pay a set amount at regular intervals to another's (\"the payee's\") account.\n"
|
||||
+ "\n" + "Note: At present only savings account to savings account and savings account to Loan account transfers are permitted.")
|
||||
@RequiredArgsConstructor
|
||||
public class StandingInstructionApiResource {
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final DefaultToApiJsonSerializer<StandingInstructionData> toApiJsonSerializer;
|
||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||
private final StandingInstructionReadPlatformService standingInstructionReadPlatformService;
|
||||
private final AccountTransfersReadPlatformService accountTransfersReadPlatformService;
|
||||
private final SqlValidator sqlValidator;
|
||||
|
||||
private static final CommandHandlerRegistry<String, Long, String, CommandWrapper> COMMAND_HANDLER_REGISTRY = new CommandHandlerRegistry<>(
|
||||
Map.of(CommandParameterUtil.UPDATE_COMMAND_VALUE,
|
||||
(id, json) -> new CommandWrapperBuilder().updateStandingInstruction(id).withJson(json).build(),
|
||||
CommandParameterUtil.DELETE_COMMAND_VALUE,
|
||||
(id, json) -> new CommandWrapperBuilder().deleteStandingInstruction(id).withJson(json).build()));
|
||||
|
||||
@GET
|
||||
@Path("template")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve Standing Instruction Template", description = "This is a convenience resource. "
|
||||
+ "It can be useful when building maintenance user interface screens for client applications. "
|
||||
+ "The template data returned consists of any or all of:\n" + "\n" + "Field Defaults\n" + "Allowed Value Lists\n"
|
||||
+ "Example Requests:\n" + "\n" + "standinginstructions/template?fromAccountType=2&fromOfficeId=1\n" + "\n"
|
||||
+ "standinginstructions/template?fromAccountType=2&fromOfficeId=1&fromClientId=1&transferType=1\n" + "\n"
|
||||
+ "standinginstructions/template?fromClientId=1&fromAccountType=2&fromAccountId=1&transferType=1")
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = StandingInstructionApiResourceSwagger.GetStandingInstructionsTemplateResponse.class)))
|
||||
public StandingInstructionData template(@BeanParam StandingInstructionSearchParam instructionParam) {
|
||||
context.authenticatedUser().validateHasReadPermission(StandingInstructionApiConstants.STANDING_INSTRUCTION_RESOURCE_NAME);
|
||||
|
||||
return standingInstructionReadPlatformService.retrieveTemplate(instructionParam.getFromOfficeId(),
|
||||
instructionParam.getFromClientId(), instructionParam.getFromAccountId(), instructionParam.getFromAccountType(),
|
||||
instructionParam.getToOfficeId(), instructionParam.getToClientId(), instructionParam.getToAccountId(),
|
||||
instructionParam.getToAccountType(), instructionParam.getTransferType());
|
||||
}
|
||||
|
||||
@POST
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Create new Standing Instruction", description = "Ability to create new instruction for transfer of monetary funds from one account to another")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = StandingInstructionCreationRequest.class)))
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = StandingInstructionApiResourceSwagger.PostStandingInstructionsResponse.class)))
|
||||
public CommandProcessingResult create(@Parameter(hidden = true) StandingInstructionCreationRequest creationRequest) {
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().createStandingInstruction()
|
||||
.withJson(toApiJsonSerializer.serialize(creationRequest)).build();
|
||||
|
||||
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("{standingInstructionId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Update Standing Instruction | Delete Standing Instruction", description = "Ability to modify existing instruction for transfer of monetary funds from one account to another.\n"
|
||||
+ "\n" + "PUT https://DomainName/api/v1/standinginstructions/1?command=update\n" + "\n\n"
|
||||
+ "Ability to modify existing instruction for transfer of monetary funds from one account to another.\n" + "\n"
|
||||
+ "PUT https://DomainName/api/v1/standinginstructions/1?command=delete")
|
||||
@RequestBody(content = @Content(schema = @Schema(implementation = StandingInstructionUpdatesRequest.class)))
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = StandingInstructionApiResourceSwagger.PutStandingInstructionsStandingInstructionIdResponse.class)))
|
||||
public CommandProcessingResult update(
|
||||
@PathParam("standingInstructionId") @Parameter(description = "standingInstructionId") final Long standingInstructionId,
|
||||
@Parameter(hidden = true) StandingInstructionUpdatesRequest updatesRequest,
|
||||
@QueryParam("command") @Parameter(description = "command") final String commandParam) {
|
||||
|
||||
final String serializedUpdatesRequest = toApiJsonSerializer.serialize(updatesRequest);
|
||||
final CommandWrapper commandRequest = COMMAND_HANDLER_REGISTRY.execute(commandParam, standingInstructionId,
|
||||
serializedUpdatesRequest, new UnrecognizedQueryParamException("command", commandParam));
|
||||
|
||||
return commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "List Standing Instructions", description = "Example Requests:\n" + "\n" + "standinginstructions")
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = StandingInstructionApiResourceSwagger.GetStandingInstructionsResponse.class)))
|
||||
public Page<StandingInstructionData> retrieveAll(
|
||||
@QueryParam("externalId") @Parameter(description = "externalId") final String externalId,
|
||||
@QueryParam("offset") @Parameter(description = "offset") final Integer offset,
|
||||
@QueryParam("limit") @Parameter(description = "limit") final Integer limit,
|
||||
@QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy,
|
||||
@QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder,
|
||||
@QueryParam("transferType") @Parameter(description = "transferType") final Integer transferType,
|
||||
@QueryParam("clientName") @Parameter(description = "clientName") final String clientName,
|
||||
@QueryParam("clientId") @Parameter(description = "clientId") final Long clientId,
|
||||
@QueryParam("fromAccountId") @Parameter(description = "fromAccountId") final Long fromAccount,
|
||||
@QueryParam("fromAccountType") @Parameter(description = "fromAccountType") final Integer fromAccountType) {
|
||||
|
||||
context.authenticatedUser().validateHasReadPermission(StandingInstructionApiConstants.STANDING_INSTRUCTION_RESOURCE_NAME);
|
||||
|
||||
sqlValidator.validate(orderBy);
|
||||
sqlValidator.validate(sortOrder);
|
||||
sqlValidator.validate(externalId);
|
||||
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).externalId(externalId).offset(offset)
|
||||
.orderBy(orderBy).sortOrder(sortOrder).build();
|
||||
|
||||
final LocalDate startDateRange = null;
|
||||
final LocalDate endDateRange = null;
|
||||
StandingInstructionDTO standingInstructionDTO = new StandingInstructionDTO(searchParameters, transferType, clientName, clientId,
|
||||
fromAccount, fromAccountType, startDateRange, endDateRange);
|
||||
|
||||
return standingInstructionReadPlatformService.retrieveAll(standingInstructionDTO);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{standingInstructionId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve Standing Instruction", description = "Example Requests :\n" + "\n" + "standinginstructions/1")
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = StandingInstructionApiResourceSwagger.GetStandingInstructionsStandingInstructionIdResponse.class)))
|
||||
public StandingInstructionData retrieveOne(
|
||||
@PathParam("standingInstructionId") @Parameter(description = "standingInstructionId") final Long standingInstructionId,
|
||||
@Context final UriInfo uriInfo, @QueryParam("externalId") @Parameter(description = "externalId") final String externalId,
|
||||
@QueryParam("offset") @Parameter(description = "offset") final Integer offset,
|
||||
@QueryParam("limit") @Parameter(description = "limit") final Integer limit,
|
||||
@QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy,
|
||||
@QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) {
|
||||
|
||||
context.authenticatedUser().validateHasReadPermission(StandingInstructionApiConstants.STANDING_INSTRUCTION_RESOURCE_NAME);
|
||||
|
||||
sqlValidator.validate(orderBy);
|
||||
sqlValidator.validate(sortOrder);
|
||||
StandingInstructionData standingInstructionData = standingInstructionReadPlatformService.retrieveOne(standingInstructionId);
|
||||
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).externalId(externalId).offset(offset)
|
||||
.orderBy(orderBy).sortOrder(sortOrder).build();
|
||||
final Set<String> associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters());
|
||||
if (!associationParameters.isEmpty()) {
|
||||
if (associationParameters.contains("all")) {
|
||||
associationParameters.addAll(Arrays.asList("transactions", "template"));
|
||||
}
|
||||
if (associationParameters.contains("transactions")) {
|
||||
Page<AccountTransferData> transfers = accountTransfersReadPlatformService
|
||||
.retrieveByStandingInstruction(standingInstructionId, searchParameters);
|
||||
standingInstructionData = StandingInstructionData.withTransferData(standingInstructionData, transfers);
|
||||
}
|
||||
if (associationParameters.contains("template")) {
|
||||
final StandingInstructionData templateData = standingInstructionReadPlatformService.retrieveTemplate(
|
||||
standingInstructionData.getFromClient().getOfficeId(), standingInstructionData.getFromClient().getId(),
|
||||
standingInstructionData.getFromAccount().getId(), standingInstructionData.fromAccountTypeEnum().getValue(),
|
||||
standingInstructionData.getToClient().getOfficeId(), standingInstructionData.getToClient().getId(),
|
||||
standingInstructionData.getToAccount().getId(), standingInstructionData.toAccountTypeEnum().getValue(),
|
||||
standingInstructionData.transferTypeEnum().getValue());
|
||||
standingInstructionData = StandingInstructionData.withTemplateData(standingInstructionData, templateData);
|
||||
}
|
||||
}
|
||||
|
||||
return standingInstructionData;
|
||||
}
|
||||
}
|
||||
|
||||
+79
-79
@@ -1,79 +1,79 @@
|
||||
/**
|
||||
* 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.account.data;
|
||||
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.fromAccountIdParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.fromAccountTypeParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.fromClientIdParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.fromOfficeIdParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.toAccountIdParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.toAccountTypeParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.toClientIdParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.toOfficeIdParamName;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class AccountTransfersDetailDataValidator {
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
@Autowired
|
||||
public AccountTransfersDetailDataValidator(final FromJsonHelper fromApiJsonHelper) {
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
}
|
||||
|
||||
public void validate(final JsonCommand command, final DataValidatorBuilder baseDataValidator) {
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
|
||||
final Long fromOfficeId = this.fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element);
|
||||
baseDataValidator.reset().parameter(fromOfficeIdParamName).value(fromOfficeId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long fromClientId = this.fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element);
|
||||
baseDataValidator.reset().parameter(fromClientIdParamName).value(fromClientId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long fromAccountId = this.fromApiJsonHelper.extractLongNamed(fromAccountIdParamName, element);
|
||||
baseDataValidator.reset().parameter(fromAccountIdParamName).value(fromAccountId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Integer fromAccountType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(fromAccountTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(fromAccountTypeParamName).value(fromAccountType).notNull()
|
||||
.isOneOfTheseValues(Integer.valueOf(1), Integer.valueOf(2));
|
||||
|
||||
final Long toOfficeId = this.fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element);
|
||||
baseDataValidator.reset().parameter(toOfficeIdParamName).value(toOfficeId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long toClientId = this.fromApiJsonHelper.extractLongNamed(toClientIdParamName, element);
|
||||
baseDataValidator.reset().parameter(toClientIdParamName).value(toClientId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long toAccountId = this.fromApiJsonHelper.extractLongNamed(toAccountIdParamName, element);
|
||||
baseDataValidator.reset().parameter(toAccountIdParamName).value(toAccountId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Integer toAccountType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(toAccountTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(toAccountTypeParamName).value(toAccountType).notNull().isOneOfTheseValues(Integer.valueOf(1),
|
||||
Integer.valueOf(2));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* 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.account.data;
|
||||
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.fromAccountIdParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.fromAccountTypeParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.fromClientIdParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.fromOfficeIdParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.toAccountIdParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.toAccountTypeParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.toClientIdParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.toOfficeIdParamName;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class AccountTransfersDetailDataValidator {
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
@Autowired
|
||||
public AccountTransfersDetailDataValidator(final FromJsonHelper fromApiJsonHelper) {
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
}
|
||||
|
||||
public void validate(final JsonCommand command, final DataValidatorBuilder baseDataValidator) {
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
|
||||
final Long fromOfficeId = this.fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element);
|
||||
baseDataValidator.reset().parameter(fromOfficeIdParamName).value(fromOfficeId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long fromClientId = this.fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element);
|
||||
baseDataValidator.reset().parameter(fromClientIdParamName).value(fromClientId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long fromAccountId = this.fromApiJsonHelper.extractLongNamed(fromAccountIdParamName, element);
|
||||
baseDataValidator.reset().parameter(fromAccountIdParamName).value(fromAccountId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Integer fromAccountType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(fromAccountTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(fromAccountTypeParamName).value(fromAccountType).notNull()
|
||||
.isOneOfTheseValues(Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3));
|
||||
|
||||
final Long toOfficeId = this.fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element);
|
||||
baseDataValidator.reset().parameter(toOfficeIdParamName).value(toOfficeId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long toClientId = this.fromApiJsonHelper.extractLongNamed(toClientIdParamName, element);
|
||||
baseDataValidator.reset().parameter(toClientIdParamName).value(toClientId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Long toAccountId = this.fromApiJsonHelper.extractLongNamed(toAccountIdParamName, element);
|
||||
baseDataValidator.reset().parameter(toAccountIdParamName).value(toAccountId).notNull().integerGreaterThanZero();
|
||||
|
||||
final Integer toAccountType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(toAccountTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(toAccountTypeParamName).value(toAccountType).notNull().isOneOfTheseValues(Integer.valueOf(1),
|
||||
Integer.valueOf(2), Integer.valueOf(3));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+359
-329
@@ -1,329 +1,359 @@
|
||||
/**
|
||||
* 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.account.data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.MonthDay;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import lombok.Getter;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.service.Page;
|
||||
import org.apache.fineract.organisation.office.data.OfficeData;
|
||||
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferRecurrenceType;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferType;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionType;
|
||||
import org.apache.fineract.portfolio.client.data.ClientData;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
|
||||
|
||||
/**
|
||||
* Immutable data object representing a savings account.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public final class StandingInstructionData {
|
||||
|
||||
@Getter
|
||||
private final Long id;
|
||||
@Getter
|
||||
private final Long accountDetailId;
|
||||
@Getter
|
||||
private final String name;
|
||||
private final OfficeData fromOffice;
|
||||
@Getter
|
||||
private final ClientData fromClient;
|
||||
private final EnumOptionData fromAccountType;
|
||||
@Getter
|
||||
private final PortfolioAccountData fromAccount;
|
||||
private final OfficeData toOffice;
|
||||
@Getter
|
||||
private final ClientData toClient;
|
||||
private final EnumOptionData toAccountType;
|
||||
@Getter
|
||||
private final PortfolioAccountData toAccount;
|
||||
private final EnumOptionData transferType;
|
||||
private final EnumOptionData priority;
|
||||
private final EnumOptionData instructionType;
|
||||
@Getter
|
||||
private final EnumOptionData status;
|
||||
@Getter
|
||||
private final BigDecimal amount;
|
||||
@Getter
|
||||
private final LocalDate validFrom;
|
||||
private final LocalDate validTill;
|
||||
private final EnumOptionData recurrenceType;
|
||||
private final EnumOptionData recurrenceFrequency;
|
||||
@Getter
|
||||
private final Integer recurrenceInterval;
|
||||
private final MonthDay recurrenceOnMonthDay;
|
||||
private final Page<AccountTransferData> transactions;
|
||||
|
||||
private final Collection<OfficeData> fromOfficeOptions;
|
||||
private final Collection<ClientData> fromClientOptions;
|
||||
private final Collection<EnumOptionData> fromAccountTypeOptions;
|
||||
private final Collection<PortfolioAccountData> fromAccountOptions;
|
||||
private final Collection<OfficeData> toOfficeOptions;
|
||||
private final Collection<ClientData> toClientOptions;
|
||||
private final Collection<EnumOptionData> toAccountTypeOptions;
|
||||
private final Collection<PortfolioAccountData> toAccountOptions;
|
||||
private final Collection<EnumOptionData> transferTypeOptions;
|
||||
private final Collection<EnumOptionData> statusOptions;
|
||||
private final Collection<EnumOptionData> instructionTypeOptions;
|
||||
private final Collection<EnumOptionData> priorityOptions;
|
||||
private final Collection<EnumOptionData> recurrenceTypeOptions;
|
||||
private final Collection<EnumOptionData> recurrenceFrequencyOptions;
|
||||
|
||||
public static StandingInstructionData template(final Collection<OfficeData> fromOfficeOptions,
|
||||
final Collection<ClientData> fromClientOptions, final Collection<EnumOptionData> fromAccountTypeOptions,
|
||||
final Collection<PortfolioAccountData> fromAccountOptions, final Collection<OfficeData> toOfficeOptions,
|
||||
final Collection<ClientData> toClientOptions, final Collection<EnumOptionData> toAccountTypeOptions,
|
||||
final Collection<PortfolioAccountData> toAccountOptions, final Collection<EnumOptionData> transferTypeOptions,
|
||||
final Collection<EnumOptionData> statusOptions, final Collection<EnumOptionData> instructionTypeOptions,
|
||||
final Collection<EnumOptionData> priorityOptions, final Collection<EnumOptionData> recurrenceTypeOptions,
|
||||
final Collection<EnumOptionData> recurrenceFrequencyOptions) {
|
||||
|
||||
final Long id = null;
|
||||
final Long accountDetailId = null;
|
||||
final String name = null;
|
||||
final OfficeData fromOffice = null;
|
||||
final OfficeData toOffice = null;
|
||||
final ClientData fromClient = null;
|
||||
final ClientData toClient = null;
|
||||
final EnumOptionData fromAccountType = null;
|
||||
final PortfolioAccountData fromAccount = null;
|
||||
final EnumOptionData toAccountType = null;
|
||||
final PortfolioAccountData toAccount = null;
|
||||
final EnumOptionData transferType = null;
|
||||
final EnumOptionData priority = null;
|
||||
final EnumOptionData instructionType = null;
|
||||
final EnumOptionData status = null;
|
||||
final BigDecimal amount = null;
|
||||
final LocalDate validFrom = null;
|
||||
final LocalDate validTill = null;
|
||||
final EnumOptionData recurrenceType = null;
|
||||
final EnumOptionData recurrenceFrequency = null;
|
||||
final Integer recurrenceInterval = null;
|
||||
final MonthDay recurrenceOnMonthDay = null;
|
||||
final Page<AccountTransferData> transactions = null;
|
||||
|
||||
return new StandingInstructionData(id, accountDetailId, name, fromOffice, fromClient, fromAccountType, fromAccount, toOffice,
|
||||
toClient, toAccountType, toAccount, transferType, priority, instructionType, status, amount, validFrom, validTill,
|
||||
recurrenceType, recurrenceFrequency, recurrenceInterval, recurrenceOnMonthDay, transactions, fromOfficeOptions,
|
||||
fromClientOptions, fromAccountTypeOptions, fromAccountOptions, toOfficeOptions, toClientOptions, toAccountTypeOptions,
|
||||
toAccountOptions, transferTypeOptions, statusOptions, instructionTypeOptions, priorityOptions, recurrenceTypeOptions,
|
||||
recurrenceFrequencyOptions);
|
||||
}
|
||||
|
||||
public static StandingInstructionData instance(final Long id, final Long accountDetailId, final String name,
|
||||
final OfficeData fromOffice, final OfficeData toOffice, final ClientData fromClient, final ClientData toClient,
|
||||
final EnumOptionData fromAccountType, final PortfolioAccountData fromAccount, final EnumOptionData toAccountType,
|
||||
final PortfolioAccountData toAccount, final EnumOptionData transferType, final EnumOptionData priority,
|
||||
final EnumOptionData instructionType, final EnumOptionData status, final BigDecimal amount, final LocalDate validFrom,
|
||||
final LocalDate validTill, final EnumOptionData recurrenceType, final EnumOptionData recurrenceFrequency,
|
||||
final Integer recurrenceInterval, final MonthDay recurrenceOnMonthDay) {
|
||||
final Page<AccountTransferData> transactions = null;
|
||||
final Collection<OfficeData> fromOfficeOptions = null;
|
||||
final Collection<ClientData> fromClientOptions = null;
|
||||
final Collection<EnumOptionData> fromAccountTypeOptions = null;
|
||||
final Collection<PortfolioAccountData> fromAccountOptions = null;
|
||||
final Collection<OfficeData> toOfficeOptions = null;
|
||||
final Collection<ClientData> toClientOptions = null;
|
||||
final Collection<EnumOptionData> toAccountTypeOptions = null;
|
||||
final Collection<PortfolioAccountData> toAccountOptions = null;
|
||||
final Collection<EnumOptionData> transferTypeOptions = null;
|
||||
final Collection<EnumOptionData> statusOptions = null;
|
||||
final Collection<EnumOptionData> instructionTypeOptions = null;
|
||||
final Collection<EnumOptionData> priorityOptions = null;
|
||||
final Collection<EnumOptionData> recurrenceTypeOptions = null;
|
||||
final Collection<EnumOptionData> recurrenceFrequencyOptions = null;
|
||||
|
||||
return new StandingInstructionData(id, accountDetailId, name, fromOffice, fromClient, fromAccountType, fromAccount, toOffice,
|
||||
toClient, toAccountType, toAccount, transferType, priority, instructionType, status, amount, validFrom, validTill,
|
||||
recurrenceType, recurrenceFrequency, recurrenceInterval, recurrenceOnMonthDay, transactions, fromOfficeOptions,
|
||||
fromClientOptions, fromAccountTypeOptions, fromAccountOptions, toOfficeOptions, toClientOptions, toAccountTypeOptions,
|
||||
toAccountOptions, transferTypeOptions, statusOptions, instructionTypeOptions, priorityOptions, recurrenceTypeOptions,
|
||||
recurrenceFrequencyOptions);
|
||||
}
|
||||
|
||||
public static StandingInstructionData withTemplateData(StandingInstructionData instructionData, StandingInstructionData templateData) {
|
||||
return new StandingInstructionData(instructionData.id, instructionData.accountDetailId, instructionData.name,
|
||||
instructionData.fromOffice, instructionData.fromClient, instructionData.fromAccountType, instructionData.fromAccount,
|
||||
instructionData.toOffice, instructionData.toClient, instructionData.toAccountType, instructionData.toAccount,
|
||||
instructionData.transferType, instructionData.priority, instructionData.instructionType, instructionData.status,
|
||||
instructionData.amount, instructionData.validFrom, instructionData.validTill, instructionData.recurrenceType,
|
||||
instructionData.recurrenceFrequency, instructionData.recurrenceInterval, instructionData.recurrenceOnMonthDay,
|
||||
instructionData.transactions, templateData.fromOfficeOptions, templateData.fromClientOptions,
|
||||
templateData.fromAccountTypeOptions, templateData.fromAccountOptions, templateData.toOfficeOptions,
|
||||
templateData.toClientOptions, templateData.toAccountTypeOptions, templateData.toAccountOptions,
|
||||
templateData.transferTypeOptions, templateData.statusOptions, templateData.instructionTypeOptions,
|
||||
templateData.priorityOptions, templateData.recurrenceTypeOptions, templateData.recurrenceFrequencyOptions);
|
||||
}
|
||||
|
||||
private StandingInstructionData(final Long id, final Long accountDetailId, final String name, final OfficeData fromOffice,
|
||||
final ClientData fromClient, final EnumOptionData fromAccountType, final PortfolioAccountData fromAccount,
|
||||
final OfficeData toOffice, final ClientData toClient, final EnumOptionData toAccountType, final PortfolioAccountData toAccount,
|
||||
final EnumOptionData transferType, final EnumOptionData priority, final EnumOptionData instructionType,
|
||||
final EnumOptionData status, final BigDecimal amount, final LocalDate validFrom, LocalDate validTill,
|
||||
final EnumOptionData recurrenceType, final EnumOptionData recurrenceFrequency, final Integer recurrenceInterval,
|
||||
final MonthDay recurrenceOnMonthDay, final Page<AccountTransferData> transactions,
|
||||
final Collection<OfficeData> fromOfficeOptions, final Collection<ClientData> fromClientOptions,
|
||||
final Collection<EnumOptionData> fromAccountTypeOptions, final Collection<PortfolioAccountData> fromAccountOptions,
|
||||
final Collection<OfficeData> toOfficeOptions, final Collection<ClientData> toClientOptions,
|
||||
final Collection<EnumOptionData> toAccountTypeOptions, final Collection<PortfolioAccountData> toAccountOptions,
|
||||
final Collection<EnumOptionData> transferTypeOptions, final Collection<EnumOptionData> statusOptions,
|
||||
final Collection<EnumOptionData> instructionTypeOptions, final Collection<EnumOptionData> priorityOptions,
|
||||
final Collection<EnumOptionData> recurrenceTypeOptions, final Collection<EnumOptionData> recurrenceFrequencyOptions) {
|
||||
this.id = id;
|
||||
this.accountDetailId = accountDetailId;
|
||||
this.name = name;
|
||||
this.fromOffice = fromOffice;
|
||||
this.fromClient = fromClient;
|
||||
this.fromAccountType = fromAccountType;
|
||||
this.fromAccount = fromAccount;
|
||||
this.toOffice = toOffice;
|
||||
this.toClient = toClient;
|
||||
this.toAccountType = toAccountType;
|
||||
this.toAccount = toAccount;
|
||||
this.transferType = transferType;
|
||||
|
||||
this.priority = priority;
|
||||
this.instructionType = instructionType;
|
||||
this.status = status;
|
||||
this.amount = amount;
|
||||
this.validFrom = validFrom;
|
||||
this.validTill = validTill;
|
||||
this.recurrenceType = recurrenceType;
|
||||
this.recurrenceFrequency = recurrenceFrequency;
|
||||
this.recurrenceInterval = recurrenceInterval;
|
||||
this.recurrenceOnMonthDay = recurrenceOnMonthDay;
|
||||
|
||||
this.fromOfficeOptions = fromOfficeOptions;
|
||||
this.fromClientOptions = fromClientOptions;
|
||||
this.fromAccountTypeOptions = fromAccountTypeOptions;
|
||||
this.fromAccountOptions = fromAccountOptions;
|
||||
this.toOfficeOptions = toOfficeOptions;
|
||||
this.toClientOptions = toClientOptions;
|
||||
this.toAccountTypeOptions = toAccountTypeOptions;
|
||||
this.toAccountOptions = toAccountOptions;
|
||||
this.transferTypeOptions = transferTypeOptions;
|
||||
this.statusOptions = statusOptions;
|
||||
this.instructionTypeOptions = instructionTypeOptions;
|
||||
this.priorityOptions = priorityOptions;
|
||||
this.recurrenceTypeOptions = recurrenceTypeOptions;
|
||||
this.recurrenceFrequencyOptions = recurrenceFrequencyOptions;
|
||||
this.transactions = transactions;
|
||||
}
|
||||
|
||||
public static StandingInstructionData template(OfficeData fromOffice, ClientData fromClient, EnumOptionData fromAccountType,
|
||||
PortfolioAccountData fromAccount, LocalDate transferDate, OfficeData toOffice, ClientData toClient,
|
||||
EnumOptionData toAccountType, PortfolioAccountData toAccount, final Collection<OfficeData> fromOfficeOptions,
|
||||
final Collection<ClientData> fromClientOptions, final Collection<EnumOptionData> fromAccountTypeOptions,
|
||||
final Collection<PortfolioAccountData> fromAccountOptions, final Collection<OfficeData> toOfficeOptions,
|
||||
final Collection<ClientData> toClientOptions, final Collection<EnumOptionData> toAccountTypeOptions,
|
||||
final Collection<PortfolioAccountData> toAccountOptions, final Collection<EnumOptionData> transferTypeOptions,
|
||||
final Collection<EnumOptionData> statusOptions, final Collection<EnumOptionData> instructionTypeOptions,
|
||||
final Collection<EnumOptionData> priorityOptions, final Collection<EnumOptionData> recurrenceTypeOptions,
|
||||
final Collection<EnumOptionData> recurrenceFrequencyOptions) {
|
||||
final Long id = null;
|
||||
final Long accountDetailId = null;
|
||||
final String name = null;
|
||||
final EnumOptionData transferType = null;
|
||||
final EnumOptionData priority = null;
|
||||
final EnumOptionData instructionType = null;
|
||||
final EnumOptionData status = null;
|
||||
final BigDecimal amount = null;
|
||||
final LocalDate validFrom = null;
|
||||
final LocalDate validTill = null;
|
||||
final EnumOptionData recurrenceType = null;
|
||||
final EnumOptionData recurrenceFrequency = null;
|
||||
final Integer recurrenceInterval = null;
|
||||
final MonthDay recurrenceOnMonthDay = null;
|
||||
final Page<AccountTransferData> transactions = null;
|
||||
|
||||
return new StandingInstructionData(id, accountDetailId, name, fromOffice, fromClient, fromAccountType, fromAccount, toOffice,
|
||||
toClient, toAccountType, toAccount, transferType, priority, instructionType, status, amount, validFrom, validTill,
|
||||
recurrenceType, recurrenceFrequency, recurrenceInterval, recurrenceOnMonthDay, transactions, fromOfficeOptions,
|
||||
fromClientOptions, fromAccountTypeOptions, fromAccountOptions, toOfficeOptions, toClientOptions, toAccountTypeOptions,
|
||||
toAccountOptions, transferTypeOptions, statusOptions, instructionTypeOptions, priorityOptions, recurrenceTypeOptions,
|
||||
recurrenceFrequencyOptions);
|
||||
}
|
||||
|
||||
public static StandingInstructionData withTransferData(StandingInstructionData instructionData,
|
||||
final Page<AccountTransferData> transactions) {
|
||||
return new StandingInstructionData(instructionData.id, instructionData.accountDetailId, instructionData.name,
|
||||
instructionData.fromOffice, instructionData.fromClient, instructionData.fromAccountType, instructionData.fromAccount,
|
||||
instructionData.toOffice, instructionData.toClient, instructionData.toAccountType, instructionData.toAccount,
|
||||
instructionData.transferType, instructionData.priority, instructionData.instructionType, instructionData.status,
|
||||
instructionData.amount, instructionData.validFrom, instructionData.validTill, instructionData.recurrenceType,
|
||||
instructionData.recurrenceFrequency, instructionData.recurrenceInterval, instructionData.recurrenceOnMonthDay, transactions,
|
||||
instructionData.fromOfficeOptions, instructionData.fromClientOptions, instructionData.fromAccountTypeOptions,
|
||||
instructionData.fromAccountOptions, instructionData.toOfficeOptions, instructionData.toClientOptions,
|
||||
instructionData.toAccountTypeOptions, instructionData.toAccountOptions, instructionData.transferTypeOptions,
|
||||
instructionData.statusOptions, instructionData.instructionTypeOptions, instructionData.priorityOptions,
|
||||
instructionData.recurrenceTypeOptions, instructionData.recurrenceFrequencyOptions);
|
||||
}
|
||||
|
||||
public StandingInstructionType getInstructionType() {
|
||||
return Optional.ofNullable(this.instructionType).map(e -> StandingInstructionType.fromInt(e.getId().intValue())).orElse(null);
|
||||
|
||||
}
|
||||
|
||||
public AccountTransferRecurrenceType getRecurrenceType() {
|
||||
return Optional.ofNullable(this.recurrenceType).map(e -> AccountTransferRecurrenceType.fromInt(e.getId().intValue())).orElse(null);
|
||||
}
|
||||
|
||||
public PeriodFrequencyType getRecurrenceFrequency() {
|
||||
return Optional.ofNullable(this.recurrenceFrequency).map(e -> PeriodFrequencyType.fromInt(e.getId().intValue())).orElse(null);
|
||||
}
|
||||
|
||||
public PortfolioAccountType getFromAccountType() {
|
||||
return Optional.ofNullable(this.fromAccountType).map(e -> PortfolioAccountType.fromInt(e.getId().intValue())).orElse(null);
|
||||
}
|
||||
|
||||
public PortfolioAccountType getToAccountType() {
|
||||
return Optional.ofNullable(this.toAccountType).map(e -> PortfolioAccountType.fromInt(e.getId().intValue())).orElse(null);
|
||||
}
|
||||
|
||||
public AccountTransferType getTransferType() {
|
||||
return Optional.ofNullable(this.transferType).map(e -> AccountTransferType.fromInt(e.getId().intValue())).orElse(null);
|
||||
}
|
||||
|
||||
public Integer getRecurrenceOnDay() {
|
||||
return Optional.ofNullable(this.recurrenceOnMonthDay).map(monthDay -> monthDay.get(ChronoField.DAY_OF_MONTH)).orElse(0);
|
||||
}
|
||||
|
||||
public Integer getRecurrenceOnMonth() {
|
||||
return Optional.ofNullable(this.recurrenceOnMonthDay).map(monthDay -> monthDay.get(ChronoField.MONTH_OF_YEAR)).orElse(0);
|
||||
}
|
||||
|
||||
public Integer toTransferType() {
|
||||
Integer transferType = null;
|
||||
AccountTransferType accountTransferType = getTransferType();
|
||||
if (accountTransferType.isChargePayment()) {
|
||||
transferType = LoanTransactionType.CHARGE_PAYMENT.getValue();
|
||||
} else if (accountTransferType.isLoanRepayment()) {
|
||||
transferType = LoanTransactionType.REPAYMENT.getValue();
|
||||
}
|
||||
return transferType;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* 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.account.data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.MonthDay;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import lombok.Getter;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.service.Page;
|
||||
import org.apache.fineract.organisation.office.data.OfficeData;
|
||||
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferRecurrenceType;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferType;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionType;
|
||||
import org.apache.fineract.portfolio.client.data.ClientData;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType;
|
||||
|
||||
/**
|
||||
* Immutable data object representing a savings account.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public final class StandingInstructionData {
|
||||
|
||||
@Getter
|
||||
private final Long id;
|
||||
@Getter
|
||||
private final Long accountDetailId;
|
||||
@Getter
|
||||
private final String name;
|
||||
@Getter
|
||||
private final OfficeData fromOffice;
|
||||
@Getter
|
||||
private final ClientData fromClient;
|
||||
@Getter
|
||||
private final EnumOptionData fromAccountType;
|
||||
@Getter
|
||||
private final PortfolioAccountData fromAccount;
|
||||
@Getter
|
||||
private final OfficeData toOffice;
|
||||
@Getter
|
||||
private final ClientData toClient;
|
||||
@Getter
|
||||
private final EnumOptionData toAccountType;
|
||||
@Getter
|
||||
private final PortfolioAccountData toAccount;
|
||||
@Getter
|
||||
private final EnumOptionData transferType;
|
||||
@Getter
|
||||
private final EnumOptionData priority;
|
||||
@Getter
|
||||
private final EnumOptionData instructionType;
|
||||
@Getter
|
||||
private final EnumOptionData status;
|
||||
@Getter
|
||||
private final BigDecimal amount;
|
||||
@Getter
|
||||
private final LocalDate validFrom;
|
||||
@Getter
|
||||
private final LocalDate validTill;
|
||||
@Getter
|
||||
private final EnumOptionData recurrenceType;
|
||||
@Getter
|
||||
private final EnumOptionData recurrenceFrequency;
|
||||
@Getter
|
||||
private final Integer recurrenceInterval;
|
||||
@Getter
|
||||
private final MonthDay recurrenceOnMonthDay;
|
||||
@Getter
|
||||
private final Page<AccountTransferData> transactions;
|
||||
|
||||
@Getter
|
||||
private final Collection<OfficeData> fromOfficeOptions;
|
||||
@Getter
|
||||
private final Collection<ClientData> fromClientOptions;
|
||||
@Getter
|
||||
private final Collection<EnumOptionData> fromAccountTypeOptions;
|
||||
@Getter
|
||||
private final Collection<PortfolioAccountData> fromAccountOptions;
|
||||
@Getter
|
||||
private final Collection<OfficeData> toOfficeOptions;
|
||||
@Getter
|
||||
private final Collection<ClientData> toClientOptions;
|
||||
@Getter
|
||||
private final Collection<EnumOptionData> toAccountTypeOptions;
|
||||
@Getter
|
||||
private final Collection<PortfolioAccountData> toAccountOptions;
|
||||
@Getter
|
||||
private final Collection<EnumOptionData> transferTypeOptions;
|
||||
@Getter
|
||||
private final Collection<EnumOptionData> statusOptions;
|
||||
@Getter
|
||||
private final Collection<EnumOptionData> instructionTypeOptions;
|
||||
@Getter
|
||||
private final Collection<EnumOptionData> priorityOptions;
|
||||
@Getter
|
||||
private final Collection<EnumOptionData> recurrenceTypeOptions;
|
||||
@Getter
|
||||
private final Collection<EnumOptionData> recurrenceFrequencyOptions;
|
||||
|
||||
public static StandingInstructionData template(final Collection<OfficeData> fromOfficeOptions,
|
||||
final Collection<ClientData> fromClientOptions, final Collection<EnumOptionData> fromAccountTypeOptions,
|
||||
final Collection<PortfolioAccountData> fromAccountOptions, final Collection<OfficeData> toOfficeOptions,
|
||||
final Collection<ClientData> toClientOptions, final Collection<EnumOptionData> toAccountTypeOptions,
|
||||
final Collection<PortfolioAccountData> toAccountOptions, final Collection<EnumOptionData> transferTypeOptions,
|
||||
final Collection<EnumOptionData> statusOptions, final Collection<EnumOptionData> instructionTypeOptions,
|
||||
final Collection<EnumOptionData> priorityOptions, final Collection<EnumOptionData> recurrenceTypeOptions,
|
||||
final Collection<EnumOptionData> recurrenceFrequencyOptions) {
|
||||
|
||||
final Long id = null;
|
||||
final Long accountDetailId = null;
|
||||
final String name = null;
|
||||
final OfficeData fromOffice = null;
|
||||
final OfficeData toOffice = null;
|
||||
final ClientData fromClient = null;
|
||||
final ClientData toClient = null;
|
||||
final EnumOptionData fromAccountType = null;
|
||||
final PortfolioAccountData fromAccount = null;
|
||||
final EnumOptionData toAccountType = null;
|
||||
final PortfolioAccountData toAccount = null;
|
||||
final EnumOptionData transferType = null;
|
||||
final EnumOptionData priority = null;
|
||||
final EnumOptionData instructionType = null;
|
||||
final EnumOptionData status = null;
|
||||
final BigDecimal amount = null;
|
||||
final LocalDate validFrom = null;
|
||||
final LocalDate validTill = null;
|
||||
final EnumOptionData recurrenceType = null;
|
||||
final EnumOptionData recurrenceFrequency = null;
|
||||
final Integer recurrenceInterval = null;
|
||||
final MonthDay recurrenceOnMonthDay = null;
|
||||
final Page<AccountTransferData> transactions = null;
|
||||
|
||||
return new StandingInstructionData(id, accountDetailId, name, fromOffice, fromClient, fromAccountType, fromAccount, toOffice,
|
||||
toClient, toAccountType, toAccount, transferType, priority, instructionType, status, amount, validFrom, validTill,
|
||||
recurrenceType, recurrenceFrequency, recurrenceInterval, recurrenceOnMonthDay, transactions, fromOfficeOptions,
|
||||
fromClientOptions, fromAccountTypeOptions, fromAccountOptions, toOfficeOptions, toClientOptions, toAccountTypeOptions,
|
||||
toAccountOptions, transferTypeOptions, statusOptions, instructionTypeOptions, priorityOptions, recurrenceTypeOptions,
|
||||
recurrenceFrequencyOptions);
|
||||
}
|
||||
|
||||
public static StandingInstructionData instance(final Long id, final Long accountDetailId, final String name,
|
||||
final OfficeData fromOffice, final OfficeData toOffice, final ClientData fromClient, final ClientData toClient,
|
||||
final EnumOptionData fromAccountType, final PortfolioAccountData fromAccount, final EnumOptionData toAccountType,
|
||||
final PortfolioAccountData toAccount, final EnumOptionData transferType, final EnumOptionData priority,
|
||||
final EnumOptionData instructionType, final EnumOptionData status, final BigDecimal amount, final LocalDate validFrom,
|
||||
final LocalDate validTill, final EnumOptionData recurrenceType, final EnumOptionData recurrenceFrequency,
|
||||
final Integer recurrenceInterval, final MonthDay recurrenceOnMonthDay) {
|
||||
final Page<AccountTransferData> transactions = null;
|
||||
final Collection<OfficeData> fromOfficeOptions = null;
|
||||
final Collection<ClientData> fromClientOptions = null;
|
||||
final Collection<EnumOptionData> fromAccountTypeOptions = null;
|
||||
final Collection<PortfolioAccountData> fromAccountOptions = null;
|
||||
final Collection<OfficeData> toOfficeOptions = null;
|
||||
final Collection<ClientData> toClientOptions = null;
|
||||
final Collection<EnumOptionData> toAccountTypeOptions = null;
|
||||
final Collection<PortfolioAccountData> toAccountOptions = null;
|
||||
final Collection<EnumOptionData> transferTypeOptions = null;
|
||||
final Collection<EnumOptionData> statusOptions = null;
|
||||
final Collection<EnumOptionData> instructionTypeOptions = null;
|
||||
final Collection<EnumOptionData> priorityOptions = null;
|
||||
final Collection<EnumOptionData> recurrenceTypeOptions = null;
|
||||
final Collection<EnumOptionData> recurrenceFrequencyOptions = null;
|
||||
|
||||
return new StandingInstructionData(id, accountDetailId, name, fromOffice, fromClient, fromAccountType, fromAccount, toOffice,
|
||||
toClient, toAccountType, toAccount, transferType, priority, instructionType, status, amount, validFrom, validTill,
|
||||
recurrenceType, recurrenceFrequency, recurrenceInterval, recurrenceOnMonthDay, transactions, fromOfficeOptions,
|
||||
fromClientOptions, fromAccountTypeOptions, fromAccountOptions, toOfficeOptions, toClientOptions, toAccountTypeOptions,
|
||||
toAccountOptions, transferTypeOptions, statusOptions, instructionTypeOptions, priorityOptions, recurrenceTypeOptions,
|
||||
recurrenceFrequencyOptions);
|
||||
}
|
||||
|
||||
public static StandingInstructionData withTemplateData(StandingInstructionData instructionData, StandingInstructionData templateData) {
|
||||
return new StandingInstructionData(instructionData.id, instructionData.accountDetailId, instructionData.name,
|
||||
instructionData.fromOffice, instructionData.fromClient, instructionData.fromAccountType, instructionData.fromAccount,
|
||||
instructionData.toOffice, instructionData.toClient, instructionData.toAccountType, instructionData.toAccount,
|
||||
instructionData.transferType, instructionData.priority, instructionData.instructionType, instructionData.status,
|
||||
instructionData.amount, instructionData.validFrom, instructionData.validTill, instructionData.recurrenceType,
|
||||
instructionData.recurrenceFrequency, instructionData.recurrenceInterval, instructionData.recurrenceOnMonthDay,
|
||||
instructionData.transactions, templateData.fromOfficeOptions, templateData.fromClientOptions,
|
||||
templateData.fromAccountTypeOptions, templateData.fromAccountOptions, templateData.toOfficeOptions,
|
||||
templateData.toClientOptions, templateData.toAccountTypeOptions, templateData.toAccountOptions,
|
||||
templateData.transferTypeOptions, templateData.statusOptions, templateData.instructionTypeOptions,
|
||||
templateData.priorityOptions, templateData.recurrenceTypeOptions, templateData.recurrenceFrequencyOptions);
|
||||
}
|
||||
|
||||
private StandingInstructionData(final Long id, final Long accountDetailId, final String name, final OfficeData fromOffice,
|
||||
final ClientData fromClient, final EnumOptionData fromAccountType, final PortfolioAccountData fromAccount,
|
||||
final OfficeData toOffice, final ClientData toClient, final EnumOptionData toAccountType, final PortfolioAccountData toAccount,
|
||||
final EnumOptionData transferType, final EnumOptionData priority, final EnumOptionData instructionType,
|
||||
final EnumOptionData status, final BigDecimal amount, final LocalDate validFrom, LocalDate validTill,
|
||||
final EnumOptionData recurrenceType, final EnumOptionData recurrenceFrequency, final Integer recurrenceInterval,
|
||||
final MonthDay recurrenceOnMonthDay, final Page<AccountTransferData> transactions,
|
||||
final Collection<OfficeData> fromOfficeOptions, final Collection<ClientData> fromClientOptions,
|
||||
final Collection<EnumOptionData> fromAccountTypeOptions, final Collection<PortfolioAccountData> fromAccountOptions,
|
||||
final Collection<OfficeData> toOfficeOptions, final Collection<ClientData> toClientOptions,
|
||||
final Collection<EnumOptionData> toAccountTypeOptions, final Collection<PortfolioAccountData> toAccountOptions,
|
||||
final Collection<EnumOptionData> transferTypeOptions, final Collection<EnumOptionData> statusOptions,
|
||||
final Collection<EnumOptionData> instructionTypeOptions, final Collection<EnumOptionData> priorityOptions,
|
||||
final Collection<EnumOptionData> recurrenceTypeOptions, final Collection<EnumOptionData> recurrenceFrequencyOptions) {
|
||||
this.id = id;
|
||||
this.accountDetailId = accountDetailId;
|
||||
this.name = name;
|
||||
this.fromOffice = fromOffice;
|
||||
this.fromClient = fromClient;
|
||||
this.fromAccountType = fromAccountType;
|
||||
this.fromAccount = fromAccount;
|
||||
this.toOffice = toOffice;
|
||||
this.toClient = toClient;
|
||||
this.toAccountType = toAccountType;
|
||||
this.toAccount = toAccount;
|
||||
this.transferType = transferType;
|
||||
|
||||
this.priority = priority;
|
||||
this.instructionType = instructionType;
|
||||
this.status = status;
|
||||
this.amount = amount;
|
||||
this.validFrom = validFrom;
|
||||
this.validTill = validTill;
|
||||
this.recurrenceType = recurrenceType;
|
||||
this.recurrenceFrequency = recurrenceFrequency;
|
||||
this.recurrenceInterval = recurrenceInterval;
|
||||
this.recurrenceOnMonthDay = recurrenceOnMonthDay;
|
||||
|
||||
this.fromOfficeOptions = fromOfficeOptions;
|
||||
this.fromClientOptions = fromClientOptions;
|
||||
this.fromAccountTypeOptions = fromAccountTypeOptions;
|
||||
this.fromAccountOptions = fromAccountOptions;
|
||||
this.toOfficeOptions = toOfficeOptions;
|
||||
this.toClientOptions = toClientOptions;
|
||||
this.toAccountTypeOptions = toAccountTypeOptions;
|
||||
this.toAccountOptions = toAccountOptions;
|
||||
this.transferTypeOptions = transferTypeOptions;
|
||||
this.statusOptions = statusOptions;
|
||||
this.instructionTypeOptions = instructionTypeOptions;
|
||||
this.priorityOptions = priorityOptions;
|
||||
this.recurrenceTypeOptions = recurrenceTypeOptions;
|
||||
this.recurrenceFrequencyOptions = recurrenceFrequencyOptions;
|
||||
this.transactions = transactions;
|
||||
}
|
||||
|
||||
public static StandingInstructionData template(OfficeData fromOffice, ClientData fromClient, EnumOptionData fromAccountType,
|
||||
PortfolioAccountData fromAccount, LocalDate transferDate, OfficeData toOffice, ClientData toClient,
|
||||
EnumOptionData toAccountType, PortfolioAccountData toAccount, final Collection<OfficeData> fromOfficeOptions,
|
||||
final Collection<ClientData> fromClientOptions, final Collection<EnumOptionData> fromAccountTypeOptions,
|
||||
final Collection<PortfolioAccountData> fromAccountOptions, final Collection<OfficeData> toOfficeOptions,
|
||||
final Collection<ClientData> toClientOptions, final Collection<EnumOptionData> toAccountTypeOptions,
|
||||
final Collection<PortfolioAccountData> toAccountOptions, final Collection<EnumOptionData> transferTypeOptions,
|
||||
final Collection<EnumOptionData> statusOptions, final Collection<EnumOptionData> instructionTypeOptions,
|
||||
final Collection<EnumOptionData> priorityOptions, final Collection<EnumOptionData> recurrenceTypeOptions,
|
||||
final Collection<EnumOptionData> recurrenceFrequencyOptions) {
|
||||
final Long id = null;
|
||||
final Long accountDetailId = null;
|
||||
final String name = null;
|
||||
final EnumOptionData transferType = null;
|
||||
final EnumOptionData priority = null;
|
||||
final EnumOptionData instructionType = null;
|
||||
final EnumOptionData status = null;
|
||||
final BigDecimal amount = null;
|
||||
final LocalDate validFrom = null;
|
||||
final LocalDate validTill = null;
|
||||
final EnumOptionData recurrenceType = null;
|
||||
final EnumOptionData recurrenceFrequency = null;
|
||||
final Integer recurrenceInterval = null;
|
||||
final MonthDay recurrenceOnMonthDay = null;
|
||||
final Page<AccountTransferData> transactions = null;
|
||||
|
||||
return new StandingInstructionData(id, accountDetailId, name, fromOffice, fromClient, fromAccountType, fromAccount, toOffice,
|
||||
toClient, toAccountType, toAccount, transferType, priority, instructionType, status, amount, validFrom, validTill,
|
||||
recurrenceType, recurrenceFrequency, recurrenceInterval, recurrenceOnMonthDay, transactions, fromOfficeOptions,
|
||||
fromClientOptions, fromAccountTypeOptions, fromAccountOptions, toOfficeOptions, toClientOptions, toAccountTypeOptions,
|
||||
toAccountOptions, transferTypeOptions, statusOptions, instructionTypeOptions, priorityOptions, recurrenceTypeOptions,
|
||||
recurrenceFrequencyOptions);
|
||||
}
|
||||
|
||||
public static StandingInstructionData withTransferData(StandingInstructionData instructionData,
|
||||
final Page<AccountTransferData> transactions) {
|
||||
return new StandingInstructionData(instructionData.id, instructionData.accountDetailId, instructionData.name,
|
||||
instructionData.fromOffice, instructionData.fromClient, instructionData.fromAccountType, instructionData.fromAccount,
|
||||
instructionData.toOffice, instructionData.toClient, instructionData.toAccountType, instructionData.toAccount,
|
||||
instructionData.transferType, instructionData.priority, instructionData.instructionType, instructionData.status,
|
||||
instructionData.amount, instructionData.validFrom, instructionData.validTill, instructionData.recurrenceType,
|
||||
instructionData.recurrenceFrequency, instructionData.recurrenceInterval, instructionData.recurrenceOnMonthDay, transactions,
|
||||
instructionData.fromOfficeOptions, instructionData.fromClientOptions, instructionData.fromAccountTypeOptions,
|
||||
instructionData.fromAccountOptions, instructionData.toOfficeOptions, instructionData.toClientOptions,
|
||||
instructionData.toAccountTypeOptions, instructionData.toAccountOptions, instructionData.transferTypeOptions,
|
||||
instructionData.statusOptions, instructionData.instructionTypeOptions, instructionData.priorityOptions,
|
||||
instructionData.recurrenceTypeOptions, instructionData.recurrenceFrequencyOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the domain enum for instruction type — used internally by business logic.
|
||||
* NOTE: renamed from getInstructionType() to avoid overriding Lombok @Getter (which must
|
||||
* return EnumOptionData so Jackson serializes it as an object, not a plain string).
|
||||
*/
|
||||
public StandingInstructionType instructionTypeEnum() {
|
||||
return Optional.ofNullable(this.instructionType).map(e -> StandingInstructionType.fromInt(e.getId().intValue())).orElse(null);
|
||||
}
|
||||
|
||||
public AccountTransferRecurrenceType recurrenceTypeEnum() {
|
||||
return Optional.ofNullable(this.recurrenceType).map(e -> AccountTransferRecurrenceType.fromInt(e.getId().intValue())).orElse(null);
|
||||
}
|
||||
|
||||
public PeriodFrequencyType recurrenceFrequencyEnum() {
|
||||
return Optional.ofNullable(this.recurrenceFrequency).map(e -> PeriodFrequencyType.fromInt(e.getId().intValue())).orElse(null);
|
||||
}
|
||||
|
||||
public PortfolioAccountType fromAccountTypeEnum() {
|
||||
return Optional.ofNullable(this.fromAccountType).map(e -> PortfolioAccountType.fromInt(e.getId().intValue())).orElse(null);
|
||||
}
|
||||
|
||||
public PortfolioAccountType toAccountTypeEnum() {
|
||||
return Optional.ofNullable(this.toAccountType).map(e -> PortfolioAccountType.fromInt(e.getId().intValue())).orElse(null);
|
||||
}
|
||||
|
||||
public AccountTransferType transferTypeEnum() {
|
||||
return Optional.ofNullable(this.transferType).map(e -> AccountTransferType.fromInt(e.getId().intValue())).orElse(null);
|
||||
}
|
||||
|
||||
public Integer getRecurrenceOnDay() {
|
||||
return Optional.ofNullable(this.recurrenceOnMonthDay).map(monthDay -> monthDay.get(ChronoField.DAY_OF_MONTH)).orElse(0);
|
||||
}
|
||||
|
||||
public Integer getRecurrenceOnMonth() {
|
||||
return Optional.ofNullable(this.recurrenceOnMonthDay).map(monthDay -> monthDay.get(ChronoField.MONTH_OF_YEAR)).orElse(0);
|
||||
}
|
||||
|
||||
public Integer toTransferType() {
|
||||
Integer transferType = null;
|
||||
AccountTransferType accountTransferType = transferTypeEnum();
|
||||
if (accountTransferType != null && accountTransferType.isChargePayment()) {
|
||||
transferType = LoanTransactionType.CHARGE_PAYMENT.getValue();
|
||||
} else if (accountTransferType != null && accountTransferType.isLoanRepayment()) {
|
||||
transferType = LoanTransactionType.REPAYMENT.getValue();
|
||||
}
|
||||
return transferType;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+296
-294
@@ -1,294 +1,296 @@
|
||||
/**
|
||||
* 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.account.data;
|
||||
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.fromAccountTypeParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.toAccountTypeParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.transferTypeParamName;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.MonthDay;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
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.AccountDetailConstants;
|
||||
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
||||
import org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferRecurrenceType;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferType;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionType;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class StandingInstructionDataValidator {
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
private final AccountTransfersDetailDataValidator accountTransfersDetailDataValidator;
|
||||
private static final Set<String> CREATE_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(AccountDetailConstants.localeParamName,
|
||||
AccountDetailConstants.dateFormatParamName, AccountDetailConstants.fromOfficeIdParamName,
|
||||
AccountDetailConstants.fromClientIdParamName, AccountDetailConstants.fromAccountTypeParamName,
|
||||
AccountDetailConstants.fromAccountIdParamName, AccountDetailConstants.toOfficeIdParamName,
|
||||
AccountDetailConstants.toClientIdParamName, AccountDetailConstants.toAccountTypeParamName,
|
||||
AccountDetailConstants.toAccountIdParamName, AccountDetailConstants.transferTypeParamName,
|
||||
StandingInstructionApiConstants.priorityParamName, StandingInstructionApiConstants.instructionTypeParamName,
|
||||
StandingInstructionApiConstants.statusParamName, StandingInstructionApiConstants.amountParamName,
|
||||
StandingInstructionApiConstants.validFromParamName, StandingInstructionApiConstants.validTillParamName,
|
||||
StandingInstructionApiConstants.recurrenceTypeParamName, StandingInstructionApiConstants.recurrenceFrequencyParamName,
|
||||
StandingInstructionApiConstants.recurrenceIntervalParamName, StandingInstructionApiConstants.recurrenceOnMonthDayParamName,
|
||||
StandingInstructionApiConstants.nameParamName, StandingInstructionApiConstants.monthDayFormatParamName));
|
||||
|
||||
private static final Set<String> UPDATE_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(AccountDetailConstants.localeParamName,
|
||||
AccountDetailConstants.dateFormatParamName, StandingInstructionApiConstants.priorityParamName,
|
||||
StandingInstructionApiConstants.instructionTypeParamName, StandingInstructionApiConstants.statusParamName,
|
||||
StandingInstructionApiConstants.amountParamName, StandingInstructionApiConstants.validFromParamName,
|
||||
StandingInstructionApiConstants.validTillParamName, StandingInstructionApiConstants.recurrenceTypeParamName,
|
||||
StandingInstructionApiConstants.recurrenceFrequencyParamName, StandingInstructionApiConstants.recurrenceIntervalParamName,
|
||||
StandingInstructionApiConstants.recurrenceOnMonthDayParamName, StandingInstructionApiConstants.monthDayFormatParamName));
|
||||
|
||||
@Autowired
|
||||
public StandingInstructionDataValidator(final FromJsonHelper fromApiJsonHelper,
|
||||
final AccountTransfersDetailDataValidator accountTransfersDetailDataValidator) {
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
this.accountTransfersDetailDataValidator = accountTransfersDetailDataValidator;
|
||||
}
|
||||
|
||||
public void validateForCreate(final JsonCommand command) {
|
||||
final String json = command.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(StandingInstructionApiConstants.STANDING_INSTRUCTION_RESOURCE_NAME);
|
||||
this.accountTransfersDetailDataValidator.validate(command, baseDataValidator);
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
|
||||
final Integer status = this.fromApiJsonHelper.extractIntegerNamed(StandingInstructionApiConstants.statusParamName, element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.statusParamName).value(status).notNull().inMinMaxRange(1, 2);
|
||||
|
||||
final LocalDate validFrom = this.fromApiJsonHelper.extractLocalDateNamed(StandingInstructionApiConstants.validFromParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.validFromParamName).value(validFrom).notNull();
|
||||
|
||||
final LocalDate validTill = this.fromApiJsonHelper.extractLocalDateNamed(StandingInstructionApiConstants.validTillParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.validTillParamName).value(validTill)
|
||||
.validateDateAfter(validFrom);
|
||||
|
||||
final BigDecimal transferAmount = this.fromApiJsonHelper
|
||||
.extractBigDecimalWithLocaleNamed(StandingInstructionApiConstants.amountParamName, element);
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.amountParamName).value(transferAmount).positiveAmount();
|
||||
|
||||
final Integer transferType = this.fromApiJsonHelper.extractIntegerNamed(transferTypeParamName, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(transferTypeParamName).value(transferType).notNull().inMinMaxRange(1, 3);
|
||||
|
||||
final Integer priority = this.fromApiJsonHelper.extractIntegerNamed(StandingInstructionApiConstants.priorityParamName, element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.priorityParamName).value(priority).notNull().inMinMaxRange(1,
|
||||
4);
|
||||
|
||||
final Integer standingInstructionType = this.fromApiJsonHelper
|
||||
.extractIntegerNamed(StandingInstructionApiConstants.instructionTypeParamName, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.instructionTypeParamName).value(standingInstructionType)
|
||||
.notNull().inMinMaxRange(1, 2);
|
||||
|
||||
final Integer recurrenceType = this.fromApiJsonHelper.extractIntegerNamed(StandingInstructionApiConstants.recurrenceTypeParamName,
|
||||
element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceTypeParamName).value(recurrenceType).notNull()
|
||||
.inMinMaxRange(1, 2);
|
||||
boolean isPeriodic = false;
|
||||
if (recurrenceType != null) {
|
||||
isPeriodic = AccountTransferRecurrenceType.fromInt(recurrenceType).isPeriodicRecurrence();
|
||||
}
|
||||
|
||||
final Integer recurrenceFrequency = this.fromApiJsonHelper
|
||||
.extractIntegerNamed(StandingInstructionApiConstants.recurrenceFrequencyParamName, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceFrequencyParamName).value(recurrenceFrequency)
|
||||
.inMinMaxRange(0, 3);
|
||||
|
||||
if (recurrenceFrequency != null) {
|
||||
PeriodFrequencyType frequencyType = PeriodFrequencyType.fromInt(recurrenceFrequency);
|
||||
if (frequencyType.isMonthly() || frequencyType.isYearly()) {
|
||||
final MonthDay monthDay = this.fromApiJsonHelper
|
||||
.extractMonthDayNamed(StandingInstructionApiConstants.recurrenceOnMonthDayParamName, element);
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceOnMonthDayParamName).value(monthDay)
|
||||
.notNull();
|
||||
}
|
||||
}
|
||||
|
||||
final Integer recurrenceInterval = this.fromApiJsonHelper
|
||||
.extractIntegerNamed(StandingInstructionApiConstants.recurrenceIntervalParamName, element, Locale.getDefault());
|
||||
if (isPeriodic) {
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceIntervalParamName).value(recurrenceInterval)
|
||||
.notNull();
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceFrequencyParamName).value(recurrenceFrequency)
|
||||
.notNull();
|
||||
}
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceIntervalParamName).value(recurrenceInterval)
|
||||
.integerGreaterThanZero();
|
||||
|
||||
final String name = this.fromApiJsonHelper.extractStringNamed(StandingInstructionApiConstants.nameParamName, element);
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.nameParamName).value(name).notNull();
|
||||
|
||||
final Integer toAccountType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(toAccountTypeParamName, element);
|
||||
if (toAccountType != null && PortfolioAccountType.fromInt(toAccountType).isSavingsAccount()) {
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.instructionTypeParamName).value(standingInstructionType)
|
||||
.notNull().inMinMaxRange(1, 1);
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceTypeParamName).value(recurrenceType).notNull()
|
||||
.inMinMaxRange(1, 1);
|
||||
|
||||
}
|
||||
if (standingInstructionType != null && StandingInstructionType.fromInt(standingInstructionType).isFixedAmoutTransfer()) {
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.amountParamName).value(transferAmount).notNull();
|
||||
}
|
||||
|
||||
String errorCode = null;
|
||||
AccountTransferType accountTransferType = AccountTransferType.fromInt(transferType);
|
||||
final Integer fromAccountType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(fromAccountTypeParamName, element);
|
||||
if (fromAccountType != null && toAccountType != null) {
|
||||
PortfolioAccountType fromPortfolioAccountType = PortfolioAccountType.fromInt(fromAccountType);
|
||||
PortfolioAccountType toPortfolioAccountType = PortfolioAccountType.fromInt(toAccountType);
|
||||
if (accountTransferType.isAccountTransfer()
|
||||
&& (fromPortfolioAccountType.isLoanAccount() || toPortfolioAccountType.isLoanAccount())) {
|
||||
errorCode = "not.account.transfer";
|
||||
} else if (accountTransferType.isLoanRepayment()
|
||||
&& (fromPortfolioAccountType.isLoanAccount() || toPortfolioAccountType.isSavingsAccount())) {
|
||||
errorCode = "not.loan.repayment";
|
||||
}
|
||||
if (errorCode != null) {
|
||||
baseDataValidator.reset().parameter(transferTypeParamName).failWithCode(errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
public void validateForUpdate(final JsonCommand command) {
|
||||
final String json = command.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(StandingInstructionApiConstants.STANDING_INSTRUCTION_RESOURCE_NAME);
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.validFromParamName, element)) {
|
||||
final LocalDate validFrom = this.fromApiJsonHelper.extractLocalDateNamed(StandingInstructionApiConstants.validFromParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.validFromParamName).value(validFrom).notNull();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.validTillParamName, element)) {
|
||||
final LocalDate validTill = this.fromApiJsonHelper.extractLocalDateNamed(StandingInstructionApiConstants.validTillParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.validTillParamName).value(validTill).notNull();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.amountParamName, element)) {
|
||||
final BigDecimal transferAmount = this.fromApiJsonHelper
|
||||
.extractBigDecimalWithLocaleNamed(StandingInstructionApiConstants.amountParamName, element);
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.amountParamName).value(transferAmount).positiveAmount();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.statusParamName, element)) {
|
||||
final Integer status = this.fromApiJsonHelper.extractIntegerNamed(StandingInstructionApiConstants.statusParamName, element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.statusParamName).value(status).notNull().inMinMaxRange(1,
|
||||
2);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.priorityParamName, element)) {
|
||||
final Integer priority = this.fromApiJsonHelper.extractIntegerNamed(StandingInstructionApiConstants.priorityParamName, element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.priorityParamName).value(priority).notNull()
|
||||
.inMinMaxRange(1, 4);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.instructionTypeParamName, element)) {
|
||||
final Integer standingInstructionType = this.fromApiJsonHelper
|
||||
.extractIntegerNamed(StandingInstructionApiConstants.instructionTypeParamName, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.instructionTypeParamName).value(standingInstructionType)
|
||||
.notNull().inMinMaxRange(1, 2);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.recurrenceTypeParamName, element)) {
|
||||
final Integer recurrenceType = this.fromApiJsonHelper
|
||||
.extractIntegerNamed(StandingInstructionApiConstants.recurrenceTypeParamName, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceTypeParamName).value(recurrenceType).notNull()
|
||||
.inMinMaxRange(1, 2);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.recurrenceFrequencyParamName, element)) {
|
||||
final Integer recurrenceFrequency = this.fromApiJsonHelper
|
||||
.extractIntegerNamed(StandingInstructionApiConstants.recurrenceFrequencyParamName, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceFrequencyParamName).value(recurrenceFrequency)
|
||||
.inMinMaxRange(0, 3);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.recurrenceIntervalParamName, element)) {
|
||||
final Integer recurrenceInterval = this.fromApiJsonHelper
|
||||
.extractIntegerNamed(StandingInstructionApiConstants.recurrenceIntervalParamName, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceIntervalParamName).value(recurrenceInterval)
|
||||
.integerGreaterThanZero();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.nameParamName, element)) {
|
||||
final String name = this.fromApiJsonHelper.extractStringNamed(StandingInstructionApiConstants.nameParamName, element);
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.nameParamName).value(name).notNull();
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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.account.data;
|
||||
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.fromAccountTypeParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.toAccountTypeParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.transferTypeParamName;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.MonthDay;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
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.AccountDetailConstants;
|
||||
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
||||
import org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferRecurrenceType;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferType;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionType;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class StandingInstructionDataValidator {
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
private final AccountTransfersDetailDataValidator accountTransfersDetailDataValidator;
|
||||
private static final Set<String> CREATE_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(AccountDetailConstants.localeParamName,
|
||||
AccountDetailConstants.dateFormatParamName, AccountDetailConstants.fromOfficeIdParamName,
|
||||
AccountDetailConstants.fromClientIdParamName, AccountDetailConstants.fromAccountTypeParamName,
|
||||
AccountDetailConstants.fromAccountIdParamName, AccountDetailConstants.toOfficeIdParamName,
|
||||
AccountDetailConstants.toClientIdParamName, AccountDetailConstants.toAccountTypeParamName,
|
||||
AccountDetailConstants.toAccountIdParamName, AccountDetailConstants.transferTypeParamName,
|
||||
StandingInstructionApiConstants.priorityParamName, StandingInstructionApiConstants.instructionTypeParamName,
|
||||
StandingInstructionApiConstants.statusParamName, StandingInstructionApiConstants.amountParamName,
|
||||
StandingInstructionApiConstants.validFromParamName, StandingInstructionApiConstants.validTillParamName,
|
||||
StandingInstructionApiConstants.recurrenceTypeParamName, StandingInstructionApiConstants.recurrenceFrequencyParamName,
|
||||
StandingInstructionApiConstants.recurrenceIntervalParamName, StandingInstructionApiConstants.recurrenceOnMonthDayParamName,
|
||||
StandingInstructionApiConstants.nameParamName, StandingInstructionApiConstants.monthDayFormatParamName));
|
||||
|
||||
private static final Set<String> UPDATE_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(AccountDetailConstants.localeParamName,
|
||||
AccountDetailConstants.dateFormatParamName, StandingInstructionApiConstants.priorityParamName,
|
||||
StandingInstructionApiConstants.instructionTypeParamName, StandingInstructionApiConstants.statusParamName,
|
||||
StandingInstructionApiConstants.amountParamName, StandingInstructionApiConstants.validFromParamName,
|
||||
StandingInstructionApiConstants.validTillParamName, StandingInstructionApiConstants.recurrenceTypeParamName,
|
||||
StandingInstructionApiConstants.recurrenceFrequencyParamName, StandingInstructionApiConstants.recurrenceIntervalParamName,
|
||||
StandingInstructionApiConstants.recurrenceOnMonthDayParamName, StandingInstructionApiConstants.monthDayFormatParamName));
|
||||
|
||||
@Autowired
|
||||
public StandingInstructionDataValidator(final FromJsonHelper fromApiJsonHelper,
|
||||
final AccountTransfersDetailDataValidator accountTransfersDetailDataValidator) {
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
this.accountTransfersDetailDataValidator = accountTransfersDetailDataValidator;
|
||||
}
|
||||
|
||||
public void validateForCreate(final JsonCommand command) {
|
||||
final String json = command.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(StandingInstructionApiConstants.STANDING_INSTRUCTION_RESOURCE_NAME);
|
||||
this.accountTransfersDetailDataValidator.validate(command, baseDataValidator);
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
|
||||
final Integer status = this.fromApiJsonHelper.extractIntegerNamed(StandingInstructionApiConstants.statusParamName, element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.statusParamName).value(status).notNull().inMinMaxRange(1, 2);
|
||||
|
||||
final LocalDate validFrom = this.fromApiJsonHelper.extractLocalDateNamed(StandingInstructionApiConstants.validFromParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.validFromParamName).value(validFrom).notNull();
|
||||
|
||||
final LocalDate validTill = this.fromApiJsonHelper.extractLocalDateNamed(StandingInstructionApiConstants.validTillParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.validTillParamName).value(validTill)
|
||||
.validateDateAfter(validFrom);
|
||||
|
||||
final BigDecimal transferAmount = this.fromApiJsonHelper
|
||||
.extractBigDecimalWithLocaleNamed(StandingInstructionApiConstants.amountParamName, element);
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.amountParamName).value(transferAmount).positiveAmount();
|
||||
|
||||
final Integer transferType = this.fromApiJsonHelper.extractIntegerNamed(transferTypeParamName, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(transferTypeParamName).value(transferType).notNull().inMinMaxRange(1, 3);
|
||||
|
||||
final Integer priority = this.fromApiJsonHelper.extractIntegerNamed(StandingInstructionApiConstants.priorityParamName, element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.priorityParamName).value(priority).notNull().inMinMaxRange(1,
|
||||
4);
|
||||
|
||||
final Integer standingInstructionType = this.fromApiJsonHelper
|
||||
.extractIntegerNamed(StandingInstructionApiConstants.instructionTypeParamName, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.instructionTypeParamName).value(standingInstructionType)
|
||||
.notNull().inMinMaxRange(1, 2);
|
||||
|
||||
final Integer recurrenceType = this.fromApiJsonHelper.extractIntegerNamed(StandingInstructionApiConstants.recurrenceTypeParamName,
|
||||
element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceTypeParamName).value(recurrenceType).notNull()
|
||||
.inMinMaxRange(1, 2);
|
||||
boolean isPeriodic = false;
|
||||
if (recurrenceType != null) {
|
||||
isPeriodic = AccountTransferRecurrenceType.fromInt(recurrenceType).isPeriodicRecurrence();
|
||||
}
|
||||
|
||||
final Integer recurrenceFrequency = this.fromApiJsonHelper
|
||||
.extractIntegerNamed(StandingInstructionApiConstants.recurrenceFrequencyParamName, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceFrequencyParamName).value(recurrenceFrequency)
|
||||
.inMinMaxRange(0, 3);
|
||||
|
||||
if (recurrenceFrequency != null) {
|
||||
PeriodFrequencyType frequencyType = PeriodFrequencyType.fromInt(recurrenceFrequency);
|
||||
if (frequencyType.isMonthly() || frequencyType.isYearly()) {
|
||||
final MonthDay monthDay = this.fromApiJsonHelper
|
||||
.extractMonthDayNamed(StandingInstructionApiConstants.recurrenceOnMonthDayParamName, element);
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceOnMonthDayParamName).value(monthDay)
|
||||
.notNull();
|
||||
}
|
||||
}
|
||||
|
||||
final Integer recurrenceInterval = this.fromApiJsonHelper
|
||||
.extractIntegerNamed(StandingInstructionApiConstants.recurrenceIntervalParamName, element, Locale.getDefault());
|
||||
if (isPeriodic) {
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceIntervalParamName).value(recurrenceInterval)
|
||||
.notNull();
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceFrequencyParamName).value(recurrenceFrequency)
|
||||
.notNull();
|
||||
}
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceIntervalParamName).value(recurrenceInterval)
|
||||
.integerGreaterThanZero();
|
||||
|
||||
final String name = this.fromApiJsonHelper.extractStringNamed(StandingInstructionApiConstants.nameParamName, element);
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.nameParamName).value(name).notNull();
|
||||
|
||||
final Integer toAccountType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(toAccountTypeParamName, element);
|
||||
if (toAccountType != null && (PortfolioAccountType.fromInt(toAccountType).isSavingsAccount()
|
||||
|| PortfolioAccountType.fromInt(toAccountType).isCurrentAccount())) {
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.instructionTypeParamName).value(standingInstructionType)
|
||||
.notNull().inMinMaxRange(1, 1);
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceTypeParamName).value(recurrenceType).notNull()
|
||||
.inMinMaxRange(1, 1);
|
||||
|
||||
}
|
||||
if (standingInstructionType != null && StandingInstructionType.fromInt(standingInstructionType).isFixedAmoutTransfer()) {
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.amountParamName).value(transferAmount).notNull();
|
||||
}
|
||||
|
||||
String errorCode = null;
|
||||
AccountTransferType accountTransferType = AccountTransferType.fromInt(transferType);
|
||||
final Integer fromAccountType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(fromAccountTypeParamName, element);
|
||||
if (fromAccountType != null && toAccountType != null) {
|
||||
PortfolioAccountType fromPortfolioAccountType = PortfolioAccountType.fromInt(fromAccountType);
|
||||
PortfolioAccountType toPortfolioAccountType = PortfolioAccountType.fromInt(toAccountType);
|
||||
if (accountTransferType.isAccountTransfer()
|
||||
&& (fromPortfolioAccountType.isLoanAccount() || toPortfolioAccountType.isLoanAccount())) {
|
||||
errorCode = "not.account.transfer";
|
||||
} else if (accountTransferType.isLoanRepayment()
|
||||
&& (fromPortfolioAccountType.isLoanAccount()
|
||||
|| (toPortfolioAccountType.isSavingsAccount() || toPortfolioAccountType.isCurrentAccount()))) {
|
||||
errorCode = "not.loan.repayment";
|
||||
}
|
||||
if (errorCode != null) {
|
||||
baseDataValidator.reset().parameter(transferTypeParamName).failWithCode(errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
public void validateForUpdate(final JsonCommand command) {
|
||||
final String json = command.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(StandingInstructionApiConstants.STANDING_INSTRUCTION_RESOURCE_NAME);
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.validFromParamName, element)) {
|
||||
final LocalDate validFrom = this.fromApiJsonHelper.extractLocalDateNamed(StandingInstructionApiConstants.validFromParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.validFromParamName).value(validFrom).notNull();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.validTillParamName, element)) {
|
||||
final LocalDate validTill = this.fromApiJsonHelper.extractLocalDateNamed(StandingInstructionApiConstants.validTillParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.validTillParamName).value(validTill).notNull();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.amountParamName, element)) {
|
||||
final BigDecimal transferAmount = this.fromApiJsonHelper
|
||||
.extractBigDecimalWithLocaleNamed(StandingInstructionApiConstants.amountParamName, element);
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.amountParamName).value(transferAmount).positiveAmount();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.statusParamName, element)) {
|
||||
final Integer status = this.fromApiJsonHelper.extractIntegerNamed(StandingInstructionApiConstants.statusParamName, element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.statusParamName).value(status).notNull().inMinMaxRange(1,
|
||||
2);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.priorityParamName, element)) {
|
||||
final Integer priority = this.fromApiJsonHelper.extractIntegerNamed(StandingInstructionApiConstants.priorityParamName, element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.priorityParamName).value(priority).notNull()
|
||||
.inMinMaxRange(1, 4);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.instructionTypeParamName, element)) {
|
||||
final Integer standingInstructionType = this.fromApiJsonHelper
|
||||
.extractIntegerNamed(StandingInstructionApiConstants.instructionTypeParamName, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.instructionTypeParamName).value(standingInstructionType)
|
||||
.notNull().inMinMaxRange(1, 2);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.recurrenceTypeParamName, element)) {
|
||||
final Integer recurrenceType = this.fromApiJsonHelper
|
||||
.extractIntegerNamed(StandingInstructionApiConstants.recurrenceTypeParamName, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceTypeParamName).value(recurrenceType).notNull()
|
||||
.inMinMaxRange(1, 2);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.recurrenceFrequencyParamName, element)) {
|
||||
final Integer recurrenceFrequency = this.fromApiJsonHelper
|
||||
.extractIntegerNamed(StandingInstructionApiConstants.recurrenceFrequencyParamName, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceFrequencyParamName).value(recurrenceFrequency)
|
||||
.inMinMaxRange(0, 3);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.recurrenceIntervalParamName, element)) {
|
||||
final Integer recurrenceInterval = this.fromApiJsonHelper
|
||||
.extractIntegerNamed(StandingInstructionApiConstants.recurrenceIntervalParamName, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceIntervalParamName).value(recurrenceInterval)
|
||||
.integerGreaterThanZero();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.nameParamName, element)) {
|
||||
final String name = this.fromApiJsonHelper.extractStringNamed(StandingInstructionApiConstants.nameParamName, element);
|
||||
baseDataValidator.reset().parameter(StandingInstructionApiConstants.nameParamName).value(name).notNull();
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+314
-214
@@ -1,214 +1,314 @@
|
||||
/**
|
||||
* 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.account.domain;
|
||||
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.fromAccountIdParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.fromClientIdParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.fromOfficeIdParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.toAccountIdParamName;
|
||||
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.AccountDetailConstants.transferTypeParamName;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import java.util.Locale;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.organisation.office.domain.Office;
|
||||
import org.apache.fineract.organisation.office.domain.OfficeRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.client.domain.Client;
|
||||
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountAssembler;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class AccountTransferDetailAssembler {
|
||||
|
||||
private final ClientRepositoryWrapper clientRepository;
|
||||
private final OfficeRepositoryWrapper officeRepositoryWrapper;
|
||||
private final SavingsAccountAssembler savingsAccountAssembler;
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
private final LoanAssembler loanAccountAssembler;
|
||||
|
||||
@Autowired
|
||||
public AccountTransferDetailAssembler(final ClientRepositoryWrapper clientRepository,
|
||||
final OfficeRepositoryWrapper officeRepositoryWrapper, final SavingsAccountAssembler savingsAccountAssembler,
|
||||
final FromJsonHelper fromApiJsonHelper, final LoanAssembler loanAccountAssembler) {
|
||||
this.clientRepository = clientRepository;
|
||||
this.officeRepositoryWrapper = officeRepositoryWrapper;
|
||||
this.savingsAccountAssembler = savingsAccountAssembler;
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
this.loanAccountAssembler = loanAccountAssembler;
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleSavingsToSavingsTransfer(final JsonCommand command) {
|
||||
|
||||
final Long fromSavingsId = command.longValueOfParameterNamed(fromAccountIdParamName);
|
||||
final SavingsAccount fromSavingsAccount = this.savingsAccountAssembler.assembleFrom(fromSavingsId, false);
|
||||
|
||||
final boolean backdatedTxnsAllowedTill = false;
|
||||
final Long toSavingsId = command.longValueOfParameterNamed(toAccountIdParamName);
|
||||
final SavingsAccount toSavingsAccount = this.savingsAccountAssembler.assembleFrom(toSavingsId, backdatedTxnsAllowedTill);
|
||||
|
||||
return assembleSavingsToSavingsTransfer(command, fromSavingsAccount, toSavingsAccount);
|
||||
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleSavingsToLoanTransfer(final JsonCommand command) {
|
||||
|
||||
final Long fromSavingsAccountId = command.longValueOfParameterNamed(fromAccountIdParamName);
|
||||
final boolean backdatedTxnsAllowedTill = false;
|
||||
final SavingsAccount fromSavingsAccount = this.savingsAccountAssembler.assembleFrom(fromSavingsAccountId, backdatedTxnsAllowedTill);
|
||||
|
||||
final Long toLoanAccountId = command.longValueOfParameterNamed(toAccountIdParamName);
|
||||
final Loan toLoanAccount = this.loanAccountAssembler.assembleFrom(toLoanAccountId);
|
||||
|
||||
return assembleSavingsToLoanTransfer(command, fromSavingsAccount, toLoanAccount);
|
||||
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleLoanToSavingsTransfer(final JsonCommand command) {
|
||||
|
||||
final Long fromLoanAccountId = command.longValueOfParameterNamed(fromAccountIdParamName);
|
||||
final Loan fromLoanAccount = this.loanAccountAssembler.assembleFrom(fromLoanAccountId);
|
||||
final boolean backdatedTxnsAllowedTill = false;
|
||||
final Long toSavingsAccountId = command.longValueOfParameterNamed(toAccountIdParamName);
|
||||
final SavingsAccount toSavingsAccount = this.savingsAccountAssembler.assembleFrom(toSavingsAccountId, backdatedTxnsAllowedTill);
|
||||
|
||||
return assembleLoanToSavingsTransfer(command, fromLoanAccount, toSavingsAccount);
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleSavingsToSavingsTransfer(final JsonCommand command, final SavingsAccount fromSavingsAccount,
|
||||
final SavingsAccount toSavingsAccount) {
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
|
||||
final Long fromOfficeId = this.fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element);
|
||||
final Office fromOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(fromOfficeId);
|
||||
|
||||
final Long fromClientId = this.fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element);
|
||||
final Client fromClient = this.clientRepository.findOneWithNotFoundDetection(fromClientId);
|
||||
|
||||
final Long toOfficeId = this.fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element);
|
||||
final Office toOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(toOfficeId);
|
||||
|
||||
final Long toClientId = this.fromApiJsonHelper.extractLongNamed(toClientIdParamName, element);
|
||||
final Client toClient = this.clientRepository.findOneWithNotFoundDetection(toClientId);
|
||||
|
||||
final Integer transfertype = this.fromApiJsonHelper.extractIntegerNamed(transferTypeParamName, element, Locale.getDefault());
|
||||
|
||||
return AccountTransferDetails.savingsToSavingsTransfer(fromOffice, fromClient, fromSavingsAccount, toOffice, toClient,
|
||||
toSavingsAccount, transfertype);
|
||||
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleSavingsToLoanTransfer(final JsonCommand command, final SavingsAccount fromSavingsAccount,
|
||||
final Loan toLoanAccount) {
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
|
||||
final Long fromOfficeId = this.fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element);
|
||||
final Office fromOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(fromOfficeId);
|
||||
|
||||
final Long fromClientId = this.fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element);
|
||||
final Client fromClient = this.clientRepository.findOneWithNotFoundDetection(fromClientId);
|
||||
|
||||
final Long toOfficeId = this.fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element);
|
||||
final Office toOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(toOfficeId);
|
||||
|
||||
final Long toClientId = this.fromApiJsonHelper.extractLongNamed(toClientIdParamName, element);
|
||||
final Client toClient = this.clientRepository.findOneWithNotFoundDetection(toClientId);
|
||||
|
||||
final Integer transfertype = this.fromApiJsonHelper.extractIntegerNamed(transferTypeParamName, element, Locale.getDefault());
|
||||
|
||||
return AccountTransferDetails.savingsToLoanTransfer(fromOffice, fromClient, fromSavingsAccount, toOffice, toClient, toLoanAccount,
|
||||
transfertype);
|
||||
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleLoanToSavingsTransfer(final JsonCommand command, final Loan fromLoanAccount,
|
||||
final SavingsAccount toSavingsAccount) {
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
|
||||
final Long fromOfficeId = this.fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element);
|
||||
final Office fromOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(fromOfficeId);
|
||||
|
||||
final Long fromClientId = this.fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element);
|
||||
final Client fromClient = this.clientRepository.findOneWithNotFoundDetection(fromClientId);
|
||||
|
||||
final Long toOfficeId = this.fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element);
|
||||
final Office toOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(toOfficeId);
|
||||
|
||||
final Long toClientId = this.fromApiJsonHelper.extractLongNamed(toClientIdParamName, element);
|
||||
final Client toClient = this.clientRepository.findOneWithNotFoundDetection(toClientId);
|
||||
final Integer transfertype = this.fromApiJsonHelper.extractIntegerNamed(transferTypeParamName, element, Locale.getDefault());
|
||||
|
||||
return AccountTransferDetails.loanTosavingsTransfer(fromOffice, fromClient, fromLoanAccount, toOffice, toClient, toSavingsAccount,
|
||||
transfertype);
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleSavingsToLoanTransfer(final SavingsAccount fromSavingsAccount, final Loan toLoanAccount,
|
||||
Integer transferType) {
|
||||
final Office fromOffice = fromSavingsAccount.office();
|
||||
final Client fromClient = fromSavingsAccount.getClient();
|
||||
final Office toOffice = toLoanAccount.getOffice();
|
||||
final Client toClient = toLoanAccount.client();
|
||||
|
||||
return AccountTransferDetails.savingsToLoanTransfer(fromOffice, fromClient, fromSavingsAccount, toOffice, toClient, toLoanAccount,
|
||||
transferType);
|
||||
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleSavingsToSavingsTransfer(final SavingsAccount fromSavingsAccount,
|
||||
final SavingsAccount toSavingsAccount, Integer transferType) {
|
||||
final Office fromOffice = fromSavingsAccount.office();
|
||||
final Client fromClient = fromSavingsAccount.getClient();
|
||||
final Office toOffice = toSavingsAccount.office();
|
||||
final Client toClient = toSavingsAccount.getClient();
|
||||
|
||||
return AccountTransferDetails.savingsToSavingsTransfer(fromOffice, fromClient, fromSavingsAccount, toOffice, toClient,
|
||||
toSavingsAccount, transferType);
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleLoanToSavingsTransfer(final Loan fromLoanAccount, final SavingsAccount toSavingsAccount,
|
||||
Integer transferType) {
|
||||
final Office fromOffice = fromLoanAccount.getOffice();
|
||||
final Client fromClient = fromLoanAccount.client();
|
||||
final Office toOffice = toSavingsAccount.office();
|
||||
final Client toClient = toSavingsAccount.getClient();
|
||||
|
||||
return AccountTransferDetails.loanTosavingsTransfer(fromOffice, fromClient, fromLoanAccount, toOffice, toClient, toSavingsAccount,
|
||||
transferType);
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleLoanToLoanTransfer(Loan fromLoanAccount, Loan toLoanAccount, Integer transferType) {
|
||||
final Office fromOffice = fromLoanAccount.getOffice();
|
||||
final Client fromClient = fromLoanAccount.client();
|
||||
final Office toOffice = toLoanAccount.getOffice();
|
||||
final Client toClient = toLoanAccount.client();
|
||||
|
||||
return AccountTransferDetails.loanToLoanTransfer(fromOffice, fromClient, fromLoanAccount, toOffice, toClient, toLoanAccount,
|
||||
transferType);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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.account.domain;
|
||||
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.fromAccountIdParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.fromClientIdParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.fromOfficeIdParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.toAccountIdParamName;
|
||||
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.AccountDetailConstants.transferTypeParamName;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import java.util.Locale;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.organisation.office.domain.Office;
|
||||
import org.apache.fineract.organisation.office.domain.OfficeRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.client.domain.Client;
|
||||
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.currentaccount.domain.CurrentAccount;
|
||||
import org.apache.fineract.portfolio.currentaccount.domain.CurrentAccountRepository;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountAssembler;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class AccountTransferDetailAssembler {
|
||||
|
||||
private final ClientRepositoryWrapper clientRepository;
|
||||
private final OfficeRepositoryWrapper officeRepositoryWrapper;
|
||||
private final SavingsAccountAssembler savingsAccountAssembler;
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
private final LoanAssembler loanAccountAssembler;
|
||||
private final CurrentAccountRepository currentAccountRepository;
|
||||
|
||||
@Autowired
|
||||
public AccountTransferDetailAssembler(final ClientRepositoryWrapper clientRepository,
|
||||
final OfficeRepositoryWrapper officeRepositoryWrapper, final SavingsAccountAssembler savingsAccountAssembler,
|
||||
final FromJsonHelper fromApiJsonHelper, final LoanAssembler loanAccountAssembler,
|
||||
final CurrentAccountRepository currentAccountRepository) {
|
||||
this.clientRepository = clientRepository;
|
||||
this.officeRepositoryWrapper = officeRepositoryWrapper;
|
||||
this.savingsAccountAssembler = savingsAccountAssembler;
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
this.loanAccountAssembler = loanAccountAssembler;
|
||||
this.currentAccountRepository = currentAccountRepository;
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleSavingsToSavingsTransfer(final JsonCommand command) {
|
||||
|
||||
final Long fromSavingsId = command.longValueOfParameterNamed(fromAccountIdParamName);
|
||||
final SavingsAccount fromSavingsAccount = this.savingsAccountAssembler.assembleFrom(fromSavingsId, false);
|
||||
|
||||
final boolean backdatedTxnsAllowedTill = false;
|
||||
final Long toSavingsId = command.longValueOfParameterNamed(toAccountIdParamName);
|
||||
final SavingsAccount toSavingsAccount = this.savingsAccountAssembler.assembleFrom(toSavingsId, backdatedTxnsAllowedTill);
|
||||
|
||||
return assembleSavingsToSavingsTransfer(command, fromSavingsAccount, toSavingsAccount);
|
||||
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleSavingsToLoanTransfer(final JsonCommand command) {
|
||||
|
||||
final Long fromSavingsAccountId = command.longValueOfParameterNamed(fromAccountIdParamName);
|
||||
final boolean backdatedTxnsAllowedTill = false;
|
||||
final SavingsAccount fromSavingsAccount = this.savingsAccountAssembler.assembleFrom(fromSavingsAccountId, backdatedTxnsAllowedTill);
|
||||
|
||||
final Long toLoanAccountId = command.longValueOfParameterNamed(toAccountIdParamName);
|
||||
final Loan toLoanAccount = this.loanAccountAssembler.assembleFrom(toLoanAccountId);
|
||||
|
||||
return assembleSavingsToLoanTransfer(command, fromSavingsAccount, toLoanAccount);
|
||||
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleLoanToSavingsTransfer(final JsonCommand command) {
|
||||
|
||||
final Long fromLoanAccountId = command.longValueOfParameterNamed(fromAccountIdParamName);
|
||||
final Loan fromLoanAccount = this.loanAccountAssembler.assembleFrom(fromLoanAccountId);
|
||||
final boolean backdatedTxnsAllowedTill = false;
|
||||
final Long toSavingsAccountId = command.longValueOfParameterNamed(toAccountIdParamName);
|
||||
final SavingsAccount toSavingsAccount = this.savingsAccountAssembler.assembleFrom(toSavingsAccountId, backdatedTxnsAllowedTill);
|
||||
|
||||
return assembleLoanToSavingsTransfer(command, fromLoanAccount, toSavingsAccount);
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleSavingsToSavingsTransfer(final JsonCommand command, final SavingsAccount fromSavingsAccount,
|
||||
final SavingsAccount toSavingsAccount) {
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
|
||||
final Long fromOfficeId = this.fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element);
|
||||
final Office fromOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(fromOfficeId);
|
||||
|
||||
final Long fromClientId = this.fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element);
|
||||
final Client fromClient = this.clientRepository.findOneWithNotFoundDetection(fromClientId);
|
||||
|
||||
final Long toOfficeId = this.fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element);
|
||||
final Office toOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(toOfficeId);
|
||||
|
||||
final Long toClientId = this.fromApiJsonHelper.extractLongNamed(toClientIdParamName, element);
|
||||
final Client toClient = this.clientRepository.findOneWithNotFoundDetection(toClientId);
|
||||
|
||||
final Integer transfertype = this.fromApiJsonHelper.extractIntegerNamed(transferTypeParamName, element, Locale.getDefault());
|
||||
|
||||
return AccountTransferDetails.savingsToSavingsTransfer(fromOffice, fromClient, fromSavingsAccount, toOffice, toClient,
|
||||
toSavingsAccount, transfertype);
|
||||
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleSavingsToLoanTransfer(final JsonCommand command, final SavingsAccount fromSavingsAccount,
|
||||
final Loan toLoanAccount) {
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
|
||||
final Long fromOfficeId = this.fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element);
|
||||
final Office fromOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(fromOfficeId);
|
||||
|
||||
final Long fromClientId = this.fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element);
|
||||
final Client fromClient = this.clientRepository.findOneWithNotFoundDetection(fromClientId);
|
||||
|
||||
final Long toOfficeId = this.fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element);
|
||||
final Office toOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(toOfficeId);
|
||||
|
||||
final Long toClientId = this.fromApiJsonHelper.extractLongNamed(toClientIdParamName, element);
|
||||
final Client toClient = this.clientRepository.findOneWithNotFoundDetection(toClientId);
|
||||
|
||||
final Integer transfertype = this.fromApiJsonHelper.extractIntegerNamed(transferTypeParamName, element, Locale.getDefault());
|
||||
|
||||
return AccountTransferDetails.savingsToLoanTransfer(fromOffice, fromClient, fromSavingsAccount, toOffice, toClient, toLoanAccount,
|
||||
transfertype);
|
||||
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleLoanToSavingsTransfer(final JsonCommand command, final Loan fromLoanAccount,
|
||||
final SavingsAccount toSavingsAccount) {
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
|
||||
final Long fromOfficeId = this.fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element);
|
||||
final Office fromOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(fromOfficeId);
|
||||
|
||||
final Long fromClientId = this.fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element);
|
||||
final Client fromClient = this.clientRepository.findOneWithNotFoundDetection(fromClientId);
|
||||
|
||||
final Long toOfficeId = this.fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element);
|
||||
final Office toOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(toOfficeId);
|
||||
|
||||
final Long toClientId = this.fromApiJsonHelper.extractLongNamed(toClientIdParamName, element);
|
||||
final Client toClient = this.clientRepository.findOneWithNotFoundDetection(toClientId);
|
||||
final Integer transfertype = this.fromApiJsonHelper.extractIntegerNamed(transferTypeParamName, element, Locale.getDefault());
|
||||
|
||||
return AccountTransferDetails.loanTosavingsTransfer(fromOffice, fromClient, fromLoanAccount, toOffice, toClient, toSavingsAccount,
|
||||
transfertype);
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleSavingsToLoanTransfer(final SavingsAccount fromSavingsAccount, final Loan toLoanAccount,
|
||||
Integer transferType) {
|
||||
final Office fromOffice = fromSavingsAccount.office();
|
||||
final Client fromClient = fromSavingsAccount.getClient();
|
||||
final Office toOffice = toLoanAccount.getOffice();
|
||||
final Client toClient = toLoanAccount.client();
|
||||
|
||||
return AccountTransferDetails.savingsToLoanTransfer(fromOffice, fromClient, fromSavingsAccount, toOffice, toClient, toLoanAccount,
|
||||
transferType);
|
||||
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleSavingsToSavingsTransfer(final SavingsAccount fromSavingsAccount,
|
||||
final SavingsAccount toSavingsAccount, Integer transferType) {
|
||||
final Office fromOffice = fromSavingsAccount.office();
|
||||
final Client fromClient = fromSavingsAccount.getClient();
|
||||
final Office toOffice = toSavingsAccount.office();
|
||||
final Client toClient = toSavingsAccount.getClient();
|
||||
|
||||
return AccountTransferDetails.savingsToSavingsTransfer(fromOffice, fromClient, fromSavingsAccount, toOffice, toClient,
|
||||
toSavingsAccount, transferType);
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleLoanToSavingsTransfer(final Loan fromLoanAccount, final SavingsAccount toSavingsAccount,
|
||||
Integer transferType) {
|
||||
final Office fromOffice = fromLoanAccount.getOffice();
|
||||
final Client fromClient = fromLoanAccount.client();
|
||||
final Office toOffice = toSavingsAccount.office();
|
||||
final Client toClient = toSavingsAccount.getClient();
|
||||
|
||||
return AccountTransferDetails.loanTosavingsTransfer(fromOffice, fromClient, fromLoanAccount, toOffice, toClient, toSavingsAccount,
|
||||
transferType);
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleLoanToLoanTransfer(Loan fromLoanAccount, Loan toLoanAccount, Integer transferType) {
|
||||
final Office fromOffice = fromLoanAccount.getOffice();
|
||||
final Client fromClient = fromLoanAccount.client();
|
||||
final Office toOffice = toLoanAccount.getOffice();
|
||||
final Client toClient = toLoanAccount.client();
|
||||
|
||||
return AccountTransferDetails.loanToLoanTransfer(fromOffice, fromClient, fromLoanAccount, toOffice, toClient, toLoanAccount,
|
||||
transferType);
|
||||
}
|
||||
|
||||
// --- Current account assembly methods ---
|
||||
|
||||
public AccountTransferDetails assembleCurrentToCurrentTransfer(final JsonCommand command) {
|
||||
final Long fromCurrentAccountId = command.longValueOfParameterNamed(fromAccountIdParamName);
|
||||
final CurrentAccount fromCurrentAccount = currentAccountRepository.findById(fromCurrentAccountId)
|
||||
.orElseThrow(() -> new IllegalArgumentException("From current account not found: " + fromCurrentAccountId));
|
||||
|
||||
final Long toCurrentAccountId = command.longValueOfParameterNamed(toAccountIdParamName);
|
||||
final CurrentAccount toCurrentAccount = currentAccountRepository.findById(toCurrentAccountId)
|
||||
.orElseThrow(() -> new IllegalArgumentException("To current account not found: " + toCurrentAccountId));
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
final Long fromOfficeId = this.fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element);
|
||||
final Office fromOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(fromOfficeId);
|
||||
final Long fromClientId = this.fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element);
|
||||
final Client fromClient = this.clientRepository.findOneWithNotFoundDetection(fromClientId);
|
||||
final Long toOfficeId = this.fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element);
|
||||
final Office toOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(toOfficeId);
|
||||
final Long toClientId = this.fromApiJsonHelper.extractLongNamed(toClientIdParamName, element);
|
||||
final Client toClient = this.clientRepository.findOneWithNotFoundDetection(toClientId);
|
||||
final Integer transfertype = this.fromApiJsonHelper.extractIntegerNamed(transferTypeParamName, element, Locale.getDefault());
|
||||
|
||||
return AccountTransferDetails.currentToCurrentTransfer(fromOffice, fromClient, fromCurrentAccount, toOffice, toClient,
|
||||
toCurrentAccount, transfertype);
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleCurrentToSavingsTransfer(final JsonCommand command) {
|
||||
final Long fromCurrentAccountId = command.longValueOfParameterNamed(fromAccountIdParamName);
|
||||
final CurrentAccount fromCurrentAccount = currentAccountRepository.findById(fromCurrentAccountId)
|
||||
.orElseThrow(() -> new IllegalArgumentException("From current account not found: " + fromCurrentAccountId));
|
||||
|
||||
final Long toSavingsId = command.longValueOfParameterNamed(toAccountIdParamName);
|
||||
final SavingsAccount toSavingsAccount = this.savingsAccountAssembler.assembleFrom(toSavingsId, false);
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
final Long fromOfficeId = this.fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element);
|
||||
final Office fromOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(fromOfficeId);
|
||||
final Long fromClientId = this.fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element);
|
||||
final Client fromClient = this.clientRepository.findOneWithNotFoundDetection(fromClientId);
|
||||
final Long toOfficeId = this.fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element);
|
||||
final Office toOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(toOfficeId);
|
||||
final Long toClientId = this.fromApiJsonHelper.extractLongNamed(toClientIdParamName, element);
|
||||
final Client toClient = this.clientRepository.findOneWithNotFoundDetection(toClientId);
|
||||
final Integer transfertype = this.fromApiJsonHelper.extractIntegerNamed(transferTypeParamName, element, Locale.getDefault());
|
||||
|
||||
return AccountTransferDetails.currentToSavingsTransfer(fromOffice, fromClient, fromCurrentAccount, toOffice, toClient,
|
||||
toSavingsAccount, transfertype);
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleSavingsToCurrentTransfer(final JsonCommand command) {
|
||||
final Long fromSavingsId = command.longValueOfParameterNamed(fromAccountIdParamName);
|
||||
final SavingsAccount fromSavingsAccount = this.savingsAccountAssembler.assembleFrom(fromSavingsId, false);
|
||||
|
||||
final Long toCurrentAccountId = command.longValueOfParameterNamed(toAccountIdParamName);
|
||||
final CurrentAccount toCurrentAccount = currentAccountRepository.findById(toCurrentAccountId)
|
||||
.orElseThrow(() -> new IllegalArgumentException("To current account not found: " + toCurrentAccountId));
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
final Long fromOfficeId = this.fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element);
|
||||
final Office fromOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(fromOfficeId);
|
||||
final Long fromClientId = this.fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element);
|
||||
final Client fromClient = this.clientRepository.findOneWithNotFoundDetection(fromClientId);
|
||||
final Long toOfficeId = this.fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element);
|
||||
final Office toOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(toOfficeId);
|
||||
final Long toClientId = this.fromApiJsonHelper.extractLongNamed(toClientIdParamName, element);
|
||||
final Client toClient = this.clientRepository.findOneWithNotFoundDetection(toClientId);
|
||||
final Integer transfertype = this.fromApiJsonHelper.extractIntegerNamed(transferTypeParamName, element, Locale.getDefault());
|
||||
|
||||
return AccountTransferDetails.savingsToCurrentTransfer(fromOffice, fromClient, fromSavingsAccount, toOffice, toClient,
|
||||
toCurrentAccount, transfertype);
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleCurrentToLoanTransfer(final JsonCommand command) {
|
||||
final Long fromCurrentAccountId = command.longValueOfParameterNamed(fromAccountIdParamName);
|
||||
final CurrentAccount fromCurrentAccount = currentAccountRepository.findById(fromCurrentAccountId)
|
||||
.orElseThrow(() -> new IllegalArgumentException("From current account not found: " + fromCurrentAccountId));
|
||||
|
||||
final Long toLoanAccountId = command.longValueOfParameterNamed(toAccountIdParamName);
|
||||
final Loan toLoanAccount = this.loanAccountAssembler.assembleFrom(toLoanAccountId);
|
||||
|
||||
final JsonElement element = command.parsedJson();
|
||||
final Long fromOfficeId = this.fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element);
|
||||
final Office fromOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(fromOfficeId);
|
||||
final Long fromClientId = this.fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element);
|
||||
final Client fromClient = this.clientRepository.findOneWithNotFoundDetection(fromClientId);
|
||||
final Long toOfficeId = this.fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element);
|
||||
final Office toOffice = this.officeRepositoryWrapper.findOneWithNotFoundDetection(toOfficeId);
|
||||
final Long toClientId = this.fromApiJsonHelper.extractLongNamed(toClientIdParamName, element);
|
||||
final Client toClient = this.clientRepository.findOneWithNotFoundDetection(toClientId);
|
||||
final Integer transfertype = this.fromApiJsonHelper.extractIntegerNamed(transferTypeParamName, element, Locale.getDefault());
|
||||
|
||||
return AccountTransferDetails.currentToLoanTransfer(fromOffice, fromClient, fromCurrentAccount, toOffice, toClient,
|
||||
toLoanAccount, transfertype);
|
||||
}
|
||||
}
|
||||
|
||||
+216
-165
@@ -1,165 +1,216 @@
|
||||
/**
|
||||
* 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.account.domain;
|
||||
|
||||
import jakarta.persistence.CascadeType;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.OneToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.organisation.office.domain.Office;
|
||||
import org.apache.fineract.portfolio.client.domain.Client;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_account_transfer_details")
|
||||
public class AccountTransferDetails extends AbstractPersistableCustom<Long> {
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "from_office_id", nullable = false)
|
||||
private Office fromOffice;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "from_client_id", nullable = false)
|
||||
private Client fromClient;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "from_savings_account_id", nullable = true)
|
||||
private SavingsAccount fromSavingsAccount;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "to_office_id", nullable = false)
|
||||
private Office toOffice;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "to_client_id", nullable = false)
|
||||
private Client toClient;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "to_savings_account_id", nullable = true)
|
||||
private SavingsAccount toSavingsAccount;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "to_loan_account_id", nullable = true)
|
||||
private Loan toLoanAccount;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "from_loan_account_id", nullable = true)
|
||||
private Loan fromLoanAccount;
|
||||
|
||||
@Column(name = "transfer_type")
|
||||
private Integer transferType;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "accountTransferDetails", orphanRemoval = true, fetch = FetchType.EAGER)
|
||||
private List<AccountTransferTransaction> accountTransferTransactions = new ArrayList<>();
|
||||
|
||||
@OneToOne(mappedBy = "accountTransferDetails", cascade = CascadeType.ALL, optional = true, orphanRemoval = true, fetch = FetchType.EAGER)
|
||||
private AccountTransferStandingInstruction accountTransferStandingInstruction;
|
||||
|
||||
public static AccountTransferDetails savingsToSavingsTransfer(final Office fromOffice, final Client fromClient,
|
||||
final SavingsAccount fromSavingsAccount, final Office toOffice, final Client toClient, final SavingsAccount toSavingsAccount,
|
||||
Integer transferType) {
|
||||
|
||||
return new AccountTransferDetails(fromOffice, fromClient, fromSavingsAccount, null, toOffice, toClient, toSavingsAccount, null,
|
||||
transferType, null);
|
||||
}
|
||||
|
||||
public static AccountTransferDetails savingsToLoanTransfer(final Office fromOffice, final Client fromClient,
|
||||
final SavingsAccount fromSavingsAccount, final Office toOffice, final Client toClient, final Loan toLoanAccount,
|
||||
Integer transferType) {
|
||||
return new AccountTransferDetails(fromOffice, fromClient, fromSavingsAccount, null, toOffice, toClient, null, toLoanAccount,
|
||||
transferType, null);
|
||||
}
|
||||
|
||||
public static AccountTransferDetails loanTosavingsTransfer(final Office fromOffice, final Client fromClient, final Loan fromLoanAccount,
|
||||
final Office toOffice, final Client toClient, final SavingsAccount toSavingsAccount, Integer transferType) {
|
||||
return new AccountTransferDetails(fromOffice, fromClient, null, fromLoanAccount, toOffice, toClient, toSavingsAccount, null,
|
||||
transferType, null);
|
||||
}
|
||||
|
||||
protected AccountTransferDetails() {
|
||||
//
|
||||
}
|
||||
|
||||
private AccountTransferDetails(final Office fromOffice, final Client fromClient, final SavingsAccount fromSavingsAccount,
|
||||
final Loan fromLoanAccount, final Office toOffice, final Client toClient, final SavingsAccount toSavingsAccount,
|
||||
final Loan toLoanAccount, final Integer transferType,
|
||||
final AccountTransferStandingInstruction accountTransferStandingInstruction) {
|
||||
this.fromOffice = fromOffice;
|
||||
this.fromClient = fromClient;
|
||||
this.fromSavingsAccount = fromSavingsAccount;
|
||||
this.fromLoanAccount = fromLoanAccount;
|
||||
this.toOffice = toOffice;
|
||||
this.toClient = toClient;
|
||||
this.toSavingsAccount = toSavingsAccount;
|
||||
this.toLoanAccount = toLoanAccount;
|
||||
this.transferType = transferType;
|
||||
this.accountTransferStandingInstruction = accountTransferStandingInstruction;
|
||||
}
|
||||
|
||||
public SavingsAccount toSavingsAccount() {
|
||||
return this.toSavingsAccount;
|
||||
}
|
||||
|
||||
public SavingsAccount fromSavingsAccount() {
|
||||
return this.fromSavingsAccount;
|
||||
}
|
||||
|
||||
public void addAccountTransferTransaction(AccountTransferTransaction accountTransferTransaction) {
|
||||
this.accountTransferTransactions.add(accountTransferTransaction);
|
||||
}
|
||||
|
||||
public void updateAccountTransferStandingInstruction(final AccountTransferStandingInstruction accountTransferStandingInstruction) {
|
||||
this.accountTransferStandingInstruction = accountTransferStandingInstruction;
|
||||
}
|
||||
|
||||
public Loan toLoanAccount() {
|
||||
return this.toLoanAccount;
|
||||
}
|
||||
|
||||
public Loan fromLoanAccount() {
|
||||
return this.fromLoanAccount;
|
||||
}
|
||||
|
||||
public AccountTransferStandingInstruction accountTransferStandingInstruction() {
|
||||
return this.accountTransferStandingInstruction;
|
||||
}
|
||||
|
||||
public AccountTransferType transferType() {
|
||||
return AccountTransferType.fromInt(this.transferType);
|
||||
}
|
||||
|
||||
public static AccountTransferDetails loanToLoanTransfer(Office fromOffice, Client fromClient, Loan fromLoanAccount, Office toOffice,
|
||||
Client toClient, Loan toLoanAccount, Integer transferType) {
|
||||
return new AccountTransferDetails(fromOffice, fromClient, null, fromLoanAccount, toOffice, toClient, null, toLoanAccount,
|
||||
transferType, null);
|
||||
}
|
||||
|
||||
public List<AccountTransferTransaction> getAccountTransferTransactions() {
|
||||
return accountTransferTransactions;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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.account.domain;
|
||||
|
||||
import jakarta.persistence.CascadeType;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.OneToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.organisation.office.domain.Office;
|
||||
import org.apache.fineract.portfolio.client.domain.Client;
|
||||
import org.apache.fineract.portfolio.currentaccount.domain.CurrentAccount;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_account_transfer_details")
|
||||
public class AccountTransferDetails extends AbstractPersistableCustom<Long> {
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "from_office_id", nullable = false)
|
||||
private Office fromOffice;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "from_client_id", nullable = false)
|
||||
private Client fromClient;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "from_savings_account_id", nullable = true)
|
||||
private SavingsAccount fromSavingsAccount;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "to_office_id", nullable = false)
|
||||
private Office toOffice;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "to_client_id", nullable = false)
|
||||
private Client toClient;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "to_savings_account_id", nullable = true)
|
||||
private SavingsAccount toSavingsAccount;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "to_loan_account_id", nullable = true)
|
||||
private Loan toLoanAccount;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "from_loan_account_id", nullable = true)
|
||||
private Loan fromLoanAccount;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "from_current_account_id", nullable = true)
|
||||
private CurrentAccount fromCurrentAccount;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "to_current_account_id", nullable = true)
|
||||
private CurrentAccount toCurrentAccount;
|
||||
|
||||
@Column(name = "transfer_type")
|
||||
private Integer transferType;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "accountTransferDetails", orphanRemoval = true, fetch = FetchType.EAGER)
|
||||
private List<AccountTransferTransaction> accountTransferTransactions = new ArrayList<>();
|
||||
|
||||
@OneToOne(mappedBy = "accountTransferDetails", cascade = CascadeType.ALL, optional = true, orphanRemoval = true, fetch = FetchType.EAGER)
|
||||
private AccountTransferStandingInstruction accountTransferStandingInstruction;
|
||||
|
||||
public static AccountTransferDetails savingsToSavingsTransfer(final Office fromOffice, final Client fromClient,
|
||||
final SavingsAccount fromSavingsAccount, final Office toOffice, final Client toClient, final SavingsAccount toSavingsAccount,
|
||||
Integer transferType) {
|
||||
|
||||
return new AccountTransferDetails(fromOffice, fromClient, fromSavingsAccount, null, null, toOffice, toClient, toSavingsAccount,
|
||||
null, null, transferType, null);
|
||||
}
|
||||
|
||||
public static AccountTransferDetails savingsToLoanTransfer(final Office fromOffice, final Client fromClient,
|
||||
final SavingsAccount fromSavingsAccount, final Office toOffice, final Client toClient, final Loan toLoanAccount,
|
||||
Integer transferType) {
|
||||
return new AccountTransferDetails(fromOffice, fromClient, fromSavingsAccount, null, null, toOffice, toClient, null, toLoanAccount,
|
||||
null, transferType, null);
|
||||
}
|
||||
|
||||
public static AccountTransferDetails loanTosavingsTransfer(final Office fromOffice, final Client fromClient, final Loan fromLoanAccount,
|
||||
final Office toOffice, final Client toClient, final SavingsAccount toSavingsAccount, Integer transferType) {
|
||||
return new AccountTransferDetails(fromOffice, fromClient, null, fromLoanAccount, null, toOffice, toClient, toSavingsAccount, null,
|
||||
null, transferType, null);
|
||||
}
|
||||
|
||||
protected AccountTransferDetails() {
|
||||
//
|
||||
}
|
||||
|
||||
private AccountTransferDetails(final Office fromOffice, final Client fromClient, final SavingsAccount fromSavingsAccount,
|
||||
final Loan fromLoanAccount, final CurrentAccount fromCurrentAccount,
|
||||
final Office toOffice, final Client toClient, final SavingsAccount toSavingsAccount,
|
||||
final Loan toLoanAccount, final CurrentAccount toCurrentAccount,
|
||||
final Integer transferType,
|
||||
final AccountTransferStandingInstruction accountTransferStandingInstruction) {
|
||||
this.fromOffice = fromOffice;
|
||||
this.fromClient = fromClient;
|
||||
this.fromSavingsAccount = fromSavingsAccount;
|
||||
this.fromLoanAccount = fromLoanAccount;
|
||||
this.fromCurrentAccount = fromCurrentAccount;
|
||||
this.toOffice = toOffice;
|
||||
this.toClient = toClient;
|
||||
this.toSavingsAccount = toSavingsAccount;
|
||||
this.toLoanAccount = toLoanAccount;
|
||||
this.toCurrentAccount = toCurrentAccount;
|
||||
this.transferType = transferType;
|
||||
this.accountTransferStandingInstruction = accountTransferStandingInstruction;
|
||||
}
|
||||
|
||||
public SavingsAccount toSavingsAccount() {
|
||||
return this.toSavingsAccount;
|
||||
}
|
||||
|
||||
public SavingsAccount fromSavingsAccount() {
|
||||
return this.fromSavingsAccount;
|
||||
}
|
||||
|
||||
public void addAccountTransferTransaction(AccountTransferTransaction accountTransferTransaction) {
|
||||
this.accountTransferTransactions.add(accountTransferTransaction);
|
||||
}
|
||||
|
||||
public void updateAccountTransferStandingInstruction(final AccountTransferStandingInstruction accountTransferStandingInstruction) {
|
||||
this.accountTransferStandingInstruction = accountTransferStandingInstruction;
|
||||
}
|
||||
|
||||
public Loan toLoanAccount() {
|
||||
return this.toLoanAccount;
|
||||
}
|
||||
|
||||
public Loan fromLoanAccount() {
|
||||
return this.fromLoanAccount;
|
||||
}
|
||||
|
||||
public CurrentAccount fromCurrentAccount() {
|
||||
return this.fromCurrentAccount;
|
||||
}
|
||||
|
||||
public CurrentAccount toCurrentAccount() {
|
||||
return this.toCurrentAccount;
|
||||
}
|
||||
|
||||
public AccountTransferStandingInstruction accountTransferStandingInstruction() {
|
||||
return this.accountTransferStandingInstruction;
|
||||
}
|
||||
|
||||
public AccountTransferType transferType() {
|
||||
return AccountTransferType.fromInt(this.transferType);
|
||||
}
|
||||
|
||||
public static AccountTransferDetails loanToLoanTransfer(Office fromOffice, Client fromClient, Loan fromLoanAccount, Office toOffice,
|
||||
Client toClient, Loan toLoanAccount, Integer transferType) {
|
||||
return new AccountTransferDetails(fromOffice, fromClient, null, fromLoanAccount, null, toOffice, toClient, null, toLoanAccount,
|
||||
null, transferType, null);
|
||||
}
|
||||
|
||||
// --- Current account factory methods ---
|
||||
|
||||
public static AccountTransferDetails currentToCurrentTransfer(final Office fromOffice, final Client fromClient,
|
||||
final CurrentAccount fromCurrentAccount, final Office toOffice, final Client toClient,
|
||||
final CurrentAccount toCurrentAccount, Integer transferType) {
|
||||
return new AccountTransferDetails(fromOffice, fromClient, null, null, fromCurrentAccount, toOffice, toClient, null, null,
|
||||
toCurrentAccount, transferType, null);
|
||||
}
|
||||
|
||||
public static AccountTransferDetails currentToSavingsTransfer(final Office fromOffice, final Client fromClient,
|
||||
final CurrentAccount fromCurrentAccount, final Office toOffice, final Client toClient,
|
||||
final SavingsAccount toSavingsAccount, Integer transferType) {
|
||||
return new AccountTransferDetails(fromOffice, fromClient, null, null, fromCurrentAccount, toOffice, toClient, toSavingsAccount,
|
||||
null, null, transferType, null);
|
||||
}
|
||||
|
||||
public static AccountTransferDetails savingsToCurrentTransfer(final Office fromOffice, final Client fromClient,
|
||||
final SavingsAccount fromSavingsAccount, final Office toOffice, final Client toClient,
|
||||
final CurrentAccount toCurrentAccount, Integer transferType) {
|
||||
return new AccountTransferDetails(fromOffice, fromClient, fromSavingsAccount, null, null, toOffice, toClient, null, null,
|
||||
toCurrentAccount, transferType, null);
|
||||
}
|
||||
|
||||
public static AccountTransferDetails currentToLoanTransfer(final Office fromOffice, final Client fromClient,
|
||||
final CurrentAccount fromCurrentAccount, final Office toOffice, final Client toClient,
|
||||
final Loan toLoanAccount, Integer transferType) {
|
||||
return new AccountTransferDetails(fromOffice, fromClient, null, null, fromCurrentAccount, toOffice, toClient, null, toLoanAccount,
|
||||
null, transferType, null);
|
||||
}
|
||||
|
||||
public List<AccountTransferTransaction> getAccountTransferTransactions() {
|
||||
return accountTransferTransactions;
|
||||
}
|
||||
}
|
||||
|
||||
+302
-290
@@ -1,290 +1,302 @@
|
||||
/**
|
||||
* 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.account.domain;
|
||||
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.transferTypeParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.STANDING_INSTRUCTION_RESOURCE_NAME;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.amountParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.instructionTypeParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.priorityParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.recurrenceFrequencyParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.recurrenceIntervalParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.recurrenceOnMonthDayParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.recurrenceTypeParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.statusParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.validFromParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.validTillParamName;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.MonthDay;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_account_transfer_standing_instructions", uniqueConstraints = {
|
||||
@UniqueConstraint(columnNames = { "name" }, name = "name") })
|
||||
public class AccountTransferStandingInstruction extends AbstractPersistableCustom<Long> {
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "account_transfer_details_id", nullable = true)
|
||||
private AccountTransferDetails accountTransferDetails;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
|
||||
@Column(name = "priority")
|
||||
private Integer priority;
|
||||
|
||||
@Column(name = "instruction_type")
|
||||
private Integer instructionType;
|
||||
|
||||
@Column(name = "status")
|
||||
private Integer status;
|
||||
|
||||
@Column(name = "amount", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal amount;
|
||||
|
||||
@Column(name = "valid_from")
|
||||
private LocalDate validFrom;
|
||||
|
||||
@Column(name = "valid_till")
|
||||
private LocalDate validTill;
|
||||
|
||||
@Column(name = "recurrence_type")
|
||||
private Integer recurrenceType;
|
||||
|
||||
@Column(name = "recurrence_frequency")
|
||||
private Integer recurrenceFrequency;
|
||||
|
||||
@Column(name = "recurrence_interval")
|
||||
private Integer recurrenceInterval;
|
||||
|
||||
@Column(name = "recurrence_on_day")
|
||||
private Integer recurrenceOnDay;
|
||||
|
||||
@Column(name = "recurrence_on_month")
|
||||
private Integer recurrenceOnMonth;
|
||||
|
||||
@Column(name = "last_run_date")
|
||||
private LocalDate latsRunDate;
|
||||
|
||||
protected AccountTransferStandingInstruction() {
|
||||
|
||||
}
|
||||
|
||||
public static AccountTransferStandingInstruction create(final AccountTransferDetails accountTransferDetails, final String name,
|
||||
final Integer priority, final Integer instructionType, final Integer status, final BigDecimal amount, final LocalDate validFrom,
|
||||
final LocalDate validTill, final Integer recurrenceType, final Integer recurrenceFrequency, final Integer recurrenceInterval,
|
||||
final MonthDay recurrenceOnMonthDay) {
|
||||
Integer recurrenceOnDay = null;
|
||||
Integer recurrenceOnMonth = null;
|
||||
if (recurrenceOnMonthDay != null) {
|
||||
recurrenceOnDay = recurrenceOnMonthDay.getDayOfMonth();
|
||||
recurrenceOnMonth = recurrenceOnMonthDay.getMonthValue();
|
||||
}
|
||||
return new AccountTransferStandingInstruction(accountTransferDetails, name, priority, instructionType, status, amount, validFrom,
|
||||
validTill, recurrenceType, recurrenceFrequency, recurrenceInterval, recurrenceOnDay, recurrenceOnMonth);
|
||||
}
|
||||
|
||||
private AccountTransferStandingInstruction(final AccountTransferDetails accountTransferDetails, final String name,
|
||||
final Integer priority, final Integer instructionType, final Integer status, final BigDecimal amount, final LocalDate validFrom,
|
||||
final LocalDate validTill, final Integer recurrenceType, final Integer recurrenceFrequency, final Integer recurrenceInterval,
|
||||
final Integer recurrenceOnDay, final Integer recurrenceOnMonth) {
|
||||
this.accountTransferDetails = accountTransferDetails;
|
||||
this.name = name;
|
||||
this.priority = priority;
|
||||
this.instructionType = instructionType;
|
||||
this.status = status;
|
||||
this.amount = amount;
|
||||
this.validFrom = validFrom;
|
||||
this.validTill = validTill;
|
||||
this.recurrenceType = recurrenceType;
|
||||
this.recurrenceFrequency = recurrenceFrequency;
|
||||
this.recurrenceInterval = recurrenceInterval;
|
||||
this.recurrenceOnDay = recurrenceOnDay;
|
||||
this.recurrenceOnMonth = recurrenceOnMonth;
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(STANDING_INSTRUCTION_RESOURCE_NAME);
|
||||
|
||||
validateDependencies(baseDataValidator);
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Object> update(JsonCommand command) {
|
||||
final Map<String, Object> actualChanges = new HashMap<>();
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(STANDING_INSTRUCTION_RESOURCE_NAME);
|
||||
|
||||
if (StandingInstructionStatus.fromInt(this.status).isDeleted()) {
|
||||
baseDataValidator.reset().parameter(statusParamName).failWithCode("can.not.modify.once.deleted");
|
||||
}
|
||||
|
||||
if (command.isChangeInDateParameterNamed(validFromParamName, this.validFrom)) {
|
||||
this.validFrom = command.localDateValueOfParameterNamed(validFromParamName);
|
||||
actualChanges.put(validFromParamName, this.validFrom);
|
||||
}
|
||||
|
||||
if (command.isChangeInDateParameterNamed(validTillParamName, this.validTill)) {
|
||||
this.validTill = command.localDateValueOfParameterNamed(validTillParamName);
|
||||
actualChanges.put(validTillParamName, this.validTill);
|
||||
}
|
||||
|
||||
if (command.isChangeInBigDecimalParameterNamed(amountParamName, this.amount)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(amountParamName);
|
||||
actualChanges.put(amountParamName, newValue);
|
||||
this.amount = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(statusParamName, this.status)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(statusParamName);
|
||||
actualChanges.put(statusParamName, newValue);
|
||||
this.status = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(priorityParamName, this.priority)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(priorityParamName);
|
||||
actualChanges.put(priorityParamName, newValue);
|
||||
this.priority = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(instructionTypeParamName, this.instructionType)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(instructionTypeParamName);
|
||||
actualChanges.put(instructionTypeParamName, newValue);
|
||||
this.instructionType = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(recurrenceTypeParamName, this.recurrenceType)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(recurrenceTypeParamName);
|
||||
actualChanges.put(recurrenceTypeParamName, newValue);
|
||||
this.recurrenceType = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(recurrenceFrequencyParamName, this.recurrenceFrequency)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(recurrenceFrequencyParamName);
|
||||
actualChanges.put(recurrenceFrequencyParamName, newValue);
|
||||
this.recurrenceFrequency = newValue;
|
||||
}
|
||||
|
||||
if (command.hasParameter(recurrenceOnMonthDayParamName)) {
|
||||
final MonthDay monthDay = command.extractMonthDayNamed(recurrenceOnMonthDayParamName);
|
||||
final String actualValueEntered = command.stringValueOfParameterNamed(recurrenceOnMonthDayParamName);
|
||||
final Integer dayOfMonthValue = monthDay.getDayOfMonth();
|
||||
if (!this.recurrenceOnDay.equals(dayOfMonthValue)) {
|
||||
actualChanges.put(recurrenceOnMonthDayParamName, actualValueEntered);
|
||||
this.recurrenceOnDay = dayOfMonthValue;
|
||||
}
|
||||
|
||||
final Integer monthOfYear = monthDay.getMonthValue();
|
||||
if (!this.recurrenceOnMonth.equals(monthOfYear)) {
|
||||
actualChanges.put(recurrenceOnMonthDayParamName, actualValueEntered);
|
||||
this.recurrenceOnMonth = monthOfYear;
|
||||
}
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(recurrenceIntervalParamName, this.recurrenceInterval)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(recurrenceIntervalParamName);
|
||||
actualChanges.put(recurrenceIntervalParamName, newValue);
|
||||
this.recurrenceInterval = newValue;
|
||||
}
|
||||
validateDependencies(baseDataValidator);
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
private void validateDependencies(final DataValidatorBuilder baseDataValidator) {
|
||||
|
||||
if (this.validTill != null && this.validFrom != null) {
|
||||
baseDataValidator.reset().parameter(validTillParamName).value(this.validTill).validateDateAfter(this.validFrom);
|
||||
}
|
||||
|
||||
if (AccountTransferRecurrenceType.fromInt(recurrenceType).isPeriodicRecurrence()) {
|
||||
baseDataValidator.reset().parameter(recurrenceFrequencyParamName).value(this.recurrenceFrequency).notNull();
|
||||
baseDataValidator.reset().parameter(recurrenceIntervalParamName).value(this.recurrenceInterval).notNull();
|
||||
if (this.recurrenceFrequency != null) {
|
||||
PeriodFrequencyType frequencyType = PeriodFrequencyType.fromInt(this.recurrenceFrequency);
|
||||
if (frequencyType.isMonthly()) {
|
||||
baseDataValidator.reset().parameter(recurrenceOnMonthDayParamName).value(this.recurrenceOnDay).notNull();
|
||||
} else if (frequencyType.isYearly()) {
|
||||
baseDataValidator.reset().parameter(recurrenceOnMonthDayParamName).value(this.recurrenceOnDay).notNull();
|
||||
baseDataValidator.reset().parameter(recurrenceOnMonthDayParamName).value(this.recurrenceOnMonth).notNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.accountTransferDetails.toSavingsAccount() != null) {
|
||||
baseDataValidator.reset().parameter(instructionTypeParamName).value(this.instructionType).notNull().inMinMaxRange(1, 1);
|
||||
baseDataValidator.reset().parameter(recurrenceTypeParamName).value(this.recurrenceType).notNull().inMinMaxRange(1, 1);
|
||||
}
|
||||
|
||||
if (StandingInstructionType.fromInt(this.instructionType).isFixedAmoutTransfer()) {
|
||||
baseDataValidator.reset().parameter(amountParamName).value(this.amount).notNull();
|
||||
}
|
||||
|
||||
String errorCode = null;
|
||||
if (this.accountTransferDetails.transferType().isAccountTransfer()
|
||||
&& (this.accountTransferDetails.fromSavingsAccount() == null || this.accountTransferDetails.toSavingsAccount() == null)) {
|
||||
errorCode = "not.account.transfer";
|
||||
} else if (this.accountTransferDetails.transferType().isLoanRepayment()
|
||||
&& (this.accountTransferDetails.fromSavingsAccount() == null || this.accountTransferDetails.toLoanAccount() == null)) {
|
||||
errorCode = "not.loan.repayment";
|
||||
}
|
||||
if (errorCode != null) {
|
||||
baseDataValidator.reset().parameter(transferTypeParamName).failWithCode(errorCode);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void updateLatsRunDate(LocalDate latsRunDate) {
|
||||
this.latsRunDate = latsRunDate;
|
||||
}
|
||||
|
||||
public void updateStatus(Integer status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* delete the standing instruction by setting the status to 3 and appending "_deleted_" and the id to the name
|
||||
**/
|
||||
public void delete() {
|
||||
this.status = StandingInstructionStatus.DELETED.getValue();
|
||||
this.name = this.name + "_deleted_" + this.getId();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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.account.domain;
|
||||
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.transferTypeParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.STANDING_INSTRUCTION_RESOURCE_NAME;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.amountParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.instructionTypeParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.priorityParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.recurrenceFrequencyParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.recurrenceIntervalParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.recurrenceOnMonthDayParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.recurrenceTypeParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.statusParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.validFromParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.validTillParamName;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.MonthDay;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_account_transfer_standing_instructions", uniqueConstraints = {
|
||||
@UniqueConstraint(columnNames = { "name" }, name = "name") })
|
||||
public class AccountTransferStandingInstruction extends AbstractPersistableCustom<Long> {
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "account_transfer_details_id", nullable = true)
|
||||
private AccountTransferDetails accountTransferDetails;
|
||||
|
||||
@Column(name = "name")
|
||||
private String name;
|
||||
|
||||
@Column(name = "priority")
|
||||
private Integer priority;
|
||||
|
||||
@Column(name = "instruction_type")
|
||||
private Integer instructionType;
|
||||
|
||||
@Column(name = "status")
|
||||
private Integer status;
|
||||
|
||||
@Column(name = "amount", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal amount;
|
||||
|
||||
@Column(name = "valid_from")
|
||||
private LocalDate validFrom;
|
||||
|
||||
@Column(name = "valid_till")
|
||||
private LocalDate validTill;
|
||||
|
||||
@Column(name = "recurrence_type")
|
||||
private Integer recurrenceType;
|
||||
|
||||
@Column(name = "recurrence_frequency")
|
||||
private Integer recurrenceFrequency;
|
||||
|
||||
@Column(name = "recurrence_interval")
|
||||
private Integer recurrenceInterval;
|
||||
|
||||
@Column(name = "recurrence_on_day")
|
||||
private Integer recurrenceOnDay;
|
||||
|
||||
@Column(name = "recurrence_on_month")
|
||||
private Integer recurrenceOnMonth;
|
||||
|
||||
@Column(name = "last_run_date")
|
||||
private LocalDate latsRunDate;
|
||||
|
||||
protected AccountTransferStandingInstruction() {
|
||||
|
||||
}
|
||||
|
||||
public static AccountTransferStandingInstruction create(final AccountTransferDetails accountTransferDetails, final String name,
|
||||
final Integer priority, final Integer instructionType, final Integer status, final BigDecimal amount, final LocalDate validFrom,
|
||||
final LocalDate validTill, final Integer recurrenceType, final Integer recurrenceFrequency, final Integer recurrenceInterval,
|
||||
final MonthDay recurrenceOnMonthDay) {
|
||||
Integer recurrenceOnDay = null;
|
||||
Integer recurrenceOnMonth = null;
|
||||
if (recurrenceOnMonthDay != null) {
|
||||
recurrenceOnDay = recurrenceOnMonthDay.getDayOfMonth();
|
||||
recurrenceOnMonth = recurrenceOnMonthDay.getMonthValue();
|
||||
}
|
||||
return new AccountTransferStandingInstruction(accountTransferDetails, name, priority, instructionType, status, amount, validFrom,
|
||||
validTill, recurrenceType, recurrenceFrequency, recurrenceInterval, recurrenceOnDay, recurrenceOnMonth);
|
||||
}
|
||||
|
||||
private AccountTransferStandingInstruction(final AccountTransferDetails accountTransferDetails, final String name,
|
||||
final Integer priority, final Integer instructionType, final Integer status, final BigDecimal amount, final LocalDate validFrom,
|
||||
final LocalDate validTill, final Integer recurrenceType, final Integer recurrenceFrequency, final Integer recurrenceInterval,
|
||||
final Integer recurrenceOnDay, final Integer recurrenceOnMonth) {
|
||||
this.accountTransferDetails = accountTransferDetails;
|
||||
this.name = name;
|
||||
this.priority = priority;
|
||||
this.instructionType = instructionType;
|
||||
this.status = status;
|
||||
this.amount = amount;
|
||||
this.validFrom = validFrom;
|
||||
this.validTill = validTill;
|
||||
this.recurrenceType = recurrenceType;
|
||||
this.recurrenceFrequency = recurrenceFrequency;
|
||||
this.recurrenceInterval = recurrenceInterval;
|
||||
this.recurrenceOnDay = recurrenceOnDay;
|
||||
this.recurrenceOnMonth = recurrenceOnMonth;
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(STANDING_INSTRUCTION_RESOURCE_NAME);
|
||||
|
||||
validateDependencies(baseDataValidator);
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Object> update(JsonCommand command) {
|
||||
final Map<String, Object> actualChanges = new HashMap<>();
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(STANDING_INSTRUCTION_RESOURCE_NAME);
|
||||
|
||||
if (StandingInstructionStatus.fromInt(this.status).isDeleted()) {
|
||||
baseDataValidator.reset().parameter(statusParamName).failWithCode("can.not.modify.once.deleted");
|
||||
}
|
||||
|
||||
if (command.isChangeInDateParameterNamed(validFromParamName, this.validFrom)) {
|
||||
this.validFrom = command.localDateValueOfParameterNamed(validFromParamName);
|
||||
actualChanges.put(validFromParamName, this.validFrom);
|
||||
}
|
||||
|
||||
if (command.isChangeInDateParameterNamed(validTillParamName, this.validTill)) {
|
||||
this.validTill = command.localDateValueOfParameterNamed(validTillParamName);
|
||||
actualChanges.put(validTillParamName, this.validTill);
|
||||
}
|
||||
|
||||
if (command.isChangeInBigDecimalParameterNamed(amountParamName, this.amount)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(amountParamName);
|
||||
actualChanges.put(amountParamName, newValue);
|
||||
this.amount = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(statusParamName, this.status)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(statusParamName);
|
||||
actualChanges.put(statusParamName, newValue);
|
||||
this.status = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(priorityParamName, this.priority)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(priorityParamName);
|
||||
actualChanges.put(priorityParamName, newValue);
|
||||
this.priority = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(instructionTypeParamName, this.instructionType)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(instructionTypeParamName);
|
||||
actualChanges.put(instructionTypeParamName, newValue);
|
||||
this.instructionType = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(recurrenceTypeParamName, this.recurrenceType)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(recurrenceTypeParamName);
|
||||
actualChanges.put(recurrenceTypeParamName, newValue);
|
||||
this.recurrenceType = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(recurrenceFrequencyParamName, this.recurrenceFrequency)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(recurrenceFrequencyParamName);
|
||||
actualChanges.put(recurrenceFrequencyParamName, newValue);
|
||||
this.recurrenceFrequency = newValue;
|
||||
}
|
||||
|
||||
if (command.hasParameter(recurrenceOnMonthDayParamName)) {
|
||||
final MonthDay monthDay = command.extractMonthDayNamed(recurrenceOnMonthDayParamName);
|
||||
final String actualValueEntered = command.stringValueOfParameterNamed(recurrenceOnMonthDayParamName);
|
||||
final Integer dayOfMonthValue = monthDay.getDayOfMonth();
|
||||
if (!this.recurrenceOnDay.equals(dayOfMonthValue)) {
|
||||
actualChanges.put(recurrenceOnMonthDayParamName, actualValueEntered);
|
||||
this.recurrenceOnDay = dayOfMonthValue;
|
||||
}
|
||||
|
||||
final Integer monthOfYear = monthDay.getMonthValue();
|
||||
if (!this.recurrenceOnMonth.equals(monthOfYear)) {
|
||||
actualChanges.put(recurrenceOnMonthDayParamName, actualValueEntered);
|
||||
this.recurrenceOnMonth = monthOfYear;
|
||||
}
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(recurrenceIntervalParamName, this.recurrenceInterval)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(recurrenceIntervalParamName);
|
||||
actualChanges.put(recurrenceIntervalParamName, newValue);
|
||||
this.recurrenceInterval = newValue;
|
||||
}
|
||||
validateDependencies(baseDataValidator);
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
private void validateDependencies(final DataValidatorBuilder baseDataValidator) {
|
||||
|
||||
if (this.validTill != null && this.validFrom != null) {
|
||||
baseDataValidator.reset().parameter(validTillParamName).value(this.validTill).validateDateAfter(this.validFrom);
|
||||
}
|
||||
|
||||
if (AccountTransferRecurrenceType.fromInt(recurrenceType).isPeriodicRecurrence()) {
|
||||
baseDataValidator.reset().parameter(recurrenceFrequencyParamName).value(this.recurrenceFrequency).notNull();
|
||||
baseDataValidator.reset().parameter(recurrenceIntervalParamName).value(this.recurrenceInterval).notNull();
|
||||
if (this.recurrenceFrequency != null) {
|
||||
PeriodFrequencyType frequencyType = PeriodFrequencyType.fromInt(this.recurrenceFrequency);
|
||||
if (frequencyType.isMonthly()) {
|
||||
baseDataValidator.reset().parameter(recurrenceOnMonthDayParamName).value(this.recurrenceOnDay).notNull();
|
||||
} else if (frequencyType.isYearly()) {
|
||||
baseDataValidator.reset().parameter(recurrenceOnMonthDayParamName).value(this.recurrenceOnDay).notNull();
|
||||
baseDataValidator.reset().parameter(recurrenceOnMonthDayParamName).value(this.recurrenceOnMonth).notNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For savings-to-savings or current-to-savings: enforce Fixed instruction + Periodic recurrence
|
||||
if (this.accountTransferDetails.toSavingsAccount() != null
|
||||
|| this.accountTransferDetails.toCurrentAccount() != null) {
|
||||
baseDataValidator.reset().parameter(instructionTypeParamName).value(this.instructionType).notNull().inMinMaxRange(1, 1);
|
||||
baseDataValidator.reset().parameter(recurrenceTypeParamName).value(this.recurrenceType).notNull().inMinMaxRange(1, 1);
|
||||
}
|
||||
|
||||
if (StandingInstructionType.fromInt(this.instructionType).isFixedAmoutTransfer()) {
|
||||
baseDataValidator.reset().parameter(amountParamName).value(this.amount).notNull();
|
||||
}
|
||||
|
||||
// Account Transfer: from must be savings OR current; to must be savings OR current
|
||||
boolean fromAccountValid = this.accountTransferDetails.fromSavingsAccount() != null
|
||||
|| this.accountTransferDetails.fromCurrentAccount() != null;
|
||||
boolean toAccountValid = this.accountTransferDetails.toSavingsAccount() != null
|
||||
|| this.accountTransferDetails.toCurrentAccount() != null;
|
||||
|
||||
// Loan Repayment: from must be savings OR current; to must be loan
|
||||
boolean fromAccountValidForLoan = this.accountTransferDetails.fromSavingsAccount() != null
|
||||
|| this.accountTransferDetails.fromCurrentAccount() != null;
|
||||
|
||||
String errorCode = null;
|
||||
if (this.accountTransferDetails.transferType().isAccountTransfer()
|
||||
&& !(fromAccountValid && toAccountValid)) {
|
||||
errorCode = "not.account.transfer";
|
||||
} else if (this.accountTransferDetails.transferType().isLoanRepayment()
|
||||
&& !(fromAccountValidForLoan && this.accountTransferDetails.toLoanAccount() != null)) {
|
||||
errorCode = "not.loan.repayment";
|
||||
}
|
||||
if (errorCode != null) {
|
||||
baseDataValidator.reset().parameter(transferTypeParamName).failWithCode(errorCode);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void updateLatsRunDate(LocalDate latsRunDate) {
|
||||
this.latsRunDate = latsRunDate;
|
||||
}
|
||||
|
||||
public void updateStatus(Integer status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* delete the standing instruction by setting the status to 3 and appending "_deleted_" and the id to the name
|
||||
**/
|
||||
public void delete() {
|
||||
this.status = StandingInstructionStatus.DELETED.getValue();
|
||||
this.name = this.name + "_deleted_" + this.getId();
|
||||
}
|
||||
}
|
||||
|
||||
+143
-93
@@ -1,93 +1,143 @@
|
||||
/**
|
||||
* 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.account.domain;
|
||||
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.amountParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.instructionTypeParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.nameParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.priorityParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.recurrenceFrequencyParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.recurrenceIntervalParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.recurrenceOnMonthDayParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.recurrenceTypeParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.statusParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.validFromParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.validTillParamName;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.MonthDay;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class StandingInstructionAssembler {
|
||||
|
||||
private final AccountTransferDetailAssembler accountTransferDetailAssembler;
|
||||
|
||||
@Autowired
|
||||
public StandingInstructionAssembler(final AccountTransferDetailAssembler accountTransferDetailAssembler) {
|
||||
|
||||
this.accountTransferDetailAssembler = accountTransferDetailAssembler;
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleSavingsToSavingsTransfer(final JsonCommand command) {
|
||||
final AccountTransferDetails accountTransferDetails = this.accountTransferDetailAssembler.assembleSavingsToSavingsTransfer(command);
|
||||
assembleStandingInstruction(command, accountTransferDetails);
|
||||
return accountTransferDetails;
|
||||
}
|
||||
|
||||
public void assembleStandingInstruction(final JsonCommand command, final AccountTransferDetails accountTransferDetails) {
|
||||
final LocalDate validFrom = command.localDateValueOfParameterNamed(validFromParamName);
|
||||
final LocalDate validTill = command.localDateValueOfParameterNamed(validTillParamName);
|
||||
BigDecimal amount = null;
|
||||
final BigDecimal transferAmount = command.bigDecimalValueOfParameterNamed(amountParamName);
|
||||
if (transferAmount != null) {
|
||||
final Money monetaryAmount = Money.of(accountTransferDetails.fromSavingsAccount().getCurrency(), transferAmount);
|
||||
amount = monetaryAmount.getAmount();
|
||||
}
|
||||
final Integer status = command.integerValueOfParameterNamed(statusParamName);
|
||||
final Integer priority = command.integerValueOfParameterNamed(priorityParamName);
|
||||
final Integer standingInstructionType = command.integerValueOfParameterNamed(instructionTypeParamName);
|
||||
final Integer recurrenceType = command.integerValueOfParameterNamed(recurrenceTypeParamName);
|
||||
final Integer recurrenceFrequency = command.integerValueOfParameterNamed(recurrenceFrequencyParamName);
|
||||
final MonthDay recurrenceOnMonthDay = command.extractMonthDayNamed(recurrenceOnMonthDayParamName);
|
||||
final Integer recurrenceInterval = command.integerValueOfParameterNamed(recurrenceIntervalParamName);
|
||||
final String name = command.stringValueOfParameterNamed(nameParamName);
|
||||
AccountTransferStandingInstruction accountTransferStandingInstruction = AccountTransferStandingInstruction.create(
|
||||
accountTransferDetails, name, priority, standingInstructionType, status, amount, validFrom, validTill, recurrenceType,
|
||||
recurrenceFrequency, recurrenceInterval, recurrenceOnMonthDay);
|
||||
accountTransferDetails.updateAccountTransferStandingInstruction(accountTransferStandingInstruction);
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleSavingsToLoanTransfer(final JsonCommand command) {
|
||||
final AccountTransferDetails accountTransferDetails = this.accountTransferDetailAssembler.assembleSavingsToLoanTransfer(command);
|
||||
assembleStandingInstruction(command, accountTransferDetails);
|
||||
return accountTransferDetails;
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleLoanToSavingsTransfer(final JsonCommand command) {
|
||||
final AccountTransferDetails accountTransferDetails = this.accountTransferDetailAssembler.assembleLoanToSavingsTransfer(command);
|
||||
assembleStandingInstruction(command, accountTransferDetails);
|
||||
return accountTransferDetails;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* 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.account.domain;
|
||||
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.amountParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.instructionTypeParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.nameParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.priorityParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.recurrenceFrequencyParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.recurrenceIntervalParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.recurrenceOnMonthDayParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.recurrenceTypeParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.statusParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.validFromParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.validTillParamName;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.MonthDay;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.portfolio.currentaccount.domain.CurrentAccount;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class StandingInstructionAssembler {
|
||||
|
||||
private final AccountTransferDetailAssembler accountTransferDetailAssembler;
|
||||
|
||||
@Autowired
|
||||
public StandingInstructionAssembler(final AccountTransferDetailAssembler accountTransferDetailAssembler) {
|
||||
|
||||
this.accountTransferDetailAssembler = accountTransferDetailAssembler;
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleSavingsToSavingsTransfer(final JsonCommand command) {
|
||||
final AccountTransferDetails accountTransferDetails = this.accountTransferDetailAssembler.assembleSavingsToSavingsTransfer(command);
|
||||
assembleStandingInstruction(command, accountTransferDetails);
|
||||
return accountTransferDetails;
|
||||
}
|
||||
|
||||
public void assembleStandingInstruction(final JsonCommand command, final AccountTransferDetails accountTransferDetails) {
|
||||
final LocalDate validFrom = command.localDateValueOfParameterNamed(validFromParamName);
|
||||
final LocalDate validTill = command.localDateValueOfParameterNamed(validTillParamName);
|
||||
BigDecimal amount = null;
|
||||
final BigDecimal transferAmount = command.bigDecimalValueOfParameterNamed(amountParamName);
|
||||
if (transferAmount != null) {
|
||||
final MonetaryCurrency currency = resolveCurrency(accountTransferDetails);
|
||||
if (currency != null) {
|
||||
final Money monetaryAmount = Money.of(currency, transferAmount);
|
||||
amount = monetaryAmount.getAmount();
|
||||
} else {
|
||||
amount = transferAmount;
|
||||
}
|
||||
}
|
||||
final Integer status = command.integerValueOfParameterNamed(statusParamName);
|
||||
final Integer priority = command.integerValueOfParameterNamed(priorityParamName);
|
||||
final Integer standingInstructionType = command.integerValueOfParameterNamed(instructionTypeParamName);
|
||||
final Integer recurrenceType = command.integerValueOfParameterNamed(recurrenceTypeParamName);
|
||||
final Integer recurrenceFrequency = command.integerValueOfParameterNamed(recurrenceFrequencyParamName);
|
||||
final MonthDay recurrenceOnMonthDay = command.extractMonthDayNamed(recurrenceOnMonthDayParamName);
|
||||
final Integer recurrenceInterval = command.integerValueOfParameterNamed(recurrenceIntervalParamName);
|
||||
final String name = command.stringValueOfParameterNamed(nameParamName);
|
||||
AccountTransferStandingInstruction accountTransferStandingInstruction = AccountTransferStandingInstruction.create(
|
||||
accountTransferDetails, name, priority, standingInstructionType, status, amount, validFrom, validTill, recurrenceType,
|
||||
recurrenceFrequency, recurrenceInterval, recurrenceOnMonthDay);
|
||||
accountTransferDetails.updateAccountTransferStandingInstruction(accountTransferStandingInstruction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the currency from the "from" account — savings, loan (null), or current account.
|
||||
*/
|
||||
private MonetaryCurrency resolveCurrency(final AccountTransferDetails details) {
|
||||
final SavingsAccount fromSavings = details.fromSavingsAccount();
|
||||
if (fromSavings != null) {
|
||||
return fromSavings.getCurrency();
|
||||
}
|
||||
final CurrentAccount fromCurrent = details.fromCurrentAccount();
|
||||
if (fromCurrent != null) {
|
||||
return new MonetaryCurrency(fromCurrent.getCurrencyCode(), fromCurrent.getCurrencyDigits(),
|
||||
fromCurrent.getCurrencyMultiplesOf());
|
||||
}
|
||||
return null; // loan accounts don't have a direct currency on AccountTransferDetails
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleSavingsToLoanTransfer(final JsonCommand command) {
|
||||
final AccountTransferDetails accountTransferDetails = this.accountTransferDetailAssembler.assembleSavingsToLoanTransfer(command);
|
||||
assembleStandingInstruction(command, accountTransferDetails);
|
||||
return accountTransferDetails;
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleLoanToSavingsTransfer(final JsonCommand command) {
|
||||
final AccountTransferDetails accountTransferDetails = this.accountTransferDetailAssembler.assembleLoanToSavingsTransfer(command);
|
||||
assembleStandingInstruction(command, accountTransferDetails);
|
||||
return accountTransferDetails;
|
||||
}
|
||||
|
||||
// --- Current account methods ---
|
||||
|
||||
public AccountTransferDetails assembleCurrentToCurrentTransfer(final JsonCommand command) {
|
||||
final AccountTransferDetails accountTransferDetails = this.accountTransferDetailAssembler.assembleCurrentToCurrentTransfer(command);
|
||||
assembleStandingInstruction(command, accountTransferDetails);
|
||||
return accountTransferDetails;
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleCurrentToSavingsTransfer(final JsonCommand command) {
|
||||
final AccountTransferDetails accountTransferDetails = this.accountTransferDetailAssembler.assembleCurrentToSavingsTransfer(command);
|
||||
assembleStandingInstruction(command, accountTransferDetails);
|
||||
return accountTransferDetails;
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleSavingsToCurrentTransfer(final JsonCommand command) {
|
||||
final AccountTransferDetails accountTransferDetails = this.accountTransferDetailAssembler.assembleSavingsToCurrentTransfer(command);
|
||||
assembleStandingInstruction(command, accountTransferDetails);
|
||||
return accountTransferDetails;
|
||||
}
|
||||
|
||||
public AccountTransferDetails assembleCurrentToLoanTransfer(final JsonCommand command) {
|
||||
final AccountTransferDetails accountTransferDetails = this.accountTransferDetailAssembler.assembleCurrentToLoanTransfer(command);
|
||||
assembleStandingInstruction(command, accountTransferDetails);
|
||||
return accountTransferDetails;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+172
-172
@@ -1,172 +1,172 @@
|
||||
/**
|
||||
* 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.account.jobs.executestandinginstructions;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformServiceUnavailableException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
|
||||
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
|
||||
import org.apache.fineract.portfolio.account.data.AccountTransferDTO;
|
||||
import org.apache.fineract.portfolio.account.data.StandingInstructionData;
|
||||
import org.apache.fineract.portfolio.account.data.StandingInstructionDuesData;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferRecurrenceType;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionStatus;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionType;
|
||||
import org.apache.fineract.portfolio.account.service.AccountTransfersWritePlatformService;
|
||||
import org.apache.fineract.portfolio.account.service.StandingInstructionReadPlatformService;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.DefaultScheduledDateGenerator;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.ScheduledDateGenerator;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
|
||||
import org.apache.fineract.portfolio.savings.exception.InsufficientAccountBalanceException;
|
||||
import org.springframework.batch.core.StepContribution;
|
||||
import org.springframework.batch.core.scope.context.ChunkContext;
|
||||
import org.springframework.batch.core.step.tasklet.Tasklet;
|
||||
import org.springframework.batch.repeat.RepeatStatus;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class ExecuteStandingInstructionsTasklet implements Tasklet {
|
||||
|
||||
private final StandingInstructionReadPlatformService standingInstructionReadPlatformService;
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final DatabaseSpecificSQLGenerator sqlGenerator;
|
||||
private final AccountTransfersWritePlatformService accountTransfersWritePlatformService;
|
||||
|
||||
@Override
|
||||
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
|
||||
Collection<StandingInstructionData> instructionData = standingInstructionReadPlatformService
|
||||
.retrieveAll(StandingInstructionStatus.ACTIVE.getValue());
|
||||
List<Throwable> errors = new ArrayList<>();
|
||||
for (StandingInstructionData data : instructionData) {
|
||||
boolean isDueForTransfer = false;
|
||||
AccountTransferRecurrenceType recurrenceType = data.getRecurrenceType();
|
||||
StandingInstructionType instructionType = data.getInstructionType();
|
||||
LocalDate transactionDate = DateUtils.getBusinessLocalDate();
|
||||
if (recurrenceType.isPeriodicRecurrence()) {
|
||||
final ScheduledDateGenerator scheduledDateGenerator = new DefaultScheduledDateGenerator();
|
||||
PeriodFrequencyType frequencyType = data.getRecurrenceFrequency();
|
||||
LocalDate startDate = data.getValidFrom();
|
||||
if (frequencyType.isMonthly()) {
|
||||
startDate = startDate.withDayOfMonth(data.getRecurrenceOnDay());
|
||||
if (DateUtils.isBefore(startDate, data.getValidFrom())) {
|
||||
startDate = startDate.plusMonths(1);
|
||||
}
|
||||
} else if (frequencyType.isYearly()) {
|
||||
startDate = startDate.withDayOfMonth(data.getRecurrenceOnDay()).withMonth(data.getRecurrenceOnMonth());
|
||||
if (DateUtils.isBefore(startDate, data.getValidFrom())) {
|
||||
startDate = startDate.plusYears(1);
|
||||
}
|
||||
}
|
||||
isDueForTransfer = scheduledDateGenerator.isDateFallsInSchedule(frequencyType, data.getRecurrenceInterval(), startDate,
|
||||
transactionDate);
|
||||
|
||||
}
|
||||
BigDecimal transactionAmount = data.getAmount();
|
||||
if (data.getToAccountType().isLoanAccount()
|
||||
&& (recurrenceType.isDuesRecurrence() || (isDueForTransfer && instructionType.isDuesAmoutTransfer()))) {
|
||||
StandingInstructionDuesData standingInstructionDuesData = standingInstructionReadPlatformService
|
||||
.retriveLoanDuesData(data.getToAccount().getId());
|
||||
if (data.getInstructionType().isDuesAmoutTransfer()) {
|
||||
transactionAmount = standingInstructionDuesData.totalDueAmount();
|
||||
}
|
||||
if (recurrenceType.isDuesRecurrence()) {
|
||||
isDueForTransfer = isDueForTransfer(standingInstructionDuesData);
|
||||
}
|
||||
}
|
||||
|
||||
if (isDueForTransfer && transactionAmount != null && transactionAmount.compareTo(BigDecimal.ZERO) > 0) {
|
||||
final SavingsAccount fromSavingsAccount = null;
|
||||
final boolean isRegularTransaction = true;
|
||||
final boolean isExceptionForBalanceCheck = false;
|
||||
AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, transactionAmount,
|
||||
data.getFromAccountType(), data.getToAccountType(), data.getFromAccount().getId(), data.getToAccount().getId(),
|
||||
data.getName() + " Standing instruction trasfer ", null, null, null, null, data.toTransferType(), null, null,
|
||||
data.getTransferType().getValue(), null, null, ExternalId.empty(), null, null, fromSavingsAccount,
|
||||
isRegularTransaction, isExceptionForBalanceCheck);
|
||||
final boolean transferCompleted = transferAmount(errors, accountTransferDTO, data.getId());
|
||||
|
||||
if (transferCompleted) {
|
||||
final String updateQuery = "UPDATE m_account_transfer_standing_instructions SET last_run_date = ? where id = ?";
|
||||
jdbcTemplate.update(updateQuery, transactionDate, data.getId());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (!errors.isEmpty()) {
|
||||
throw new JobExecutionException(errors);
|
||||
}
|
||||
return RepeatStatus.FINISHED;
|
||||
}
|
||||
|
||||
private boolean transferAmount(final List<Throwable> errors, final AccountTransferDTO accountTransferDTO, final Long instructionId) {
|
||||
boolean transferCompleted = true;
|
||||
StringBuilder errorLog = new StringBuilder();
|
||||
StringBuilder updateQuery = new StringBuilder(
|
||||
"INSERT INTO m_account_transfer_standing_instructions_history (standing_instruction_id, " + sqlGenerator.escape("status")
|
||||
+ ", amount,execution_time, error_log) VALUES (");
|
||||
try {
|
||||
accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
} catch (final PlatformApiDataValidationException e) {
|
||||
errors.add(new Exception("Validation exception while transfering funds for standing Instruction id" + instructionId + " from "
|
||||
+ accountTransferDTO.getFromAccountId() + " to " + accountTransferDTO.getToAccountId(), e));
|
||||
errorLog.append("Validation exception while trasfering funds ").append(e.getDefaultUserMessage());
|
||||
} catch (final InsufficientAccountBalanceException e) {
|
||||
errors.add(new Exception("InsufficientAccountBalance Exception while trasfering funds for standing Instruction id"
|
||||
+ instructionId + " from " + accountTransferDTO.getFromAccountId() + " to " + accountTransferDTO.getToAccountId(), e));
|
||||
errorLog.append("InsufficientAccountBalance Exception ");
|
||||
} catch (final AbstractPlatformServiceUnavailableException e) {
|
||||
errors.add(new Exception("Platform exception while trasfering funds for standing Instruction id" + instructionId + " from "
|
||||
+ accountTransferDTO.getFromAccountId() + " to " + accountTransferDTO.getToAccountId(), e));
|
||||
errorLog.append("Platform exception while trasfering funds ").append(e.getDefaultUserMessage());
|
||||
} catch (Exception e) {
|
||||
errors.add(new Exception("Unhandled System Exception while trasfering funds for standing Instruction id" + instructionId
|
||||
+ " from " + accountTransferDTO.getFromAccountId() + " to " + accountTransferDTO.getToAccountId(), e));
|
||||
errorLog.append("Exception while trasfering funds ").append(e.getMessage());
|
||||
|
||||
}
|
||||
updateQuery.append(instructionId).append(",");
|
||||
if (errorLog.length() > 0) {
|
||||
transferCompleted = false;
|
||||
updateQuery.append("'failed'").append(",");
|
||||
} else {
|
||||
updateQuery.append("'success'").append(",");
|
||||
}
|
||||
updateQuery.append(accountTransferDTO.getTransactionAmount().doubleValue());
|
||||
updateQuery.append(", now(),");
|
||||
updateQuery.append("'").append(errorLog).append("')");
|
||||
jdbcTemplate.update(updateQuery.toString());
|
||||
return transferCompleted;
|
||||
}
|
||||
|
||||
public boolean isDueForTransfer(StandingInstructionDuesData standingInstructionDuesData) {
|
||||
return standingInstructionDuesData.dueDate() != null
|
||||
&& !standingInstructionDuesData.dueDate().isAfter(LocalDate.now(DateUtils.getDateTimeZoneOfTenant()));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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.account.jobs.executestandinginstructions;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformServiceUnavailableException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
|
||||
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
|
||||
import org.apache.fineract.portfolio.account.data.AccountTransferDTO;
|
||||
import org.apache.fineract.portfolio.account.data.StandingInstructionData;
|
||||
import org.apache.fineract.portfolio.account.data.StandingInstructionDuesData;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferRecurrenceType;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionStatus;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionType;
|
||||
import org.apache.fineract.portfolio.account.service.AccountTransfersWritePlatformService;
|
||||
import org.apache.fineract.portfolio.account.service.StandingInstructionReadPlatformService;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.DefaultScheduledDateGenerator;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.ScheduledDateGenerator;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
|
||||
import org.apache.fineract.portfolio.savings.exception.InsufficientAccountBalanceException;
|
||||
import org.springframework.batch.core.StepContribution;
|
||||
import org.springframework.batch.core.scope.context.ChunkContext;
|
||||
import org.springframework.batch.core.step.tasklet.Tasklet;
|
||||
import org.springframework.batch.repeat.RepeatStatus;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class ExecuteStandingInstructionsTasklet implements Tasklet {
|
||||
|
||||
private final StandingInstructionReadPlatformService standingInstructionReadPlatformService;
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final DatabaseSpecificSQLGenerator sqlGenerator;
|
||||
private final AccountTransfersWritePlatformService accountTransfersWritePlatformService;
|
||||
|
||||
@Override
|
||||
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
|
||||
Collection<StandingInstructionData> instructionData = standingInstructionReadPlatformService
|
||||
.retrieveAll(StandingInstructionStatus.ACTIVE.getValue());
|
||||
List<Throwable> errors = new ArrayList<>();
|
||||
for (StandingInstructionData data : instructionData) {
|
||||
boolean isDueForTransfer = false;
|
||||
AccountTransferRecurrenceType recurrenceType = data.recurrenceTypeEnum();
|
||||
StandingInstructionType instructionType = data.instructionTypeEnum();
|
||||
LocalDate transactionDate = DateUtils.getBusinessLocalDate();
|
||||
if (recurrenceType.isPeriodicRecurrence()) {
|
||||
final ScheduledDateGenerator scheduledDateGenerator = new DefaultScheduledDateGenerator();
|
||||
PeriodFrequencyType frequencyType = data.recurrenceFrequencyEnum();
|
||||
LocalDate startDate = data.getValidFrom();
|
||||
if (frequencyType.isMonthly()) {
|
||||
startDate = startDate.withDayOfMonth(data.getRecurrenceOnDay());
|
||||
if (DateUtils.isBefore(startDate, data.getValidFrom())) {
|
||||
startDate = startDate.plusMonths(1);
|
||||
}
|
||||
} else if (frequencyType.isYearly()) {
|
||||
startDate = startDate.withDayOfMonth(data.getRecurrenceOnDay()).withMonth(data.getRecurrenceOnMonth());
|
||||
if (DateUtils.isBefore(startDate, data.getValidFrom())) {
|
||||
startDate = startDate.plusYears(1);
|
||||
}
|
||||
}
|
||||
isDueForTransfer = scheduledDateGenerator.isDateFallsInSchedule(frequencyType, data.getRecurrenceInterval(), startDate,
|
||||
transactionDate);
|
||||
|
||||
}
|
||||
BigDecimal transactionAmount = data.getAmount();
|
||||
if (data.toAccountTypeEnum() != null && data.toAccountTypeEnum().isLoanAccount()
|
||||
&& (recurrenceType.isDuesRecurrence() || (isDueForTransfer && instructionType.isDuesAmoutTransfer()))) {
|
||||
StandingInstructionDuesData standingInstructionDuesData = standingInstructionReadPlatformService
|
||||
.retriveLoanDuesData(data.getToAccount().getId());
|
||||
if (data.instructionTypeEnum().isDuesAmoutTransfer()) {
|
||||
transactionAmount = standingInstructionDuesData.totalDueAmount();
|
||||
}
|
||||
if (recurrenceType.isDuesRecurrence()) {
|
||||
isDueForTransfer = isDueForTransfer(standingInstructionDuesData);
|
||||
}
|
||||
}
|
||||
|
||||
if (isDueForTransfer && transactionAmount != null && transactionAmount.compareTo(BigDecimal.ZERO) > 0) {
|
||||
final SavingsAccount fromSavingsAccount = null;
|
||||
final boolean isRegularTransaction = true;
|
||||
final boolean isExceptionForBalanceCheck = false;
|
||||
AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, transactionAmount,
|
||||
data.fromAccountTypeEnum(), data.toAccountTypeEnum(), data.getFromAccount().getId(), data.getToAccount().getId(),
|
||||
data.getName() + " Standing instruction trasfer ", null, null, null, null, data.toTransferType(), null, null,
|
||||
data.transferTypeEnum().getValue(), null, null, ExternalId.empty(), null, null, fromSavingsAccount,
|
||||
isRegularTransaction, isExceptionForBalanceCheck);
|
||||
final boolean transferCompleted = transferAmount(errors, accountTransferDTO, data.getId());
|
||||
|
||||
if (transferCompleted) {
|
||||
final String updateQuery = "UPDATE m_account_transfer_standing_instructions SET last_run_date = ? where id = ?";
|
||||
jdbcTemplate.update(updateQuery, transactionDate, data.getId());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (!errors.isEmpty()) {
|
||||
throw new JobExecutionException(errors);
|
||||
}
|
||||
return RepeatStatus.FINISHED;
|
||||
}
|
||||
|
||||
private boolean transferAmount(final List<Throwable> errors, final AccountTransferDTO accountTransferDTO, final Long instructionId) {
|
||||
boolean transferCompleted = true;
|
||||
StringBuilder errorLog = new StringBuilder();
|
||||
StringBuilder updateQuery = new StringBuilder(
|
||||
"INSERT INTO m_account_transfer_standing_instructions_history (standing_instruction_id, " + sqlGenerator.escape("status")
|
||||
+ ", amount,execution_time, error_log) VALUES (");
|
||||
try {
|
||||
accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
|
||||
} catch (final PlatformApiDataValidationException e) {
|
||||
errors.add(new Exception("Validation exception while transfering funds for standing Instruction id" + instructionId + " from "
|
||||
+ accountTransferDTO.getFromAccountId() + " to " + accountTransferDTO.getToAccountId(), e));
|
||||
errorLog.append("Validation exception while trasfering funds ").append(e.getDefaultUserMessage());
|
||||
} catch (final InsufficientAccountBalanceException e) {
|
||||
errors.add(new Exception("InsufficientAccountBalance Exception while trasfering funds for standing Instruction id"
|
||||
+ instructionId + " from " + accountTransferDTO.getFromAccountId() + " to " + accountTransferDTO.getToAccountId(), e));
|
||||
errorLog.append("InsufficientAccountBalance Exception ");
|
||||
} catch (final AbstractPlatformServiceUnavailableException e) {
|
||||
errors.add(new Exception("Platform exception while trasfering funds for standing Instruction id" + instructionId + " from "
|
||||
+ accountTransferDTO.getFromAccountId() + " to " + accountTransferDTO.getToAccountId(), e));
|
||||
errorLog.append("Platform exception while trasfering funds ").append(e.getDefaultUserMessage());
|
||||
} catch (Exception e) {
|
||||
errors.add(new Exception("Unhandled System Exception while trasfering funds for standing Instruction id" + instructionId
|
||||
+ " from " + accountTransferDTO.getFromAccountId() + " to " + accountTransferDTO.getToAccountId(), e));
|
||||
errorLog.append("Exception while trasfering funds ").append(e.getMessage());
|
||||
|
||||
}
|
||||
updateQuery.append(instructionId).append(",");
|
||||
if (errorLog.length() > 0) {
|
||||
transferCompleted = false;
|
||||
updateQuery.append("'failed'").append(",");
|
||||
} else {
|
||||
updateQuery.append("'success'").append(",");
|
||||
}
|
||||
updateQuery.append(accountTransferDTO.getTransactionAmount().doubleValue());
|
||||
updateQuery.append(", now(),");
|
||||
updateQuery.append("'").append(errorLog).append("')");
|
||||
jdbcTemplate.update(updateQuery.toString());
|
||||
return transferCompleted;
|
||||
}
|
||||
|
||||
public boolean isDueForTransfer(StandingInstructionDuesData standingInstructionDuesData) {
|
||||
return standingInstructionDuesData.dueDate() != null
|
||||
&& !standingInstructionDuesData.dueDate().isAfter(LocalDate.now(DateUtils.getDateTimeZoneOfTenant()));
|
||||
}
|
||||
}
|
||||
|
||||
+206
-202
@@ -1,202 +1,206 @@
|
||||
/**
|
||||
* 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.account.service;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferRecurrenceType;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferType;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionPriority;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionStatus;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionType;
|
||||
|
||||
public final class AccountTransferEnumerations {
|
||||
|
||||
private AccountTransferEnumerations() {
|
||||
|
||||
}
|
||||
|
||||
public static EnumOptionData accountType(final Integer type) {
|
||||
return accountType(PortfolioAccountType.fromInt(type));
|
||||
}
|
||||
|
||||
public static EnumOptionData accountType(final PortfolioAccountType type) {
|
||||
|
||||
EnumOptionData optionData = null;
|
||||
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
case INVALID:
|
||||
break;
|
||||
case LOAN:
|
||||
optionData = new EnumOptionData(PortfolioAccountType.LOAN.getValue().longValue(), PortfolioAccountType.LOAN.getCode(),
|
||||
"Loan Account");
|
||||
break;
|
||||
case SAVINGS:
|
||||
optionData = new EnumOptionData(PortfolioAccountType.SAVINGS.getValue().longValue(),
|
||||
PortfolioAccountType.SAVINGS.getCode(), "Savings Account");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static EnumOptionData recurrenceType(final Integer type) {
|
||||
return recurrenceType(AccountTransferRecurrenceType.fromInt(type));
|
||||
}
|
||||
|
||||
public static EnumOptionData recurrenceType(final AccountTransferRecurrenceType type) {
|
||||
EnumOptionData optionData = null;
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
case INVALID:
|
||||
break;
|
||||
case PERIODIC:
|
||||
optionData = new EnumOptionData(AccountTransferRecurrenceType.PERIODIC.getValue().longValue(),
|
||||
AccountTransferRecurrenceType.PERIODIC.getCode(), "Periodic Recurrence");
|
||||
break;
|
||||
case AS_PER_DUES:
|
||||
optionData = new EnumOptionData(AccountTransferRecurrenceType.AS_PER_DUES.getValue().longValue(),
|
||||
AccountTransferRecurrenceType.AS_PER_DUES.getCode(), "As Per Dues Recurrence");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static EnumOptionData transferType(final Integer type) {
|
||||
return transferType(AccountTransferType.fromInt(type));
|
||||
}
|
||||
|
||||
public static EnumOptionData transferType(final AccountTransferType type) {
|
||||
EnumOptionData optionData = null;
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
case INVALID:
|
||||
break;
|
||||
case ACCOUNT_TRANSFER:
|
||||
optionData = new EnumOptionData(AccountTransferType.ACCOUNT_TRANSFER.getValue().longValue(),
|
||||
AccountTransferType.ACCOUNT_TRANSFER.getCode(), "Account Transfer");
|
||||
break;
|
||||
case LOAN_REPAYMENT:
|
||||
optionData = new EnumOptionData(AccountTransferType.LOAN_REPAYMENT.getValue().longValue(),
|
||||
AccountTransferType.LOAN_REPAYMENT.getCode(), "Loan Repayment");
|
||||
break;
|
||||
case CHARGE_PAYMENT:
|
||||
optionData = new EnumOptionData(AccountTransferType.CHARGE_PAYMENT.getValue().longValue(),
|
||||
AccountTransferType.CHARGE_PAYMENT.getCode(), "Charge Payment");
|
||||
break;
|
||||
case INTEREST_TRANSFER:
|
||||
optionData = new EnumOptionData(AccountTransferType.INTEREST_TRANSFER.getValue().longValue(),
|
||||
AccountTransferType.INTEREST_TRANSFER.getCode(), "Interest Transfer");
|
||||
break;
|
||||
case LOAN_DOWN_PAYMENT:
|
||||
optionData = new EnumOptionData(AccountTransferType.LOAN_DOWN_PAYMENT.getValue().longValue(),
|
||||
AccountTransferType.LOAN_DOWN_PAYMENT.getCode(), "Loan Down Payment");
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static EnumOptionData standingInstructionPriority(final Integer type) {
|
||||
return standingInstructionPriority(StandingInstructionPriority.fromInt(type));
|
||||
}
|
||||
|
||||
public static EnumOptionData standingInstructionPriority(final StandingInstructionPriority type) {
|
||||
EnumOptionData optionData = null;
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
case INVALID:
|
||||
break;
|
||||
case HIGH:
|
||||
optionData = new EnumOptionData(StandingInstructionPriority.HIGH.getValue().longValue(),
|
||||
StandingInstructionPriority.HIGH.getCode(), "High Priority");
|
||||
break;
|
||||
case LOW:
|
||||
optionData = new EnumOptionData(StandingInstructionPriority.LOW.getValue().longValue(),
|
||||
StandingInstructionPriority.LOW.getCode(), "Low Priority");
|
||||
break;
|
||||
case MEDIUM:
|
||||
optionData = new EnumOptionData(StandingInstructionPriority.MEDIUM.getValue().longValue(),
|
||||
StandingInstructionPriority.MEDIUM.getCode(), "Medium Priority");
|
||||
break;
|
||||
case URGENT:
|
||||
optionData = new EnumOptionData(StandingInstructionPriority.URGENT.getValue().longValue(),
|
||||
StandingInstructionPriority.URGENT.getCode(), "Urgent Priority");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static EnumOptionData standingInstructionStatus(final Integer type) {
|
||||
return standingInstructionStatus(StandingInstructionStatus.fromInt(type));
|
||||
}
|
||||
|
||||
public static EnumOptionData standingInstructionStatus(final StandingInstructionStatus type) {
|
||||
EnumOptionData optionData = null;
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
case INVALID:
|
||||
break;
|
||||
case ACTIVE:
|
||||
optionData = new EnumOptionData(StandingInstructionStatus.ACTIVE.getValue().longValue(),
|
||||
StandingInstructionStatus.ACTIVE.getCode(), "Active");
|
||||
break;
|
||||
case DELETED:
|
||||
optionData = new EnumOptionData(StandingInstructionStatus.DELETED.getValue().longValue(),
|
||||
StandingInstructionStatus.DELETED.getCode(), "Deleted");
|
||||
break;
|
||||
case DISABLED:
|
||||
optionData = new EnumOptionData(StandingInstructionStatus.DISABLED.getValue().longValue(),
|
||||
StandingInstructionStatus.DISABLED.getCode(), "Disabled");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static EnumOptionData standingInstructionType(final Integer type) {
|
||||
return standingInstructionType(StandingInstructionType.fromInt(type));
|
||||
}
|
||||
|
||||
public static EnumOptionData standingInstructionType(final StandingInstructionType type) {
|
||||
EnumOptionData optionData = null;
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
case INVALID:
|
||||
break;
|
||||
case DUES:
|
||||
optionData = new EnumOptionData(StandingInstructionType.DUES.getValue().longValue(),
|
||||
StandingInstructionType.DUES.getCode(), "Dues");
|
||||
break;
|
||||
case FIXED:
|
||||
optionData = new EnumOptionData(StandingInstructionType.FIXED.getValue().longValue(),
|
||||
StandingInstructionType.FIXED.getCode(), "Fixed");
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* 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.account.service;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferRecurrenceType;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferType;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionPriority;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionStatus;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionType;
|
||||
|
||||
public final class AccountTransferEnumerations {
|
||||
|
||||
private AccountTransferEnumerations() {
|
||||
|
||||
}
|
||||
|
||||
public static EnumOptionData accountType(final Integer type) {
|
||||
return accountType(PortfolioAccountType.fromInt(type));
|
||||
}
|
||||
|
||||
public static EnumOptionData accountType(final PortfolioAccountType type) {
|
||||
|
||||
EnumOptionData optionData = null;
|
||||
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
case INVALID:
|
||||
break;
|
||||
case LOAN:
|
||||
optionData = new EnumOptionData(PortfolioAccountType.LOAN.getValue().longValue(), PortfolioAccountType.LOAN.getCode(),
|
||||
"Loan Account");
|
||||
break;
|
||||
case SAVINGS:
|
||||
optionData = new EnumOptionData(PortfolioAccountType.SAVINGS.getValue().longValue(),
|
||||
PortfolioAccountType.SAVINGS.getCode(), "Savings Account");
|
||||
break;
|
||||
case CURRENT:
|
||||
optionData = new EnumOptionData(PortfolioAccountType.CURRENT.getValue().longValue(),
|
||||
PortfolioAccountType.CURRENT.getCode(), "Current Account");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static EnumOptionData recurrenceType(final Integer type) {
|
||||
return recurrenceType(AccountTransferRecurrenceType.fromInt(type));
|
||||
}
|
||||
|
||||
public static EnumOptionData recurrenceType(final AccountTransferRecurrenceType type) {
|
||||
EnumOptionData optionData = null;
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
case INVALID:
|
||||
break;
|
||||
case PERIODIC:
|
||||
optionData = new EnumOptionData(AccountTransferRecurrenceType.PERIODIC.getValue().longValue(),
|
||||
AccountTransferRecurrenceType.PERIODIC.getCode(), "Periodic Recurrence");
|
||||
break;
|
||||
case AS_PER_DUES:
|
||||
optionData = new EnumOptionData(AccountTransferRecurrenceType.AS_PER_DUES.getValue().longValue(),
|
||||
AccountTransferRecurrenceType.AS_PER_DUES.getCode(), "As Per Dues Recurrence");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static EnumOptionData transferType(final Integer type) {
|
||||
return transferType(AccountTransferType.fromInt(type));
|
||||
}
|
||||
|
||||
public static EnumOptionData transferType(final AccountTransferType type) {
|
||||
EnumOptionData optionData = null;
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
case INVALID:
|
||||
break;
|
||||
case ACCOUNT_TRANSFER:
|
||||
optionData = new EnumOptionData(AccountTransferType.ACCOUNT_TRANSFER.getValue().longValue(),
|
||||
AccountTransferType.ACCOUNT_TRANSFER.getCode(), "Account Transfer");
|
||||
break;
|
||||
case LOAN_REPAYMENT:
|
||||
optionData = new EnumOptionData(AccountTransferType.LOAN_REPAYMENT.getValue().longValue(),
|
||||
AccountTransferType.LOAN_REPAYMENT.getCode(), "Loan Repayment");
|
||||
break;
|
||||
case CHARGE_PAYMENT:
|
||||
optionData = new EnumOptionData(AccountTransferType.CHARGE_PAYMENT.getValue().longValue(),
|
||||
AccountTransferType.CHARGE_PAYMENT.getCode(), "Charge Payment");
|
||||
break;
|
||||
case INTEREST_TRANSFER:
|
||||
optionData = new EnumOptionData(AccountTransferType.INTEREST_TRANSFER.getValue().longValue(),
|
||||
AccountTransferType.INTEREST_TRANSFER.getCode(), "Interest Transfer");
|
||||
break;
|
||||
case LOAN_DOWN_PAYMENT:
|
||||
optionData = new EnumOptionData(AccountTransferType.LOAN_DOWN_PAYMENT.getValue().longValue(),
|
||||
AccountTransferType.LOAN_DOWN_PAYMENT.getCode(), "Loan Down Payment");
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static EnumOptionData standingInstructionPriority(final Integer type) {
|
||||
return standingInstructionPriority(StandingInstructionPriority.fromInt(type));
|
||||
}
|
||||
|
||||
public static EnumOptionData standingInstructionPriority(final StandingInstructionPriority type) {
|
||||
EnumOptionData optionData = null;
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
case INVALID:
|
||||
break;
|
||||
case HIGH:
|
||||
optionData = new EnumOptionData(StandingInstructionPriority.HIGH.getValue().longValue(),
|
||||
StandingInstructionPriority.HIGH.getCode(), "High Priority");
|
||||
break;
|
||||
case LOW:
|
||||
optionData = new EnumOptionData(StandingInstructionPriority.LOW.getValue().longValue(),
|
||||
StandingInstructionPriority.LOW.getCode(), "Low Priority");
|
||||
break;
|
||||
case MEDIUM:
|
||||
optionData = new EnumOptionData(StandingInstructionPriority.MEDIUM.getValue().longValue(),
|
||||
StandingInstructionPriority.MEDIUM.getCode(), "Medium Priority");
|
||||
break;
|
||||
case URGENT:
|
||||
optionData = new EnumOptionData(StandingInstructionPriority.URGENT.getValue().longValue(),
|
||||
StandingInstructionPriority.URGENT.getCode(), "Urgent Priority");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static EnumOptionData standingInstructionStatus(final Integer type) {
|
||||
return standingInstructionStatus(StandingInstructionStatus.fromInt(type));
|
||||
}
|
||||
|
||||
public static EnumOptionData standingInstructionStatus(final StandingInstructionStatus type) {
|
||||
EnumOptionData optionData = null;
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
case INVALID:
|
||||
break;
|
||||
case ACTIVE:
|
||||
optionData = new EnumOptionData(StandingInstructionStatus.ACTIVE.getValue().longValue(),
|
||||
StandingInstructionStatus.ACTIVE.getCode(), "Active");
|
||||
break;
|
||||
case DELETED:
|
||||
optionData = new EnumOptionData(StandingInstructionStatus.DELETED.getValue().longValue(),
|
||||
StandingInstructionStatus.DELETED.getCode(), "Deleted");
|
||||
break;
|
||||
case DISABLED:
|
||||
optionData = new EnumOptionData(StandingInstructionStatus.DISABLED.getValue().longValue(),
|
||||
StandingInstructionStatus.DISABLED.getCode(), "Disabled");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static EnumOptionData standingInstructionType(final Integer type) {
|
||||
return standingInstructionType(StandingInstructionType.fromInt(type));
|
||||
}
|
||||
|
||||
public static EnumOptionData standingInstructionType(final StandingInstructionType type) {
|
||||
EnumOptionData optionData = null;
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
case INVALID:
|
||||
break;
|
||||
case DUES:
|
||||
optionData = new EnumOptionData(StandingInstructionType.DUES.getValue().longValue(),
|
||||
StandingInstructionType.DUES.getCode(), "Dues");
|
||||
break;
|
||||
case FIXED:
|
||||
optionData = new EnumOptionData(StandingInstructionType.FIXED.getValue().longValue(),
|
||||
StandingInstructionType.FIXED.getCode(), "Fixed");
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+753
-561
File diff suppressed because it is too large
Load Diff
+482
-396
@@ -1,396 +1,482 @@
|
||||
/**
|
||||
* 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.account.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
|
||||
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
||||
import org.apache.fineract.portfolio.account.data.PortfolioAccountDTO;
|
||||
import org.apache.fineract.portfolio.account.data.PortfolioAccountData;
|
||||
import org.apache.fineract.portfolio.account.exception.AccountTransferNotFoundException;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
public class PortfolioAccountReadPlatformServiceImpl implements PortfolioAccountReadPlatformService {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
// mapper
|
||||
private final PortfolioSavingsAccountMapper savingsAccountMapper;
|
||||
private final PortfolioLoanAccountMapper loanAccountMapper;
|
||||
private final PortfolioLoanAccountRefundByTransferMapper accountRefundByTransferMapper;
|
||||
|
||||
public PortfolioAccountReadPlatformServiceImpl(final JdbcTemplate jdbcTemplate, DatabaseSpecificSQLGenerator sqlGenerator) {
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
this.savingsAccountMapper = new PortfolioSavingsAccountMapper();
|
||||
this.loanAccountMapper = new PortfolioLoanAccountMapper();
|
||||
this.accountRefundByTransferMapper = new PortfolioLoanAccountRefundByTransferMapper(sqlGenerator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortfolioAccountData retrieveOne(final Long accountId, final Integer accountTypeId) {
|
||||
return retrieveOne(accountId, accountTypeId, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortfolioAccountData retrieveOne(final Long accountId, final Integer accountTypeId, final String currencyCode) {
|
||||
|
||||
Object[] sqlParams = new Object[] { accountId };
|
||||
PortfolioAccountData accountData = null;
|
||||
try {
|
||||
String sql = null;
|
||||
final PortfolioAccountType accountType = PortfolioAccountType.fromInt(accountTypeId);
|
||||
switch (accountType) {
|
||||
case INVALID:
|
||||
break;
|
||||
case LOAN:
|
||||
|
||||
sql = "select " + this.loanAccountMapper.schema() + " where la.id = ?";
|
||||
if (currencyCode != null) {
|
||||
sql += " and la.currency_code = ?";
|
||||
sqlParams = new Object[] { accountId, currencyCode };
|
||||
}
|
||||
|
||||
accountData = this.jdbcTemplate.queryForObject(sql, this.loanAccountMapper, sqlParams);
|
||||
break;
|
||||
case SAVINGS:
|
||||
sql = "select " + this.savingsAccountMapper.schema() + " where sa.id = ?";
|
||||
if (currencyCode != null) {
|
||||
sql += " and sa.currency_code = ?";
|
||||
sqlParams = new Object[] { accountId, currencyCode };
|
||||
}
|
||||
|
||||
accountData = this.jdbcTemplate.queryForObject(sql, this.savingsAccountMapper, sqlParams);
|
||||
break;
|
||||
}
|
||||
} catch (final EmptyResultDataAccessException e) {
|
||||
throw new AccountTransferNotFoundException(accountId, e);
|
||||
}
|
||||
|
||||
return accountData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<PortfolioAccountData> retrieveAllForLookup(final PortfolioAccountDTO portfolioAccountDTO) {
|
||||
|
||||
final List<Object> sqlParams = new ArrayList<>();
|
||||
// sqlParams.add(portfolioAccountDTO.getClientId());
|
||||
Collection<PortfolioAccountData> accounts = null;
|
||||
String sql = null;
|
||||
long defaultAccountStatus = 300; // Active Status
|
||||
if (portfolioAccountDTO.getAccountStatus() != null) {
|
||||
defaultAccountStatus = portfolioAccountDTO.getFirstAccountStatus();
|
||||
}
|
||||
final PortfolioAccountType accountType = PortfolioAccountType.fromInt(portfolioAccountDTO.getAccountTypeId());
|
||||
switch (accountType) {
|
||||
case INVALID:
|
||||
break;
|
||||
case LOAN:
|
||||
sql = "select " + this.loanAccountMapper.schema() + " where ";
|
||||
if (portfolioAccountDTO.getClientId() != null) {
|
||||
sql += " la.client_id = ? and la.loan_status_id in (?) ";
|
||||
sqlParams.add(portfolioAccountDTO.getClientId());
|
||||
sqlParams.add(defaultAccountStatus);
|
||||
} else {
|
||||
sql += " la.loan_status_id in (?) ";
|
||||
sqlParams.add(defaultAccountStatus);
|
||||
}
|
||||
if (portfolioAccountDTO.getCurrencyCode() != null) {
|
||||
sql += " and la.currency_code = ?";
|
||||
sqlParams.add(portfolioAccountDTO.getCurrencyCode());
|
||||
}
|
||||
|
||||
accounts = this.jdbcTemplate.query(sql, this.loanAccountMapper, sqlParams.toArray()); // NOSONAR
|
||||
break;
|
||||
case SAVINGS:
|
||||
sql = "select " + this.savingsAccountMapper.schema() + " where ";
|
||||
if (portfolioAccountDTO.getClientId() != null) {
|
||||
sql += " sa.client_id = ? and sa.status_enum in (?) ";
|
||||
sqlParams.add(portfolioAccountDTO.getClientId());
|
||||
sqlParams.add(defaultAccountStatus);
|
||||
} else {
|
||||
sql += " sa.status_enum in (?) ";
|
||||
sqlParams.add(defaultAccountStatus);
|
||||
}
|
||||
if (portfolioAccountDTO.getCurrencyCode() != null) {
|
||||
sql += " and sa.currency_code = ?";
|
||||
sqlParams.add(portfolioAccountDTO.getCurrencyCode());
|
||||
}
|
||||
|
||||
if (portfolioAccountDTO.getDepositType() != null) {
|
||||
sql += " and sa.deposit_type_enum = ?";
|
||||
sqlParams.add(portfolioAccountDTO.getDepositType().shortValue());
|
||||
}
|
||||
|
||||
if (portfolioAccountDTO.isExcludeOverDraftAccounts()) {
|
||||
sql += " and sa.allow_overdraft = false";
|
||||
}
|
||||
|
||||
if (portfolioAccountDTO.getClientId() == null && portfolioAccountDTO.getGroupId() != null) {
|
||||
sql += " and sa.group_id = ? ";
|
||||
sqlParams.add(portfolioAccountDTO.getGroupId());
|
||||
}
|
||||
|
||||
accounts = this.jdbcTemplate.query(sql, this.savingsAccountMapper, sqlParams.toArray()); // NOSONAR
|
||||
break;
|
||||
}
|
||||
|
||||
return accounts;
|
||||
}
|
||||
|
||||
private static final class PortfolioSavingsAccountMapper implements RowMapper<PortfolioAccountData> {
|
||||
|
||||
private final String schemaSql;
|
||||
|
||||
PortfolioSavingsAccountMapper() {
|
||||
|
||||
final StringBuilder sqlBuilder = new StringBuilder(400);
|
||||
sqlBuilder.append("sa.id as id, sa.account_no as accountNo, sa.external_id as externalId, ");
|
||||
sqlBuilder.append("c.id as clientId, c.display_name as clientName, ");
|
||||
sqlBuilder.append("g.id as groupId, g.display_name as groupName, ");
|
||||
sqlBuilder.append("sp.id as productId, sp.name as productName, ");
|
||||
sqlBuilder.append("s.id as fieldOfficerId, s.display_name as fieldOfficerName, ");
|
||||
sqlBuilder.append("sa.currency_code as currencyCode, sa.currency_digits as currencyDigits,");
|
||||
sqlBuilder.append("sa.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("from m_savings_account sa ");
|
||||
sqlBuilder.append("join m_savings_product sp ON sa.product_id = sp.id ");
|
||||
sqlBuilder.append("join m_currency curr on curr.code = sa.currency_code ");
|
||||
sqlBuilder.append("left join m_client c ON c.id = sa.client_id ");
|
||||
sqlBuilder.append("left join m_group g ON g.id = sa.group_id ");
|
||||
sqlBuilder.append("left join m_staff s ON s.id = sa.field_officer_id ");
|
||||
|
||||
this.schemaSql = sqlBuilder.toString();
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
return this.schemaSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortfolioAccountData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
|
||||
final Long id = rs.getLong("id");
|
||||
final String accountNo = rs.getString("accountNo");
|
||||
final String externalId = rs.getString("externalId");
|
||||
|
||||
final Long groupId = JdbcSupport.getLong(rs, "groupId");
|
||||
final String groupName = rs.getString("groupName");
|
||||
final Long clientId = JdbcSupport.getLong(rs, "clientId");
|
||||
final String clientName = rs.getString("clientName");
|
||||
|
||||
final Long productId = rs.getLong("productId");
|
||||
final String productName = rs.getString("productName");
|
||||
|
||||
final Long fieldOfficerId = rs.getLong("fieldOfficerId");
|
||||
final String fieldOfficerName = rs.getString("fieldOfficerName");
|
||||
|
||||
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 inMulitplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf");
|
||||
final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, inMulitplesOf, currencyDisplaySymbol,
|
||||
currencyNameCode);
|
||||
|
||||
return new PortfolioAccountData(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName,
|
||||
fieldOfficerId, fieldOfficerName, currency);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class PortfolioLoanAccountMapper implements RowMapper<PortfolioAccountData> {
|
||||
|
||||
private final String schemaSql;
|
||||
|
||||
PortfolioLoanAccountMapper() {
|
||||
|
||||
final StringBuilder sqlBuilder = new StringBuilder(400);
|
||||
sqlBuilder.append("la.id as id, la.account_no as accountNo, la.external_id as externalId, ");
|
||||
sqlBuilder.append("c.id as clientId, c.display_name as clientName, ");
|
||||
sqlBuilder.append("g.id as groupId, g.display_name as groupName, ");
|
||||
sqlBuilder.append("lp.id as productId, lp.name as productName, ");
|
||||
sqlBuilder.append("s.id as fieldOfficerId, s.display_name as fieldOfficerName, ");
|
||||
sqlBuilder.append("la.currency_code as currencyCode, la.currency_digits as currencyDigits,");
|
||||
sqlBuilder.append("la.currency_multiplesof as inMultiplesOf, ");
|
||||
sqlBuilder.append("la.total_overpaid_derived as totalOverpaid, ");
|
||||
sqlBuilder.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
|
||||
sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol ");
|
||||
sqlBuilder.append("from m_loan la ");
|
||||
sqlBuilder.append("join m_product_loan lp ON la.product_id = lp.id ");
|
||||
sqlBuilder.append("join m_currency curr on curr.code = la.currency_code ");
|
||||
sqlBuilder.append("left join m_client c ON c.id = la.client_id ");
|
||||
sqlBuilder.append("left join m_group g ON g.id = la.group_id ");
|
||||
sqlBuilder.append("left join m_staff s ON s.id = la.loan_officer_id ");
|
||||
|
||||
this.schemaSql = sqlBuilder.toString();
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
return this.schemaSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortfolioAccountData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
|
||||
final Long id = rs.getLong("id");
|
||||
final String accountNo = rs.getString("accountNo");
|
||||
final String externalId = rs.getString("externalId");
|
||||
|
||||
final Long groupId = JdbcSupport.getLong(rs, "groupId");
|
||||
final String groupName = rs.getString("groupName");
|
||||
final Long clientId = JdbcSupport.getLong(rs, "clientId");
|
||||
final String clientName = rs.getString("clientName");
|
||||
|
||||
final Long productId = rs.getLong("productId");
|
||||
final String productName = rs.getString("productName");
|
||||
|
||||
final Long fieldOfficerId = rs.getLong("fieldOfficerId");
|
||||
final String fieldOfficerName = rs.getString("fieldOfficerName");
|
||||
|
||||
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 inMulitplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf");
|
||||
final BigDecimal amtForTransfer = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalOverpaid");
|
||||
final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, inMulitplesOf, currencyDisplaySymbol,
|
||||
currencyNameCode);
|
||||
|
||||
return new PortfolioAccountData(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName,
|
||||
fieldOfficerId, fieldOfficerName, currency, amtForTransfer);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class PortfolioLoanAccountRefundByTransferMapper implements RowMapper<PortfolioAccountData> {
|
||||
|
||||
private String schemaSql;
|
||||
private final DatabaseSpecificSQLGenerator sqlGenerator;
|
||||
|
||||
PortfolioLoanAccountRefundByTransferMapper(DatabaseSpecificSQLGenerator sqlGenerator) {
|
||||
this.sqlGenerator = sqlGenerator;
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
final StringBuilder amountQueryString = new StringBuilder(400);
|
||||
amountQueryString.append("(select (SUM(COALESCE(mr.principal_completed_derived, 0)) +");
|
||||
amountQueryString.append("SUM(COALESCE(mr.interest_completed_derived, 0)) + ");
|
||||
amountQueryString.append("SUM(COALESCE(mr.fee_charges_completed_derived, 0)) + ");
|
||||
amountQueryString.append(" SUM(COALESCE(mr.penalty_charges_completed_derived, 0))) as total_in_advance_derived");
|
||||
amountQueryString.append(" from m_loan ml INNER JOIN m_loan_repayment_schedule mr on mr.loan_id = ml.id");
|
||||
amountQueryString.append(" where ml.id=? and ml.loan_status_id = 300");
|
||||
amountQueryString.append(" and mr.duedate >= " + sqlGenerator.currentBusinessDate() + " group by ml.id having");
|
||||
amountQueryString.append(" (SUM(COALESCE(mr.principal_completed_derived, 0)) + ");
|
||||
amountQueryString.append(" SUM(COALESCE(mr.interest_completed_derived, 0)) + ");
|
||||
amountQueryString.append("SUM(COALESCE(mr.fee_charges_completed_derived, 0)) + ");
|
||||
amountQueryString.append("SUM(COALESCE(mr.penalty_charges_completed_derived, 0))) > 0) as totalOverpaid ");
|
||||
|
||||
final StringBuilder sqlBuilder = new StringBuilder(400);
|
||||
sqlBuilder.append("la.id as id, la.account_no as accountNo, la.external_id as externalId, ");
|
||||
sqlBuilder.append("c.id as clientId, c.display_name as clientName, ");
|
||||
sqlBuilder.append("g.id as groupId, g.display_name as groupName, ");
|
||||
sqlBuilder.append("lp.id as productId, lp.name as productName, ");
|
||||
sqlBuilder.append("s.id as fieldOfficerId, s.display_name as fieldOfficerName, ");
|
||||
sqlBuilder.append("la.currency_code as currencyCode, la.currency_digits as currencyDigits,");
|
||||
sqlBuilder.append("la.currency_multiplesof as inMultiplesOf, ");
|
||||
sqlBuilder.append(amountQueryString.toString());
|
||||
sqlBuilder.append(", ");
|
||||
sqlBuilder.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
|
||||
sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol ");
|
||||
sqlBuilder.append("from m_loan la ");
|
||||
sqlBuilder.append("join m_product_loan lp ON la.product_id = lp.id ");
|
||||
sqlBuilder.append("join m_currency curr on curr.code = la.currency_code ");
|
||||
sqlBuilder.append("left join m_client c ON c.id = la.client_id ");
|
||||
sqlBuilder.append("left join m_group g ON g.id = la.group_id ");
|
||||
sqlBuilder.append("left join m_staff s ON s.id = la.loan_officer_id ");
|
||||
|
||||
this.schemaSql = sqlBuilder.toString();
|
||||
|
||||
return this.schemaSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortfolioAccountData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
|
||||
final Long id = rs.getLong("id");
|
||||
final String accountNo = rs.getString("accountNo");
|
||||
final String externalId = rs.getString("externalId");
|
||||
|
||||
final Long groupId = JdbcSupport.getLong(rs, "groupId");
|
||||
final String groupName = rs.getString("groupName");
|
||||
final Long clientId = JdbcSupport.getLong(rs, "clientId");
|
||||
final String clientName = rs.getString("clientName");
|
||||
|
||||
final Long productId = rs.getLong("productId");
|
||||
final String productName = rs.getString("productName");
|
||||
|
||||
final Long fieldOfficerId = rs.getLong("fieldOfficerId");
|
||||
final String fieldOfficerName = rs.getString("fieldOfficerName");
|
||||
|
||||
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 inMulitplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf");
|
||||
final BigDecimal amtForTransfer = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalOverpaid");
|
||||
final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, inMulitplesOf, currencyDisplaySymbol,
|
||||
currencyNameCode);
|
||||
|
||||
return new PortfolioAccountData(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName,
|
||||
fieldOfficerId, fieldOfficerName, currency, amtForTransfer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortfolioAccountData retrieveOneByPaidInAdvance(Long accountId, Integer accountTypeId) {
|
||||
// TODO Auto-generated method stub
|
||||
Object[] sqlParams = new Object[] { accountId, accountId };
|
||||
PortfolioAccountData accountData = null;
|
||||
// String currencyCode = null;
|
||||
try {
|
||||
String sql = null;
|
||||
// final PortfolioAccountType accountType =
|
||||
// PortfolioAccountType.fromInt(accountTypeId);
|
||||
|
||||
sql = "select " + this.accountRefundByTransferMapper.schema() + " where la.id = ?";
|
||||
/*
|
||||
* if (currencyCode != null) { sql += " and la.currency_code = ?"; sqlParams = new Object[] {accountId ,
|
||||
* accountId,currencyCode }; }
|
||||
*/
|
||||
|
||||
accountData = this.jdbcTemplate.queryForObject(sql, this.accountRefundByTransferMapper, sqlParams);
|
||||
|
||||
} catch (final EmptyResultDataAccessException e) {
|
||||
throw new AccountTransferNotFoundException(accountId, e);
|
||||
}
|
||||
|
||||
return accountData;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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.account.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
|
||||
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
||||
import org.apache.fineract.portfolio.account.data.PortfolioAccountDTO;
|
||||
import org.apache.fineract.portfolio.account.data.PortfolioAccountData;
|
||||
import org.apache.fineract.portfolio.account.exception.AccountTransferNotFoundException;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
public class PortfolioAccountReadPlatformServiceImpl implements PortfolioAccountReadPlatformService {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
// mapper
|
||||
private final PortfolioSavingsAccountMapper savingsAccountMapper;
|
||||
private final PortfolioLoanAccountMapper loanAccountMapper;
|
||||
private final PortfolioLoanAccountRefundByTransferMapper accountRefundByTransferMapper;
|
||||
private final PortfolioCurrentAccountMapper currentAccountMapper;
|
||||
|
||||
public PortfolioAccountReadPlatformServiceImpl(final JdbcTemplate jdbcTemplate, DatabaseSpecificSQLGenerator sqlGenerator) {
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
this.savingsAccountMapper = new PortfolioSavingsAccountMapper();
|
||||
this.loanAccountMapper = new PortfolioLoanAccountMapper();
|
||||
this.accountRefundByTransferMapper = new PortfolioLoanAccountRefundByTransferMapper(sqlGenerator);
|
||||
this.currentAccountMapper = new PortfolioCurrentAccountMapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortfolioAccountData retrieveOne(final Long accountId, final Integer accountTypeId) {
|
||||
return retrieveOne(accountId, accountTypeId, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortfolioAccountData retrieveOne(final Long accountId, final Integer accountTypeId, final String currencyCode) {
|
||||
|
||||
Object[] sqlParams = new Object[] { accountId };
|
||||
PortfolioAccountData accountData = null;
|
||||
try {
|
||||
String sql = null;
|
||||
final PortfolioAccountType accountType = PortfolioAccountType.fromInt(accountTypeId);
|
||||
switch (accountType) {
|
||||
case INVALID:
|
||||
break;
|
||||
case LOAN:
|
||||
|
||||
sql = "select " + this.loanAccountMapper.schema() + " where la.id = ?";
|
||||
if (currencyCode != null) {
|
||||
sql += " and la.currency_code = ?";
|
||||
sqlParams = new Object[] { accountId, currencyCode };
|
||||
}
|
||||
|
||||
accountData = this.jdbcTemplate.queryForObject(sql, this.loanAccountMapper, sqlParams);
|
||||
break;
|
||||
case SAVINGS:
|
||||
sql = "select " + this.savingsAccountMapper.schema() + " where sa.id = ?";
|
||||
if (currencyCode != null) {
|
||||
sql += " and sa.currency_code = ?";
|
||||
sqlParams = new Object[] { accountId, currencyCode };
|
||||
}
|
||||
|
||||
accountData = this.jdbcTemplate.queryForObject(sql, this.savingsAccountMapper, sqlParams);
|
||||
break;
|
||||
case CURRENT:
|
||||
sql = "select " + this.currentAccountMapper.schema() + " where ca.id = ?";
|
||||
if (currencyCode != null) {
|
||||
sql += " and ca.currency_code = ?";
|
||||
sqlParams = new Object[] { accountId, currencyCode };
|
||||
}
|
||||
|
||||
accountData = this.jdbcTemplate.queryForObject(sql, this.currentAccountMapper, sqlParams);
|
||||
break;
|
||||
}
|
||||
} catch (final EmptyResultDataAccessException e) {
|
||||
throw new AccountTransferNotFoundException(accountId, e);
|
||||
}
|
||||
|
||||
return accountData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<PortfolioAccountData> retrieveAllForLookup(final PortfolioAccountDTO portfolioAccountDTO) {
|
||||
|
||||
final List<Object> sqlParams = new ArrayList<>();
|
||||
// sqlParams.add(portfolioAccountDTO.getClientId());
|
||||
Collection<PortfolioAccountData> accounts = null;
|
||||
String sql = null;
|
||||
long defaultAccountStatus = 300; // Active Status
|
||||
if (portfolioAccountDTO.getAccountStatus() != null) {
|
||||
defaultAccountStatus = portfolioAccountDTO.getFirstAccountStatus();
|
||||
}
|
||||
final PortfolioAccountType accountType = PortfolioAccountType.fromInt(portfolioAccountDTO.getAccountTypeId());
|
||||
switch (accountType) {
|
||||
case INVALID:
|
||||
break;
|
||||
case LOAN:
|
||||
sql = "select " + this.loanAccountMapper.schema() + " where ";
|
||||
if (portfolioAccountDTO.getClientId() != null) {
|
||||
sql += " la.client_id = ? and la.loan_status_id in (?) ";
|
||||
sqlParams.add(portfolioAccountDTO.getClientId());
|
||||
sqlParams.add(defaultAccountStatus);
|
||||
} else {
|
||||
sql += " la.loan_status_id in (?) ";
|
||||
sqlParams.add(defaultAccountStatus);
|
||||
}
|
||||
if (portfolioAccountDTO.getCurrencyCode() != null) {
|
||||
sql += " and la.currency_code = ?";
|
||||
sqlParams.add(portfolioAccountDTO.getCurrencyCode());
|
||||
}
|
||||
|
||||
accounts = this.jdbcTemplate.query(sql, this.loanAccountMapper, sqlParams.toArray()); // NOSONAR
|
||||
break;
|
||||
case SAVINGS:
|
||||
sql = "select " + this.savingsAccountMapper.schema() + " where ";
|
||||
if (portfolioAccountDTO.getClientId() != null) {
|
||||
sql += " sa.client_id = ? and sa.status_enum in (?) ";
|
||||
sqlParams.add(portfolioAccountDTO.getClientId());
|
||||
sqlParams.add(defaultAccountStatus);
|
||||
} else {
|
||||
sql += " sa.status_enum in (?) ";
|
||||
sqlParams.add(defaultAccountStatus);
|
||||
}
|
||||
if (portfolioAccountDTO.getCurrencyCode() != null) {
|
||||
sql += " and sa.currency_code = ?";
|
||||
sqlParams.add(portfolioAccountDTO.getCurrencyCode());
|
||||
}
|
||||
|
||||
if (portfolioAccountDTO.getDepositType() != null) {
|
||||
sql += " and sa.deposit_type_enum = ?";
|
||||
sqlParams.add(portfolioAccountDTO.getDepositType().shortValue());
|
||||
}
|
||||
|
||||
if (portfolioAccountDTO.isExcludeOverDraftAccounts()) {
|
||||
sql += " and sa.allow_overdraft = false";
|
||||
}
|
||||
|
||||
if (portfolioAccountDTO.getClientId() == null && portfolioAccountDTO.getGroupId() != null) {
|
||||
sql += " and sa.group_id = ? ";
|
||||
sqlParams.add(portfolioAccountDTO.getGroupId());
|
||||
}
|
||||
|
||||
accounts = this.jdbcTemplate.query(sql, this.savingsAccountMapper, sqlParams.toArray()); // NOSONAR
|
||||
break;
|
||||
case CURRENT:
|
||||
sql = "select " + this.currentAccountMapper.schema() + " where ";
|
||||
if (portfolioAccountDTO.getClientId() != null) {
|
||||
sql += " ca.client_id = ? and ca.status_enum in (?) ";
|
||||
sqlParams.add(portfolioAccountDTO.getClientId());
|
||||
sqlParams.add(defaultAccountStatus);
|
||||
} else {
|
||||
sql += " ca.status_enum in (?) ";
|
||||
sqlParams.add(defaultAccountStatus);
|
||||
}
|
||||
if (portfolioAccountDTO.getCurrencyCode() != null) {
|
||||
sql += " and ca.currency_code = ?";
|
||||
sqlParams.add(portfolioAccountDTO.getCurrencyCode());
|
||||
}
|
||||
|
||||
accounts = this.jdbcTemplate.query(sql, this.currentAccountMapper, sqlParams.toArray()); // NOSONAR
|
||||
break;
|
||||
}
|
||||
|
||||
return accounts;
|
||||
}
|
||||
|
||||
private static final class PortfolioSavingsAccountMapper implements RowMapper<PortfolioAccountData> {
|
||||
|
||||
private final String schemaSql;
|
||||
|
||||
PortfolioSavingsAccountMapper() {
|
||||
|
||||
final StringBuilder sqlBuilder = new StringBuilder(400);
|
||||
sqlBuilder.append("sa.id as id, sa.account_no as accountNo, sa.external_id as externalId, ");
|
||||
sqlBuilder.append("c.id as clientId, c.display_name as clientName, ");
|
||||
sqlBuilder.append("g.id as groupId, g.display_name as groupName, ");
|
||||
sqlBuilder.append("sp.id as productId, sp.name as productName, ");
|
||||
sqlBuilder.append("s.id as fieldOfficerId, s.display_name as fieldOfficerName, ");
|
||||
sqlBuilder.append("sa.currency_code as currencyCode, sa.currency_digits as currencyDigits,");
|
||||
sqlBuilder.append("sa.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("from m_savings_account sa ");
|
||||
sqlBuilder.append("join m_savings_product sp ON sa.product_id = sp.id ");
|
||||
sqlBuilder.append("join m_currency curr on curr.code = sa.currency_code ");
|
||||
sqlBuilder.append("left join m_client c ON c.id = sa.client_id ");
|
||||
sqlBuilder.append("left join m_group g ON g.id = sa.group_id ");
|
||||
sqlBuilder.append("left join m_staff s ON s.id = sa.field_officer_id ");
|
||||
|
||||
this.schemaSql = sqlBuilder.toString();
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
return this.schemaSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortfolioAccountData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
|
||||
final Long id = rs.getLong("id");
|
||||
final String accountNo = rs.getString("accountNo");
|
||||
final String externalId = rs.getString("externalId");
|
||||
|
||||
final Long groupId = JdbcSupport.getLong(rs, "groupId");
|
||||
final String groupName = rs.getString("groupName");
|
||||
final Long clientId = JdbcSupport.getLong(rs, "clientId");
|
||||
final String clientName = rs.getString("clientName");
|
||||
|
||||
final Long productId = rs.getLong("productId");
|
||||
final String productName = rs.getString("productName");
|
||||
|
||||
final Long fieldOfficerId = rs.getLong("fieldOfficerId");
|
||||
final String fieldOfficerName = rs.getString("fieldOfficerName");
|
||||
|
||||
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 inMulitplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf");
|
||||
final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, inMulitplesOf, currencyDisplaySymbol,
|
||||
currencyNameCode);
|
||||
|
||||
return new PortfolioAccountData(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName,
|
||||
fieldOfficerId, fieldOfficerName, currency);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class PortfolioLoanAccountMapper implements RowMapper<PortfolioAccountData> {
|
||||
|
||||
private final String schemaSql;
|
||||
|
||||
PortfolioLoanAccountMapper() {
|
||||
|
||||
final StringBuilder sqlBuilder = new StringBuilder(400);
|
||||
sqlBuilder.append("la.id as id, la.account_no as accountNo, la.external_id as externalId, ");
|
||||
sqlBuilder.append("c.id as clientId, c.display_name as clientName, ");
|
||||
sqlBuilder.append("g.id as groupId, g.display_name as groupName, ");
|
||||
sqlBuilder.append("lp.id as productId, lp.name as productName, ");
|
||||
sqlBuilder.append("s.id as fieldOfficerId, s.display_name as fieldOfficerName, ");
|
||||
sqlBuilder.append("la.currency_code as currencyCode, la.currency_digits as currencyDigits,");
|
||||
sqlBuilder.append("la.currency_multiplesof as inMultiplesOf, ");
|
||||
sqlBuilder.append("la.total_overpaid_derived as totalOverpaid, ");
|
||||
sqlBuilder.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
|
||||
sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol ");
|
||||
sqlBuilder.append("from m_loan la ");
|
||||
sqlBuilder.append("join m_product_loan lp ON la.product_id = lp.id ");
|
||||
sqlBuilder.append("join m_currency curr on curr.code = la.currency_code ");
|
||||
sqlBuilder.append("left join m_client c ON c.id = la.client_id ");
|
||||
sqlBuilder.append("left join m_group g ON g.id = la.group_id ");
|
||||
sqlBuilder.append("left join m_staff s ON s.id = la.loan_officer_id ");
|
||||
|
||||
this.schemaSql = sqlBuilder.toString();
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
return this.schemaSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortfolioAccountData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
|
||||
final Long id = rs.getLong("id");
|
||||
final String accountNo = rs.getString("accountNo");
|
||||
final String externalId = rs.getString("externalId");
|
||||
|
||||
final Long groupId = JdbcSupport.getLong(rs, "groupId");
|
||||
final String groupName = rs.getString("groupName");
|
||||
final Long clientId = JdbcSupport.getLong(rs, "clientId");
|
||||
final String clientName = rs.getString("clientName");
|
||||
|
||||
final Long productId = rs.getLong("productId");
|
||||
final String productName = rs.getString("productName");
|
||||
|
||||
final Long fieldOfficerId = rs.getLong("fieldOfficerId");
|
||||
final String fieldOfficerName = rs.getString("fieldOfficerName");
|
||||
|
||||
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 inMulitplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf");
|
||||
final BigDecimal amtForTransfer = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalOverpaid");
|
||||
final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, inMulitplesOf, currencyDisplaySymbol,
|
||||
currencyNameCode);
|
||||
|
||||
return new PortfolioAccountData(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName,
|
||||
fieldOfficerId, fieldOfficerName, currency, amtForTransfer);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class PortfolioLoanAccountRefundByTransferMapper implements RowMapper<PortfolioAccountData> {
|
||||
|
||||
private String schemaSql;
|
||||
private final DatabaseSpecificSQLGenerator sqlGenerator;
|
||||
|
||||
PortfolioLoanAccountRefundByTransferMapper(DatabaseSpecificSQLGenerator sqlGenerator) {
|
||||
this.sqlGenerator = sqlGenerator;
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
final StringBuilder amountQueryString = new StringBuilder(400);
|
||||
amountQueryString.append("(select (SUM(COALESCE(mr.principal_completed_derived, 0)) +");
|
||||
amountQueryString.append("SUM(COALESCE(mr.interest_completed_derived, 0)) + ");
|
||||
amountQueryString.append("SUM(COALESCE(mr.fee_charges_completed_derived, 0)) + ");
|
||||
amountQueryString.append(" SUM(COALESCE(mr.penalty_charges_completed_derived, 0))) as total_in_advance_derived");
|
||||
amountQueryString.append(" from m_loan ml INNER JOIN m_loan_repayment_schedule mr on mr.loan_id = ml.id");
|
||||
amountQueryString.append(" where ml.id=? and ml.loan_status_id = 300");
|
||||
amountQueryString.append(" and mr.duedate >= " + sqlGenerator.currentBusinessDate() + " group by ml.id having");
|
||||
amountQueryString.append(" (SUM(COALESCE(mr.principal_completed_derived, 0)) + ");
|
||||
amountQueryString.append(" SUM(COALESCE(mr.interest_completed_derived, 0)) + ");
|
||||
amountQueryString.append("SUM(COALESCE(mr.fee_charges_completed_derived, 0)) + ");
|
||||
amountQueryString.append("SUM(COALESCE(mr.penalty_charges_completed_derived, 0))) > 0) as totalOverpaid ");
|
||||
|
||||
final StringBuilder sqlBuilder = new StringBuilder(400);
|
||||
sqlBuilder.append("la.id as id, la.account_no as accountNo, la.external_id as externalId, ");
|
||||
sqlBuilder.append("c.id as clientId, c.display_name as clientName, ");
|
||||
sqlBuilder.append("g.id as groupId, g.display_name as groupName, ");
|
||||
sqlBuilder.append("lp.id as productId, lp.name as productName, ");
|
||||
sqlBuilder.append("s.id as fieldOfficerId, s.display_name as fieldOfficerName, ");
|
||||
sqlBuilder.append("la.currency_code as currencyCode, la.currency_digits as currencyDigits,");
|
||||
sqlBuilder.append("la.currency_multiplesof as inMultiplesOf, ");
|
||||
sqlBuilder.append(amountQueryString.toString());
|
||||
sqlBuilder.append(", ");
|
||||
sqlBuilder.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
|
||||
sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol ");
|
||||
sqlBuilder.append("from m_loan la ");
|
||||
sqlBuilder.append("join m_product_loan lp ON la.product_id = lp.id ");
|
||||
sqlBuilder.append("join m_currency curr on curr.code = la.currency_code ");
|
||||
sqlBuilder.append("left join m_client c ON c.id = la.client_id ");
|
||||
sqlBuilder.append("left join m_group g ON g.id = la.group_id ");
|
||||
sqlBuilder.append("left join m_staff s ON s.id = la.loan_officer_id ");
|
||||
|
||||
this.schemaSql = sqlBuilder.toString();
|
||||
|
||||
return this.schemaSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortfolioAccountData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
|
||||
final Long id = rs.getLong("id");
|
||||
final String accountNo = rs.getString("accountNo");
|
||||
final String externalId = rs.getString("externalId");
|
||||
|
||||
final Long groupId = JdbcSupport.getLong(rs, "groupId");
|
||||
final String groupName = rs.getString("groupName");
|
||||
final Long clientId = JdbcSupport.getLong(rs, "clientId");
|
||||
final String clientName = rs.getString("clientName");
|
||||
|
||||
final Long productId = rs.getLong("productId");
|
||||
final String productName = rs.getString("productName");
|
||||
|
||||
final Long fieldOfficerId = rs.getLong("fieldOfficerId");
|
||||
final String fieldOfficerName = rs.getString("fieldOfficerName");
|
||||
|
||||
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 inMulitplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf");
|
||||
final BigDecimal amtForTransfer = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalOverpaid");
|
||||
final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, inMulitplesOf, currencyDisplaySymbol,
|
||||
currencyNameCode);
|
||||
|
||||
return new PortfolioAccountData(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName,
|
||||
fieldOfficerId, fieldOfficerName, currency, amtForTransfer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortfolioAccountData retrieveOneByPaidInAdvance(Long accountId, Integer accountTypeId) {
|
||||
// TODO Auto-generated method stub
|
||||
Object[] sqlParams = new Object[] { accountId, accountId };
|
||||
PortfolioAccountData accountData = null;
|
||||
// String currencyCode = null;
|
||||
try {
|
||||
String sql = null;
|
||||
// final PortfolioAccountType accountType =
|
||||
// PortfolioAccountType.fromInt(accountTypeId);
|
||||
|
||||
sql = "select " + this.accountRefundByTransferMapper.schema() + " where la.id = ?";
|
||||
/*
|
||||
* if (currencyCode != null) { sql += " and la.currency_code = ?"; sqlParams = new Object[] {accountId ,
|
||||
* accountId,currencyCode }; }
|
||||
*/
|
||||
|
||||
accountData = this.jdbcTemplate.queryForObject(sql, this.accountRefundByTransferMapper, sqlParams);
|
||||
|
||||
} catch (final EmptyResultDataAccessException e) {
|
||||
throw new AccountTransferNotFoundException(accountId, e);
|
||||
}
|
||||
|
||||
return accountData;
|
||||
}
|
||||
|
||||
private static final class PortfolioCurrentAccountMapper implements RowMapper<PortfolioAccountData> {
|
||||
|
||||
private final String schemaSql;
|
||||
|
||||
PortfolioCurrentAccountMapper() {
|
||||
final StringBuilder sqlBuilder = new StringBuilder(400);
|
||||
sqlBuilder.append("ca.id as id, ca.account_no as accountNo, ca.external_id as externalId, ");
|
||||
sqlBuilder.append("c.id as clientId, c.display_name as clientName, ");
|
||||
sqlBuilder.append("null as groupId, null as groupName, ");
|
||||
sqlBuilder.append("cp.id as productId, cp.name as productName, ");
|
||||
sqlBuilder.append("null as fieldOfficerId, null as fieldOfficerName, ");
|
||||
sqlBuilder.append("ca.currency_code as currencyCode, ca.currency_digits as currencyDigits, ");
|
||||
sqlBuilder.append("ca.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("from m_current_account ca ");
|
||||
sqlBuilder.append("join m_current_product cp ON ca.product_id = cp.id ");
|
||||
sqlBuilder.append("join m_currency curr on curr.code = ca.currency_code ");
|
||||
sqlBuilder.append("left join m_client c ON c.id = ca.client_id ");
|
||||
|
||||
this.schemaSql = sqlBuilder.toString();
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
return this.schemaSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortfolioAccountData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
final Long id = rs.getLong("id");
|
||||
final String accountNo = rs.getString("accountNo");
|
||||
final String externalId = rs.getString("externalId");
|
||||
|
||||
final Long groupId = JdbcSupport.getLong(rs, "groupId");
|
||||
final String groupName = rs.getString("groupName");
|
||||
final Long clientId = JdbcSupport.getLong(rs, "clientId");
|
||||
final String clientName = rs.getString("clientName");
|
||||
|
||||
final Long productId = rs.getLong("productId");
|
||||
final String productName = rs.getString("productName");
|
||||
|
||||
final Long fieldOfficerId = JdbcSupport.getLong(rs, "fieldOfficerId");
|
||||
final String fieldOfficerName = rs.getString("fieldOfficerName");
|
||||
|
||||
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);
|
||||
|
||||
return new PortfolioAccountData(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName,
|
||||
fieldOfficerId, fieldOfficerName, currency);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+625
-591
File diff suppressed because it is too large
Load Diff
+179
-145
@@ -1,145 +1,179 @@
|
||||
/**
|
||||
* 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.account.service;
|
||||
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.fromAccountTypeParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.fromClientIdParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.toAccountTypeParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.statusParamName;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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.ErrorHandler;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
||||
import org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants;
|
||||
import org.apache.fineract.portfolio.account.data.StandingInstructionDataValidator;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferDetailRepository;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferDetails;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferStandingInstruction;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionAssembler;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionRepository;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionStatus;
|
||||
import org.apache.fineract.portfolio.account.exception.StandingInstructionNotFoundException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.dao.NonTransientDataAccessException;
|
||||
import org.springframework.orm.jpa.JpaSystemException;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class StandingInstructionWritePlatformServiceImpl implements StandingInstructionWritePlatformService {
|
||||
|
||||
private final StandingInstructionDataValidator standingInstructionDataValidator;
|
||||
private final StandingInstructionAssembler standingInstructionAssembler;
|
||||
private final AccountTransferDetailRepository accountTransferDetailRepository;
|
||||
private final StandingInstructionRepository standingInstructionRepository;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult create(final JsonCommand command) {
|
||||
|
||||
this.standingInstructionDataValidator.validateForCreate(command);
|
||||
|
||||
final Integer fromAccountTypeId = command.integerValueSansLocaleOfParameterNamed(fromAccountTypeParamName);
|
||||
final PortfolioAccountType fromAccountType = PortfolioAccountType.fromInt(fromAccountTypeId);
|
||||
|
||||
final Integer toAccountTypeId = command.integerValueSansLocaleOfParameterNamed(toAccountTypeParamName);
|
||||
final PortfolioAccountType toAccountType = PortfolioAccountType.fromInt(toAccountTypeId);
|
||||
|
||||
final Long fromClientId = command.longValueOfParameterNamed(fromClientIdParamName);
|
||||
|
||||
Long standingInstructionId = null;
|
||||
try {
|
||||
if (isSavingsToSavingsAccountTransfer(fromAccountType, toAccountType)) {
|
||||
final AccountTransferDetails standingInstruction = this.standingInstructionAssembler
|
||||
.assembleSavingsToSavingsTransfer(command);
|
||||
this.accountTransferDetailRepository.saveAndFlush(standingInstruction);
|
||||
standingInstructionId = standingInstruction.accountTransferStandingInstruction().getId();
|
||||
} else if (isSavingsToLoanAccountTransfer(fromAccountType, toAccountType)) {
|
||||
final AccountTransferDetails standingInstruction = this.standingInstructionAssembler.assembleSavingsToLoanTransfer(command);
|
||||
this.accountTransferDetailRepository.saveAndFlush(standingInstruction);
|
||||
standingInstructionId = standingInstruction.accountTransferStandingInstruction().getId();
|
||||
} else if (isLoanToSavingsAccountTransfer(fromAccountType, toAccountType)) {
|
||||
|
||||
final AccountTransferDetails standingInstruction = this.standingInstructionAssembler.assembleLoanToSavingsTransfer(command);
|
||||
this.accountTransferDetailRepository.saveAndFlush(standingInstruction);
|
||||
standingInstructionId = standingInstruction.accountTransferStandingInstruction().getId();
|
||||
|
||||
}
|
||||
} catch (final JpaSystemException | DataIntegrityViolationException dve) {
|
||||
final Throwable throwable = dve.getMostSpecificCause();
|
||||
handleDataIntegrityIssues(command, throwable, dve);
|
||||
return CommandProcessingResult.empty();
|
||||
}
|
||||
final CommandProcessingResultBuilder builder = new CommandProcessingResultBuilder().withEntityId(standingInstructionId)
|
||||
.withClientId(fromClientId);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private void handleDataIntegrityIssues(final JsonCommand command, Throwable realCause, final NonTransientDataAccessException dve) {
|
||||
if (realCause.getMessage().contains("name")) {
|
||||
final String name = command.stringValueOfParameterNamed(StandingInstructionApiConstants.nameParamName);
|
||||
throw new PlatformDataIntegrityException("error.msg.standinginstruction.duplicate.name",
|
||||
"Standinginstruction with name `" + name + "` already exists", "name", name);
|
||||
}
|
||||
log.error("Error occured.", dve);
|
||||
throw ErrorHandler.getMappable(dve, "error.msg.client.unknown.data.integrity.issue",
|
||||
"Unknown data integrity issue with resource: " + realCause.getMessage());
|
||||
}
|
||||
|
||||
private boolean isLoanToSavingsAccountTransfer(final PortfolioAccountType fromAccountType, final PortfolioAccountType toAccountType) {
|
||||
return fromAccountType.isLoanAccount() && toAccountType.isSavingsAccount();
|
||||
}
|
||||
|
||||
private boolean isSavingsToLoanAccountTransfer(final PortfolioAccountType fromAccountType, final PortfolioAccountType toAccountType) {
|
||||
return fromAccountType.isSavingsAccount() && toAccountType.isLoanAccount();
|
||||
}
|
||||
|
||||
private boolean isSavingsToSavingsAccountTransfer(final PortfolioAccountType fromAccountType,
|
||||
final PortfolioAccountType toAccountType) {
|
||||
return fromAccountType.isSavingsAccount() && toAccountType.isSavingsAccount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult update(final Long id, final JsonCommand command) {
|
||||
this.standingInstructionDataValidator.validateForUpdate(command);
|
||||
AccountTransferStandingInstruction standingInstructionsForUpdate = this.standingInstructionRepository.findById(id)
|
||||
.orElseThrow(() -> new StandingInstructionNotFoundException(id));
|
||||
final Map<String, Object> actualChanges = standingInstructionsForUpdate.update(command);
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(id).with(actualChanges).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult delete(final Long id) {
|
||||
AccountTransferStandingInstruction standingInstructionsForUpdate = this.standingInstructionRepository.findById(id).orElseThrow();
|
||||
// update the "deleted" and "name" properties of the standing
|
||||
// instruction
|
||||
standingInstructionsForUpdate.delete();
|
||||
|
||||
final Map<String, Object> actualChanges = new HashMap<>();
|
||||
actualChanges.put(statusParamName, StandingInstructionStatus.DELETED.getValue());
|
||||
return new CommandProcessingResultBuilder().withEntityId(id).with(actualChanges).build();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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.account.service;
|
||||
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.fromAccountTypeParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.fromClientIdParamName;
|
||||
import static org.apache.fineract.portfolio.account.AccountDetailConstants.toAccountTypeParamName;
|
||||
import static org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants.statusParamName;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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.ErrorHandler;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.apache.fineract.portfolio.account.PortfolioAccountType;
|
||||
import org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants;
|
||||
import org.apache.fineract.portfolio.account.data.StandingInstructionDataValidator;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferDetailRepository;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferDetails;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferStandingInstruction;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionAssembler;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionRepository;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionStatus;
|
||||
import org.apache.fineract.portfolio.account.exception.StandingInstructionNotFoundException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.dao.NonTransientDataAccessException;
|
||||
import org.springframework.orm.jpa.JpaSystemException;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class StandingInstructionWritePlatformServiceImpl implements StandingInstructionWritePlatformService {
|
||||
|
||||
private final StandingInstructionDataValidator standingInstructionDataValidator;
|
||||
private final StandingInstructionAssembler standingInstructionAssembler;
|
||||
private final AccountTransferDetailRepository accountTransferDetailRepository;
|
||||
private final StandingInstructionRepository standingInstructionRepository;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult create(final JsonCommand command) {
|
||||
|
||||
this.standingInstructionDataValidator.validateForCreate(command);
|
||||
|
||||
final Integer fromAccountTypeId = command.integerValueSansLocaleOfParameterNamed(fromAccountTypeParamName);
|
||||
final PortfolioAccountType fromAccountType = PortfolioAccountType.fromInt(fromAccountTypeId);
|
||||
|
||||
final Integer toAccountTypeId = command.integerValueSansLocaleOfParameterNamed(toAccountTypeParamName);
|
||||
final PortfolioAccountType toAccountType = PortfolioAccountType.fromInt(toAccountTypeId);
|
||||
|
||||
final Long fromClientId = command.longValueOfParameterNamed(fromClientIdParamName);
|
||||
|
||||
Long standingInstructionId = null;
|
||||
try {
|
||||
if (isSavingsToSavingsAccountTransfer(fromAccountType, toAccountType)) {
|
||||
final AccountTransferDetails standingInstruction = this.standingInstructionAssembler
|
||||
.assembleSavingsToSavingsTransfer(command);
|
||||
this.accountTransferDetailRepository.saveAndFlush(standingInstruction);
|
||||
standingInstructionId = standingInstruction.accountTransferStandingInstruction().getId();
|
||||
} else if (isSavingsToLoanAccountTransfer(fromAccountType, toAccountType)) {
|
||||
final AccountTransferDetails standingInstruction = this.standingInstructionAssembler.assembleSavingsToLoanTransfer(command);
|
||||
this.accountTransferDetailRepository.saveAndFlush(standingInstruction);
|
||||
standingInstructionId = standingInstruction.accountTransferStandingInstruction().getId();
|
||||
} else if (isLoanToSavingsAccountTransfer(fromAccountType, toAccountType)) {
|
||||
final AccountTransferDetails standingInstruction = this.standingInstructionAssembler.assembleLoanToSavingsTransfer(command);
|
||||
this.accountTransferDetailRepository.saveAndFlush(standingInstruction);
|
||||
standingInstructionId = standingInstruction.accountTransferStandingInstruction().getId();
|
||||
} else if (isCurrentToCurrentAccountTransfer(fromAccountType, toAccountType)) {
|
||||
final AccountTransferDetails standingInstruction = this.standingInstructionAssembler.assembleCurrentToCurrentTransfer(command);
|
||||
this.accountTransferDetailRepository.saveAndFlush(standingInstruction);
|
||||
standingInstructionId = standingInstruction.accountTransferStandingInstruction().getId();
|
||||
} else if (isCurrentToSavingsAccountTransfer(fromAccountType, toAccountType)) {
|
||||
final AccountTransferDetails standingInstruction = this.standingInstructionAssembler.assembleCurrentToSavingsTransfer(command);
|
||||
this.accountTransferDetailRepository.saveAndFlush(standingInstruction);
|
||||
standingInstructionId = standingInstruction.accountTransferStandingInstruction().getId();
|
||||
} else if (isSavingsToCurrentAccountTransfer(fromAccountType, toAccountType)) {
|
||||
final AccountTransferDetails standingInstruction = this.standingInstructionAssembler.assembleSavingsToCurrentTransfer(command);
|
||||
this.accountTransferDetailRepository.saveAndFlush(standingInstruction);
|
||||
standingInstructionId = standingInstruction.accountTransferStandingInstruction().getId();
|
||||
} else if (isCurrentToLoanAccountTransfer(fromAccountType, toAccountType)) {
|
||||
final AccountTransferDetails standingInstruction = this.standingInstructionAssembler.assembleCurrentToLoanTransfer(command);
|
||||
this.accountTransferDetailRepository.saveAndFlush(standingInstruction);
|
||||
standingInstructionId = standingInstruction.accountTransferStandingInstruction().getId();
|
||||
}
|
||||
} catch (final JpaSystemException | DataIntegrityViolationException dve) {
|
||||
final Throwable throwable = dve.getMostSpecificCause();
|
||||
handleDataIntegrityIssues(command, throwable, dve);
|
||||
return CommandProcessingResult.empty();
|
||||
}
|
||||
final CommandProcessingResultBuilder builder = new CommandProcessingResultBuilder().withEntityId(standingInstructionId)
|
||||
.withClientId(fromClientId);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private void handleDataIntegrityIssues(final JsonCommand command, Throwable realCause, final NonTransientDataAccessException dve) {
|
||||
if (realCause.getMessage().contains("name")) {
|
||||
final String name = command.stringValueOfParameterNamed(StandingInstructionApiConstants.nameParamName);
|
||||
throw new PlatformDataIntegrityException("error.msg.standinginstruction.duplicate.name",
|
||||
"Standinginstruction with name `" + name + "` already exists", "name", name);
|
||||
}
|
||||
log.error("Error occured.", dve);
|
||||
throw ErrorHandler.getMappable(dve, "error.msg.client.unknown.data.integrity.issue",
|
||||
"Unknown data integrity issue with resource: " + realCause.getMessage());
|
||||
}
|
||||
|
||||
private boolean isLoanToSavingsAccountTransfer(final PortfolioAccountType fromAccountType, final PortfolioAccountType toAccountType) {
|
||||
return fromAccountType.isLoanAccount() && toAccountType.isSavingsAccount();
|
||||
}
|
||||
|
||||
private boolean isSavingsToLoanAccountTransfer(final PortfolioAccountType fromAccountType, final PortfolioAccountType toAccountType) {
|
||||
return fromAccountType.isSavingsAccount() && toAccountType.isLoanAccount();
|
||||
}
|
||||
|
||||
private boolean isSavingsToSavingsAccountTransfer(final PortfolioAccountType fromAccountType,
|
||||
final PortfolioAccountType toAccountType) {
|
||||
return fromAccountType.isSavingsAccount() && toAccountType.isSavingsAccount();
|
||||
}
|
||||
|
||||
private boolean isCurrentToCurrentAccountTransfer(final PortfolioAccountType fromAccountType,
|
||||
final PortfolioAccountType toAccountType) {
|
||||
return fromAccountType.isCurrentAccount() && toAccountType.isCurrentAccount();
|
||||
}
|
||||
|
||||
private boolean isCurrentToSavingsAccountTransfer(final PortfolioAccountType fromAccountType,
|
||||
final PortfolioAccountType toAccountType) {
|
||||
return fromAccountType.isCurrentAccount() && toAccountType.isSavingsAccount();
|
||||
}
|
||||
|
||||
private boolean isSavingsToCurrentAccountTransfer(final PortfolioAccountType fromAccountType,
|
||||
final PortfolioAccountType toAccountType) {
|
||||
return fromAccountType.isSavingsAccount() && toAccountType.isCurrentAccount();
|
||||
}
|
||||
|
||||
private boolean isCurrentToLoanAccountTransfer(final PortfolioAccountType fromAccountType,
|
||||
final PortfolioAccountType toAccountType) {
|
||||
return fromAccountType.isCurrentAccount() && toAccountType.isLoanAccount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult update(final Long id, final JsonCommand command) {
|
||||
this.standingInstructionDataValidator.validateForUpdate(command);
|
||||
AccountTransferStandingInstruction standingInstructionsForUpdate = this.standingInstructionRepository.findById(id)
|
||||
.orElseThrow(() -> new StandingInstructionNotFoundException(id));
|
||||
final Map<String, Object> actualChanges = standingInstructionsForUpdate.update(command);
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(id).with(actualChanges).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult delete(final Long id) {
|
||||
AccountTransferStandingInstruction standingInstructionsForUpdate = this.standingInstructionRepository.findById(id).orElseThrow();
|
||||
// update the "deleted" and "name" properties of the standing
|
||||
// instruction
|
||||
standingInstructionsForUpdate.delete();
|
||||
|
||||
final Map<String, Object> actualChanges = new HashMap<>();
|
||||
actualChanges.put(statusParamName, StandingInstructionStatus.DELETED.getValue());
|
||||
return new CommandProcessingResultBuilder().withEntityId(id).with(actualChanges).build();
|
||||
}
|
||||
}
|
||||
|
||||
+138
-134
@@ -1,134 +1,138 @@
|
||||
/**
|
||||
* 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.account.starter;
|
||||
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.apache.fineract.infrastructure.core.config.FineractProperties;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.infrastructure.core.service.PaginationHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
|
||||
import org.apache.fineract.infrastructure.security.service.SqlValidator;
|
||||
import org.apache.fineract.infrastructure.security.utils.ColumnValidator;
|
||||
import org.apache.fineract.organisation.office.service.OfficeReadPlatformService;
|
||||
import org.apache.fineract.portfolio.account.data.AccountTransfersDataValidator;
|
||||
import org.apache.fineract.portfolio.account.data.StandingInstructionDataValidator;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferAssembler;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferDetailRepository;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferRepository;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionAssembler;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionRepository;
|
||||
import org.apache.fineract.portfolio.account.mapper.AccountTransfersMapper;
|
||||
import org.apache.fineract.portfolio.account.service.AccountAssociationsReadPlatformService;
|
||||
import org.apache.fineract.portfolio.account.service.AccountAssociationsReadPlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.account.service.AccountTransfersReadPlatformService;
|
||||
import org.apache.fineract.portfolio.account.service.AccountTransfersReadPlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.account.service.AccountTransfersWritePlatformService;
|
||||
import org.apache.fineract.portfolio.account.service.AccountTransfersWritePlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.account.service.PortfolioAccountReadPlatformService;
|
||||
import org.apache.fineract.portfolio.account.service.PortfolioAccountReadPlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.account.service.StandingInstructionHistoryReadPlatformService;
|
||||
import org.apache.fineract.portfolio.account.service.StandingInstructionHistoryReadPlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.account.service.StandingInstructionReadPlatformService;
|
||||
import org.apache.fineract.portfolio.account.service.StandingInstructionReadPlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.account.service.StandingInstructionWritePlatformService;
|
||||
import org.apache.fineract.portfolio.account.service.StandingInstructionWritePlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.client.service.ClientReadPlatformService;
|
||||
import org.apache.fineract.portfolio.common.service.DropdownReadPlatformService;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformService;
|
||||
import org.apache.fineract.portfolio.savings.domain.GSIMRepositoy;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountAssembler;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountDomainService;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
@Configuration
|
||||
public class AccountConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(AccountAssociationsReadPlatformService.class)
|
||||
public AccountAssociationsReadPlatformService accountAssociationsReadPlatformService(JdbcTemplate jdbcTemplate) {
|
||||
return new AccountAssociationsReadPlatformServiceImpl(jdbcTemplate);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(AccountTransfersReadPlatformService.class)
|
||||
public AccountTransfersReadPlatformService accountTransfersReadPlatformService(JdbcTemplate jdbcTemplate,
|
||||
ClientReadPlatformService clientReadPlatformService, OfficeReadPlatformService officeReadPlatformService,
|
||||
PortfolioAccountReadPlatformService portfolioAccountReadPlatformService, ColumnValidator columnValidator,
|
||||
DatabaseSpecificSQLGenerator sqlGenerator, AccountTransfersMapper accountTransfersMapper, PaginationHelper paginationHelper,
|
||||
SqlValidator sqlValidator) {
|
||||
return new AccountTransfersReadPlatformServiceImpl(jdbcTemplate, clientReadPlatformService, officeReadPlatformService,
|
||||
portfolioAccountReadPlatformService, columnValidator, sqlGenerator, accountTransfersMapper, paginationHelper, sqlValidator);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(AccountTransfersWritePlatformService.class)
|
||||
public AccountTransfersWritePlatformService accountTransfersWritePlatformService(
|
||||
AccountTransfersDataValidator accountTransfersDataValidator, AccountTransferAssembler accountTransferAssembler,
|
||||
AccountTransferRepository accountTransferRepository, SavingsAccountAssembler savingsAccountAssembler,
|
||||
SavingsAccountDomainService savingsAccountDomainService, LoanAssembler loanAccountAssembler,
|
||||
LoanAccountDomainService loanAccountDomainService, SavingsAccountWritePlatformService savingsAccountWritePlatformService,
|
||||
AccountTransferDetailRepository accountTransferDetailRepository, LoanReadPlatformService loanReadPlatformService,
|
||||
GSIMRepositoy gsimRepository, ConfigurationDomainService configurationDomainService, ExternalIdFactory externalIdFactory,
|
||||
FineractProperties fineractProperties) {
|
||||
return new AccountTransfersWritePlatformServiceImpl(accountTransfersDataValidator, accountTransferAssembler,
|
||||
accountTransferRepository, savingsAccountAssembler, savingsAccountDomainService, loanAccountAssembler,
|
||||
loanAccountDomainService, savingsAccountWritePlatformService, accountTransferDetailRepository, loanReadPlatformService,
|
||||
gsimRepository, configurationDomainService, externalIdFactory, fineractProperties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(PortfolioAccountReadPlatformService.class)
|
||||
public PortfolioAccountReadPlatformService portfolioAccountReadPlatformService(JdbcTemplate jdbcTemplate,
|
||||
DatabaseSpecificSQLGenerator sqlGenerator) {
|
||||
return new PortfolioAccountReadPlatformServiceImpl(jdbcTemplate, sqlGenerator);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(StandingInstructionHistoryReadPlatformService.class)
|
||||
public StandingInstructionHistoryReadPlatformService standingInstructionHistoryReadPlatformService(JdbcTemplate jdbcTemplate,
|
||||
ColumnValidator columnValidator, DatabaseSpecificSQLGenerator sqlGenerator, PaginationHelper paginationHelper) {
|
||||
return new StandingInstructionHistoryReadPlatformServiceImpl(jdbcTemplate, columnValidator, sqlGenerator, paginationHelper);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(StandingInstructionReadPlatformService.class)
|
||||
public StandingInstructionReadPlatformService standingInstructionReadPlatformService(JdbcTemplate jdbcTemplate,
|
||||
ClientReadPlatformService clientReadPlatformService, OfficeReadPlatformService officeReadPlatformService,
|
||||
PortfolioAccountReadPlatformService portfolioAccountReadPlatformService,
|
||||
DropdownReadPlatformService dropdownReadPlatformService, ColumnValidator columnValidator,
|
||||
DatabaseSpecificSQLGenerator sqlGenerator, PaginationHelper paginationHelper) {
|
||||
return new StandingInstructionReadPlatformServiceImpl(jdbcTemplate, clientReadPlatformService, officeReadPlatformService,
|
||||
portfolioAccountReadPlatformService, dropdownReadPlatformService, columnValidator, sqlGenerator, paginationHelper);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(StandingInstructionWritePlatformService.class)
|
||||
public StandingInstructionWritePlatformService standingInstructionWritePlatformService(
|
||||
StandingInstructionDataValidator standingInstructionDataValidator, StandingInstructionAssembler standingInstructionAssembler,
|
||||
AccountTransferDetailRepository accountTransferDetailRepository, StandingInstructionRepository standingInstructionRepository) {
|
||||
return new StandingInstructionWritePlatformServiceImpl(standingInstructionDataValidator, standingInstructionAssembler,
|
||||
accountTransferDetailRepository, standingInstructionRepository);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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.account.starter;
|
||||
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.apache.fineract.infrastructure.core.config.FineractProperties;
|
||||
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
|
||||
import org.apache.fineract.infrastructure.core.service.PaginationHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
|
||||
import org.apache.fineract.infrastructure.security.service.SqlValidator;
|
||||
import org.apache.fineract.infrastructure.security.utils.ColumnValidator;
|
||||
import org.apache.fineract.organisation.office.service.OfficeReadPlatformService;
|
||||
import org.apache.fineract.portfolio.currentaccount.domain.CurrentAccountRepository;
|
||||
import org.apache.fineract.portfolio.currentaccount.domain.CurrentAccountTransactionRepository;
|
||||
import org.apache.fineract.portfolio.account.data.AccountTransfersDataValidator;
|
||||
import org.apache.fineract.portfolio.account.data.StandingInstructionDataValidator;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferAssembler;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferDetailRepository;
|
||||
import org.apache.fineract.portfolio.account.domain.AccountTransferRepository;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionAssembler;
|
||||
import org.apache.fineract.portfolio.account.domain.StandingInstructionRepository;
|
||||
import org.apache.fineract.portfolio.account.mapper.AccountTransfersMapper;
|
||||
import org.apache.fineract.portfolio.account.service.AccountAssociationsReadPlatformService;
|
||||
import org.apache.fineract.portfolio.account.service.AccountAssociationsReadPlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.account.service.AccountTransfersReadPlatformService;
|
||||
import org.apache.fineract.portfolio.account.service.AccountTransfersReadPlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.account.service.AccountTransfersWritePlatformService;
|
||||
import org.apache.fineract.portfolio.account.service.AccountTransfersWritePlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.account.service.PortfolioAccountReadPlatformService;
|
||||
import org.apache.fineract.portfolio.account.service.PortfolioAccountReadPlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.account.service.StandingInstructionHistoryReadPlatformService;
|
||||
import org.apache.fineract.portfolio.account.service.StandingInstructionHistoryReadPlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.account.service.StandingInstructionReadPlatformService;
|
||||
import org.apache.fineract.portfolio.account.service.StandingInstructionReadPlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.account.service.StandingInstructionWritePlatformService;
|
||||
import org.apache.fineract.portfolio.account.service.StandingInstructionWritePlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.client.service.ClientReadPlatformService;
|
||||
import org.apache.fineract.portfolio.common.service.DropdownReadPlatformService;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanAccountDomainService;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanReadPlatformService;
|
||||
import org.apache.fineract.portfolio.savings.domain.GSIMRepositoy;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsAccountAssembler;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountDomainService;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
@Configuration
|
||||
public class AccountConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(AccountAssociationsReadPlatformService.class)
|
||||
public AccountAssociationsReadPlatformService accountAssociationsReadPlatformService(JdbcTemplate jdbcTemplate) {
|
||||
return new AccountAssociationsReadPlatformServiceImpl(jdbcTemplate);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(AccountTransfersReadPlatformService.class)
|
||||
public AccountTransfersReadPlatformService accountTransfersReadPlatformService(JdbcTemplate jdbcTemplate,
|
||||
ClientReadPlatformService clientReadPlatformService, OfficeReadPlatformService officeReadPlatformService,
|
||||
PortfolioAccountReadPlatformService portfolioAccountReadPlatformService, ColumnValidator columnValidator,
|
||||
DatabaseSpecificSQLGenerator sqlGenerator, AccountTransfersMapper accountTransfersMapper, PaginationHelper paginationHelper,
|
||||
SqlValidator sqlValidator) {
|
||||
return new AccountTransfersReadPlatformServiceImpl(jdbcTemplate, clientReadPlatformService, officeReadPlatformService,
|
||||
portfolioAccountReadPlatformService, columnValidator, sqlGenerator, accountTransfersMapper, paginationHelper, sqlValidator);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(AccountTransfersWritePlatformService.class)
|
||||
public AccountTransfersWritePlatformService accountTransfersWritePlatformService(
|
||||
AccountTransfersDataValidator accountTransfersDataValidator, AccountTransferAssembler accountTransferAssembler,
|
||||
AccountTransferRepository accountTransferRepository, SavingsAccountAssembler savingsAccountAssembler,
|
||||
SavingsAccountDomainService savingsAccountDomainService, LoanAssembler loanAccountAssembler,
|
||||
LoanAccountDomainService loanAccountDomainService, SavingsAccountWritePlatformService savingsAccountWritePlatformService,
|
||||
AccountTransferDetailRepository accountTransferDetailRepository, LoanReadPlatformService loanReadPlatformService,
|
||||
GSIMRepositoy gsimRepository, ConfigurationDomainService configurationDomainService, ExternalIdFactory externalIdFactory,
|
||||
FineractProperties fineractProperties, CurrentAccountRepository currentAccountRepository,
|
||||
CurrentAccountTransactionRepository currentAccountTransactionRepository) {
|
||||
return new AccountTransfersWritePlatformServiceImpl(accountTransfersDataValidator, accountTransferAssembler,
|
||||
accountTransferRepository, savingsAccountAssembler, savingsAccountDomainService, loanAccountAssembler,
|
||||
loanAccountDomainService, savingsAccountWritePlatformService, accountTransferDetailRepository, loanReadPlatformService,
|
||||
gsimRepository, configurationDomainService, externalIdFactory, fineractProperties,
|
||||
currentAccountRepository, currentAccountTransactionRepository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(PortfolioAccountReadPlatformService.class)
|
||||
public PortfolioAccountReadPlatformService portfolioAccountReadPlatformService(JdbcTemplate jdbcTemplate,
|
||||
DatabaseSpecificSQLGenerator sqlGenerator) {
|
||||
return new PortfolioAccountReadPlatformServiceImpl(jdbcTemplate, sqlGenerator);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(StandingInstructionHistoryReadPlatformService.class)
|
||||
public StandingInstructionHistoryReadPlatformService standingInstructionHistoryReadPlatformService(JdbcTemplate jdbcTemplate,
|
||||
ColumnValidator columnValidator, DatabaseSpecificSQLGenerator sqlGenerator, PaginationHelper paginationHelper) {
|
||||
return new StandingInstructionHistoryReadPlatformServiceImpl(jdbcTemplate, columnValidator, sqlGenerator, paginationHelper);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(StandingInstructionReadPlatformService.class)
|
||||
public StandingInstructionReadPlatformService standingInstructionReadPlatformService(JdbcTemplate jdbcTemplate,
|
||||
ClientReadPlatformService clientReadPlatformService, OfficeReadPlatformService officeReadPlatformService,
|
||||
PortfolioAccountReadPlatformService portfolioAccountReadPlatformService,
|
||||
DropdownReadPlatformService dropdownReadPlatformService, ColumnValidator columnValidator,
|
||||
DatabaseSpecificSQLGenerator sqlGenerator, PaginationHelper paginationHelper) {
|
||||
return new StandingInstructionReadPlatformServiceImpl(jdbcTemplate, clientReadPlatformService, officeReadPlatformService,
|
||||
portfolioAccountReadPlatformService, dropdownReadPlatformService, columnValidator, sqlGenerator, paginationHelper);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(StandingInstructionWritePlatformService.class)
|
||||
public StandingInstructionWritePlatformService standingInstructionWritePlatformService(
|
||||
StandingInstructionDataValidator standingInstructionDataValidator, StandingInstructionAssembler standingInstructionAssembler,
|
||||
AccountTransferDetailRepository accountTransferDetailRepository, StandingInstructionRepository standingInstructionRepository) {
|
||||
return new StandingInstructionWritePlatformServiceImpl(standingInstructionDataValidator, standingInstructionAssembler,
|
||||
accountTransferDetailRepository, standingInstructionRepository);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -407,7 +407,7 @@ server.tomcat.mbeanregistry.enabled=${FINERACT_SERVER_TOMCAT_MBEANREGISTRY_ENABL
|
||||
spring.datasource.hikari.driverClassName=${FINERACT_HIKARI_DRIVER_SOURCE_CLASS_NAME:org.postgresql.Driver}
|
||||
spring.datasource.hikari.jdbcUrl=${FINERACT_HIKARI_JDBC_URL:jdbc:postgresql://localhost:5432/fineract_tenants}
|
||||
spring.datasource.hikari.username=${FINERACT_HIKARI_USERNAME:postgres}
|
||||
spring.datasource.hikari.password=${FINERACT_HIKARI_PASSWORD:root}
|
||||
spring.datasource.hikari.password=${FINERACT_HIKARI_PASSWORD:313863}
|
||||
spring.datasource.hikari.minimumIdle=${FINERACT_HIKARI_MINIMUM_IDLE:3}
|
||||
spring.datasource.hikari.maximumPoolSize=${FINERACT_HIKARI_MAXIMUM_POOL_SIZE:10}
|
||||
spring.datasource.hikari.idleTimeout=${FINERACT_HIKARI_IDLE_TIMEOUT:60000}
|
||||
|
||||
@@ -317,4 +317,5 @@
|
||||
<include file="parts/0298_unique_external_id_on_current_account.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0299_seed_indian_states.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0300_rename_fd_base_interest_rate_tables_to_cbs.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0301_add_current_account_to_transfer_details.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||
|
||||
<!-- Add from_current_account_id column to m_account_transfer_details -->
|
||||
<changeSet id="0301-1" author="cbs">
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<not>
|
||||
<columnExists tableName="m_account_transfer_details" columnName="from_current_account_id"/>
|
||||
</not>
|
||||
</preConditions>
|
||||
<addColumn tableName="m_account_transfer_details">
|
||||
<column name="from_current_account_id" type="BIGINT">
|
||||
<constraints nullable="true"
|
||||
foreignKeyName="FK_atd_from_current_account"
|
||||
references="m_current_account(id)"/>
|
||||
</column>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
|
||||
<!-- Add to_current_account_id column to m_account_transfer_details -->
|
||||
<changeSet id="0301-2" author="cbs">
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<not>
|
||||
<columnExists tableName="m_account_transfer_details" columnName="to_current_account_id"/>
|
||||
</not>
|
||||
</preConditions>
|
||||
<addColumn tableName="m_account_transfer_details">
|
||||
<column name="to_current_account_id" type="BIGINT">
|
||||
<constraints nullable="true"
|
||||
foreignKeyName="FK_atd_to_current_account"
|
||||
references="m_current_account(id)"/>
|
||||
</column>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
Reference in New Issue
Block a user