From 99c153830c4c366072f8ceeea716bee7a9d3385f Mon Sep 17 00:00:00 2001 From: keshav898966 Date: Wed, 1 Jul 2026 17:25:04 +0530 Subject: [PATCH] pending account terminate feature develop --- .../domain/CommandProcessingResultType.java | 7 +- .../service/CommandWrapperBuilder.java | 8 ++ .../SynchronousCommandProcessingService.java | 3 +- .../savings/data/SavingsAccountData.java | 1 + .../domain/SavingsAccountStatusType.java | 8 +- .../savings/service/SavingsEnumerations.java | 5 ++ .../currentaccount/domain/CurrentAccount.java | 11 +++ .../CurrentAccountWritePlatformService.java | 2 + .../api/AccountTerminateApiResource.java | 80 +++++++++++++++++++ .../AccountTerminateCommandHandler.java | 46 +++++++++++ .../AccountTerminateWritePlatformService.java | 27 +++++++ ...ountTerminateWritePlatformServiceImpl.java | 66 +++++++++++++++ .../api/CurrentAccountsApiResource.java | 49 +++++++----- ...CurrentAccountTerminateCommandHandler.java | 46 +++++++++++ ...DepositAccountTerminateCommandHandler.java | 46 +++++++++++ ...DepositAccountTerminateCommandHandler.java | 46 +++++++++++ ...SavingsAccountTerminateCommandHandler.java | 46 +++++++++++ .../ActivateCurrentAccountCommandHandler.java | 8 +- ...seSavingsCurrentAccountCommandHandler.java | 8 +- ...ountApplicationApprovalCommandHandler.java | 10 +-- ...ApplicationApprovalUndoCommandHandler.java | 10 +-- ...ountApplicationDeletionCommandHandler.java | 10 +-- ...ApplicationModificationCommandHandler.java | 10 +-- ...ountApplicationRejectedCommandHandler.java | 10 +-- ...untApplicationSubmittalCommandHandler.java | 10 +-- ...untApplicationWithdrawnCommandHandler.java | 10 +-- ...CurrentAccountReadPlatformServiceImpl.java | 34 +++++++- ...urrentAccountWritePlatformServiceImpl.java | 27 +++++++ ...SavingsAccountReadPlatformServiceImpl.java | 20 +++-- ...WritePlatformServiceJpaRepositoryImpl.java | 13 +++ .../db/changelog/tenant/changelog-tenant.xml | 1 + ...te_true_to_savings_and_current_account.xml | 22 +++++ .../savings/domain/SavingsAccount.java | 15 ++++ .../SavingsAccountWritePlatformService.java | 2 + 34 files changed, 641 insertions(+), 76 deletions(-) create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/account/api/AccountTerminateApiResource.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/account/handler/AccountTerminateCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTerminateWritePlatformService.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTerminateWritePlatformServiceImpl.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/CurrentAccountTerminateCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/FixedDepositAccountTerminateCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/RecurringDepositAccountTerminateCommandHandler.java create mode 100644 fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/SavingsAccountTerminateCommandHandler.java create mode 100644 fineract-provider/src/main/resources/db/changelog/tenant/parts/0340_add_terminate_true_to_savings_and_current_account.xml diff --git a/fineract-core/src/main/java/org/apache/fineract/commands/domain/CommandProcessingResultType.java b/fineract-core/src/main/java/org/apache/fineract/commands/domain/CommandProcessingResultType.java index 17f70dfe4..224490cc7 100644 --- a/fineract-core/src/main/java/org/apache/fineract/commands/domain/CommandProcessingResultType.java +++ b/fineract-core/src/main/java/org/apache/fineract/commands/domain/CommandProcessingResultType.java @@ -34,7 +34,8 @@ public enum CommandProcessingResultType { AWAITING_APPROVAL(2, "commandProcessingResultType.awaiting.approval"), // REJECTED(3, "commandProcessingResultType.rejected"), // UNDER_PROCESSING(4, "commandProcessingResultType.underProcessing"), // - ERROR(5, "commandProcessingResultType.error"); + ERROR(5, "commandProcessingResultType.error"), // + TERMINATE(6, "commandProcessingResultType.terminate"); private static final Map BY_ID = Arrays.stream(values()) .collect(Collectors.toMap(CommandProcessingResultType::getValue, v -> v)); @@ -59,4 +60,8 @@ public enum CommandProcessingResultType { public boolean isRejected() { return this == REJECTED; } + + public boolean isTerminate() { + return this == TERMINATE; + } } diff --git a/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java b/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java index b16b574c1..2f9cf0685 100644 --- a/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java +++ b/fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java @@ -1611,6 +1611,14 @@ public class CommandWrapperBuilder { return this; } + public CommandWrapperBuilder terminateAccount(final Long accountId) { + this.actionName = "TERMINATE"; + this.entityName = "ACCOUNT"; + this.entityId = accountId; + this.href = "/accounts/" + accountId + "/terminate"; + return this; + } + public CommandWrapperBuilder approveGSIMAccountApplication(final Long accountId) { this.actionName = "APPROVE"; this.entityName = "GSIMACCOUNT"; diff --git a/fineract-core/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java b/fineract-core/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java index a13835b62..ea09a0776 100644 --- a/fineract-core/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java +++ b/fineract-core/src/main/java/org/apache/fineract/commands/service/SynchronousCommandProcessingService.java @@ -20,6 +20,7 @@ package org.apache.fineract.commands.service; import static org.apache.fineract.commands.domain.CommandProcessingResultType.ERROR; import static org.apache.fineract.commands.domain.CommandProcessingResultType.PROCESSED; +import static org.apache.fineract.commands.domain.CommandProcessingResultType.TERMINATE; import static org.apache.http.HttpStatus.SC_OK; import com.google.gson.Gson; @@ -181,7 +182,7 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer currentSource.setResultStatusCode(SC_OK); currentSource.updateForAudit(result); currentSource.setResult(toApiResultJsonSerializer.serializeResult(result)); - currentSource.setStatus(PROCESSED); + currentSource.setStatus("TERMINATE".equals(wrapper.getActionName()) ? TERMINATE : PROCESSED); // Return saved command source return commandSourceService.saveResultSameTransaction(currentSource); diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountData.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountData.java index 544d0f35f..def3e27f7 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountData.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsAccountData.java @@ -170,6 +170,7 @@ public final class SavingsAccountData implements Serializable { private Boolean balanceSwapOption; private Boolean msme; private Boolean autoDebitFacility; + private Boolean terminateTrue; private String avgBalanceCalcPeriod; private String validForPeriod; private Boolean odAccountClosedZeroBalanceInDayClosing; diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountStatusType.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountStatusType.java index ffe2fefaf..ef61b14de 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountStatusType.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccountStatusType.java @@ -36,7 +36,8 @@ public enum SavingsAccountStatusType { REJECTED(500, "savingsAccountStatusType.rejected"), // CLOSED(600, "savingsAccountStatusType.closed"), // PRE_MATURE_CLOSURE(700, "savingsAccountStatusType.pre.mature.closure"), // - MATURED(800, "savingsAccountStatusType.matured"); // + MATURED(800, "savingsAccountStatusType.matured"), // + TERMINATED(900, "savingsAccountStatusType.terminated"); // private final Integer value; private final String code; @@ -53,6 +54,7 @@ public enum SavingsAccountStatusType { case 600 -> SavingsAccountStatusType.CLOSED; case 700 -> SavingsAccountStatusType.PRE_MATURE_CLOSURE; case 800 -> SavingsAccountStatusType.MATURED; + case 900 -> SavingsAccountStatusType.TERMINATED; default -> SavingsAccountStatusType.INVALID; }; } @@ -113,4 +115,8 @@ public enum SavingsAccountStatusType { public boolean isPreMatureClosure() { return this.value.equals(SavingsAccountStatusType.PRE_MATURE_CLOSURE.getValue()); } + + public boolean isTerminated() { + return this.value.equals(SavingsAccountStatusType.TERMINATED.getValue()); + } } diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsEnumerations.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsEnumerations.java index 7f4cab97b..57e025a06 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsEnumerations.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsEnumerations.java @@ -285,6 +285,11 @@ public final class SavingsEnumerations { SavingsAccountStatusType.MATURED.getCode(), "Matured", submittedAndPendingApproval, isApproved, isRejected, isWithdrawnByApplicant, isActive, isClosed, isPrematureClosed, isTransferInProgress, isTransferOnHold, matured); break; + case TERMINATED: + optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.TERMINATED.getValue().longValue(), + SavingsAccountStatusType.TERMINATED.getCode(), "Terminated", submittedAndPendingApproval, isApproved, isRejected, + isWithdrawnByApplicant, isActive, isClosed, isPrematureClosed, isTransferInProgress, isTransferOnHold, matured); + break; } return optionData; } diff --git a/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentaccount/domain/CurrentAccount.java b/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentaccount/domain/CurrentAccount.java index 4e44db25d..38bf40627 100644 --- a/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentaccount/domain/CurrentAccount.java +++ b/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentaccount/domain/CurrentAccount.java @@ -332,6 +332,9 @@ public class CurrentAccount extends AbstractAuditableCustom { @Column(name = "is_linking_enable", nullable = false) private boolean shareLinkingEnabled = false; + @Column(name = "terminate_true", nullable = false, columnDefinition = "boolean default false") + private boolean terminateTrue = false; + // Relationships @OneToMany(mappedBy = "currentAccount", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) @@ -442,4 +445,12 @@ public class CurrentAccount extends AbstractAuditableCustom { public boolean isShareLinkingEnabled() { return shareLinkingEnabled; } public void setShareLinkingEnabled(boolean shareLinkingEnabled) { this.shareLinkingEnabled = shareLinkingEnabled; } + + public boolean isTerminateTrue() { return terminateTrue; } + public void setTerminateTrue(boolean terminateTrue) { this.terminateTrue = terminateTrue; } + + public void terminate() { + this.terminateTrue = true; + this.statusEnum = 900; + } } diff --git a/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentaccount/service/CurrentAccountWritePlatformService.java b/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentaccount/service/CurrentAccountWritePlatformService.java index c3c1a85f9..2556aaf46 100644 --- a/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentaccount/service/CurrentAccountWritePlatformService.java +++ b/fineract-current-product/src/main/java/org/apache/fineract/portfolio/currentaccount/service/CurrentAccountWritePlatformService.java @@ -40,4 +40,6 @@ public interface CurrentAccountWritePlatformService { CommandProcessingResult modifyApplication(Long accountId, JsonCommand command); CommandProcessingResult deleteApplication(Long accountId); + + CommandProcessingResult terminateAccount(Long accountId, JsonCommand command); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/api/AccountTerminateApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/api/AccountTerminateApiResource.java new file mode 100644 index 000000000..3128afbef --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/api/AccountTerminateApiResource.java @@ -0,0 +1,80 @@ +/** + * 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.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.StringUtils; +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.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer; +import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; +import com.google.gson.JsonElement; +import org.springframework.stereotype.Component; + +@Path("/v1/accounts/{accountId}/terminate") +@Component +@Tag(name = "Account Terminate", description = "Unified terminate endpoint for Savings, Current, FD and RD accounts.") +@RequiredArgsConstructor +public class AccountTerminateApiResource { + + private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; + private final DefaultToApiJsonSerializer toApiJsonSerializer; + private final FromJsonHelper fromJsonHelper; + + @POST + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + @Operation(summary = "Terminate an account", description = "Terminates a Savings, Current, Fixed Deposit or Recurring Deposit account. Pass accountType in the request body: SAVINGS | CURRENT | FD | RD.") + @ApiResponse(responseCode = "200", description = "OK") + public String terminate(@PathParam("accountId") final Long accountId, + final String apiRequestBodyAsJson) { + + final String jsonBody = StringUtils.isBlank(apiRequestBodyAsJson) ? "{}" : apiRequestBodyAsJson; + + final JsonElement root = this.fromJsonHelper.parse(jsonBody); + final String accountType = this.fromJsonHelper.extractStringNamed("accountType", root); + String entityName = "SAVINGSACCOUNT"; + if ("CURRENT".equalsIgnoreCase(accountType)) { + entityName = "CURRENTACCOUNT"; + } else if ("FD".equalsIgnoreCase(accountType)) { + entityName = "FIXEDDEPOSITACCOUNT"; + } else if ("RD".equalsIgnoreCase(accountType)) { + entityName = "RECURRINGDEPOSITACCOUNT"; + } + + final CommandWrapper commandRequest = new CommandWrapperBuilder() + .withJson(jsonBody) + .terminateAccount(accountId) + .withEntityName(entityName) + .build(); + final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest); + return toApiJsonSerializer.serialize(result); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/handler/AccountTerminateCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/handler/AccountTerminateCommandHandler.java new file mode 100644 index 000000000..9f6a2553c --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/handler/AccountTerminateCommandHandler.java @@ -0,0 +1,46 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.account.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.account.service.AccountTerminateWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "ACCOUNT", action = "TERMINATE") +public class AccountTerminateCommandHandler implements NewCommandSourceHandler { + + private final AccountTerminateWritePlatformService writePlatformService; + + @Autowired + public AccountTerminateCommandHandler(final AccountTerminateWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + return this.writePlatformService.terminate(command.entityId(), command); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTerminateWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTerminateWritePlatformService.java new file mode 100644 index 000000000..b75bc4787 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTerminateWritePlatformService.java @@ -0,0 +1,27 @@ +/** + * 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.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; + +public interface AccountTerminateWritePlatformService { + + CommandProcessingResult terminate(Long accountId, JsonCommand command); +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTerminateWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTerminateWritePlatformServiceImpl.java new file mode 100644 index 000000000..045d24ced --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/account/service/AccountTerminateWritePlatformServiceImpl.java @@ -0,0 +1,66 @@ +/** + * 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 lombok.RequiredArgsConstructor; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException; +import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountWritePlatformService; +import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * Routes terminate to the correct account service based on the + * "accountType" field in the JSON body: + * SAVINGS → m_savings_account (depositType = savings) + * FD → m_savings_account (depositType = 200) + * RD → m_savings_account (depositType = 300) + * CURRENT → m_current_account + */ +@Service +@RequiredArgsConstructor +public class AccountTerminateWritePlatformServiceImpl implements AccountTerminateWritePlatformService { + + private static final String PARAM_ACCOUNT_TYPE = "accountType"; + + private final SavingsAccountWritePlatformService savingsAccountWritePlatformService; + private final CurrentAccountWritePlatformService currentAccountWritePlatformService; + + @Override + @Transactional + public CommandProcessingResult terminate(final Long accountId, final JsonCommand command) { + final String accountType = command.stringValueOfParameterNamed(PARAM_ACCOUNT_TYPE); + + if (accountType == null || accountType.isBlank()) { + throw new PlatformDataIntegrityException( + "error.msg.account.terminate.accountType.required", + "accountType is required: SAVINGS, CURRENT, FD or RD"); + } + + return switch (accountType.toUpperCase()) { + case "CURRENT" -> currentAccountWritePlatformService.terminateAccount(accountId, command); + case "SAVINGS", "FD", "RD" -> savingsAccountWritePlatformService.terminate(accountId, command); + default -> throw new PlatformDataIntegrityException( + "error.msg.account.terminate.accountType.invalid", + "Unknown accountType '" + accountType + "'. Expected SAVINGS, CURRENT, FD or RD."); + }; + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/CurrentAccountsApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/CurrentAccountsApiResource.java index ccaf3ff11..a0310f85a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/CurrentAccountsApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/CurrentAccountsApiResource.java @@ -53,6 +53,9 @@ import org.apache.fineract.infrastructure.security.service.SqlValidator; import org.apache.fineract.portfolio.savings.DepositsApiConstants; import org.apache.fineract.portfolio.savings.data.SavingsAccountData; import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountReadPlatformService; +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.portfolio.currentaccount.service.CurrentAccountWritePlatformService; import org.apache.fineract.portfolio.savings.service.CurrentAccountTemplateReadPlatformService; import org.springframework.stereotype.Component; @@ -72,6 +75,7 @@ public class CurrentAccountsApiResource { private final SqlValidator sqlValidator; private final CurrentAccountWritePlatformService currentAccountWritePlatformService; private final CurrentAccountReadPlatformService currentAccountReadPlatformService; + private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; @GET @Path("template") @@ -125,10 +129,11 @@ public class CurrentAccountsApiResource { @Operation(summary = "Submit new current account application") @ApiResponse(responseCode = "200", description = "OK") public String submitApplication(@Parameter(hidden = true) final String apiRequestBodyAsJson) { - final org.apache.fineract.infrastructure.core.api.JsonCommand command = - org.apache.fineract.infrastructure.core.api.JsonCommand.fromJsonElement(null, - JsonParser.parseString(apiRequestBodyAsJson != null ? apiRequestBodyAsJson : "{}")); - final CommandProcessingResult result = currentAccountWritePlatformService.submitApplication(command); + final CommandWrapper commandRequest = new CommandWrapperBuilder() // + .createCurrentAccount() // + .withJson(apiRequestBodyAsJson) // + .build(); + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); return toApiJsonSerializer.serialize(result); } @@ -157,11 +162,11 @@ public class CurrentAccountsApiResource { public String update(@PathParam("accountId") final Long accountId, @Parameter(hidden = true) final String apiRequestBodyAsJson, @QueryParam("command") final String commandParam) { - - final org.apache.fineract.infrastructure.core.api.JsonCommand command = - org.apache.fineract.infrastructure.core.api.JsonCommand.fromJsonElement(null, - JsonParser.parseString(apiRequestBodyAsJson != null ? apiRequestBodyAsJson : "{}")); - final CommandProcessingResult result = currentAccountWritePlatformService.modifyApplication(accountId, command); + final CommandWrapper commandRequest = new CommandWrapperBuilder() // + .updateCurrentAccount(accountId) // + .withJson(apiRequestBodyAsJson) // + .build(); + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); return toApiJsonSerializer.serialize(result); } @@ -180,30 +185,29 @@ public class CurrentAccountsApiResource { jsonApiRequest = "{}"; } - final org.apache.fineract.infrastructure.core.api.JsonCommand command = - org.apache.fineract.infrastructure.core.api.JsonCommand.fromJsonElement(null, - JsonParser.parseString(jsonApiRequest)); + final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(jsonApiRequest); - CommandProcessingResult result = null; + CommandWrapper commandRequest = null; if (is(commandParam, "reject")) { - result = currentAccountWritePlatformService.rejectApplication(accountId, command); + commandRequest = builder.rejectCurrentAccountApplication(accountId).build(); } else if (is(commandParam, "withdrawnByApplicant")) { - result = currentAccountWritePlatformService.withdrawApplication(accountId, command); + commandRequest = builder.withdrawCurrentAccountApplication(accountId).build(); } else if (is(commandParam, "approve")) { - result = currentAccountWritePlatformService.approveApplication(accountId, command); + commandRequest = builder.approveCurrentAccountApplication(accountId).build(); } else if (is(commandParam, "undoapproval")) { - result = currentAccountWritePlatformService.undoApproval(accountId, command); + commandRequest = builder.undoCurrentAccountApplication(accountId).build(); } else if (is(commandParam, "activate")) { - result = currentAccountWritePlatformService.activate(accountId, command); + commandRequest = builder.currentAccountActivation(accountId).build(); } else if (is(commandParam, "close")) { - result = currentAccountWritePlatformService.closeAccount(accountId, command); + commandRequest = builder.closeCurrentAccountApplication(accountId).build(); } - if (result == null) { + if (commandRequest == null) { throw new UnrecognizedQueryParamException("command", commandParam, new Object[] { "reject", "withdrawnByApplicant", "approve", "undoapproval", "activate", "close" }); } + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); return toApiJsonSerializer.serialize(result); } @@ -214,7 +218,10 @@ public class CurrentAccountsApiResource { @Operation(summary = "Delete a current account application") @ApiResponse(responseCode = "200", description = "OK") public String delete(@PathParam("accountId") final Long accountId) { - final CommandProcessingResult result = currentAccountWritePlatformService.deleteApplication(accountId); + final CommandWrapper commandRequest = new CommandWrapperBuilder() // + .deleteCurrentAccount(accountId) // + .build(); + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); return toApiJsonSerializer.serialize(result); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/CurrentAccountTerminateCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/CurrentAccountTerminateCommandHandler.java new file mode 100644 index 000000000..db55dbe87 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/CurrentAccountTerminateCommandHandler.java @@ -0,0 +1,46 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.savings.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "CURRENTACCOUNT", action = "TERMINATE") +public class CurrentAccountTerminateCommandHandler implements NewCommandSourceHandler { + + private final CurrentAccountWritePlatformService writePlatformService; + + @Autowired + public CurrentAccountTerminateCommandHandler(final CurrentAccountWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + return this.writePlatformService.terminateAccount(command.entityId(), command); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/FixedDepositAccountTerminateCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/FixedDepositAccountTerminateCommandHandler.java new file mode 100644 index 000000000..f6cbd0a1d --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/FixedDepositAccountTerminateCommandHandler.java @@ -0,0 +1,46 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.savings.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "FIXEDDEPOSITACCOUNT", action = "TERMINATE") +public class FixedDepositAccountTerminateCommandHandler implements NewCommandSourceHandler { + + private final SavingsAccountWritePlatformService writePlatformService; + + @Autowired + public FixedDepositAccountTerminateCommandHandler(final SavingsAccountWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + return this.writePlatformService.terminate(command.entityId(), command); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/RecurringDepositAccountTerminateCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/RecurringDepositAccountTerminateCommandHandler.java new file mode 100644 index 000000000..1290af244 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/RecurringDepositAccountTerminateCommandHandler.java @@ -0,0 +1,46 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.savings.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "RECURRINGDEPOSITACCOUNT", action = "TERMINATE") +public class RecurringDepositAccountTerminateCommandHandler implements NewCommandSourceHandler { + + private final SavingsAccountWritePlatformService writePlatformService; + + @Autowired + public RecurringDepositAccountTerminateCommandHandler(final SavingsAccountWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + return this.writePlatformService.terminate(command.entityId(), command); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/SavingsAccountTerminateCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/SavingsAccountTerminateCommandHandler.java new file mode 100644 index 000000000..723f496c3 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/SavingsAccountTerminateCommandHandler.java @@ -0,0 +1,46 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.savings.handler; + +import org.apache.fineract.commands.annotation.CommandType; +import org.apache.fineract.commands.handler.NewCommandSourceHandler; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; +import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "SAVINGSACCOUNT", action = "TERMINATE") +public class SavingsAccountTerminateCommandHandler implements NewCommandSourceHandler { + + private final SavingsAccountWritePlatformService writePlatformService; + + @Autowired + public SavingsAccountTerminateCommandHandler(final SavingsAccountWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + return this.writePlatformService.terminate(command.entityId(), command); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/ActivateCurrentAccountCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/ActivateCurrentAccountCommandHandler.java index f8b6c5e02..5a3968a35 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/ActivateCurrentAccountCommandHandler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/ActivateCurrentAccountCommandHandler.java @@ -22,7 +22,7 @@ import org.apache.fineract.commands.annotation.CommandType; import org.apache.fineract.commands.handler.NewCommandSourceHandler; import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; -import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService; +import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountWritePlatformService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -31,16 +31,16 @@ import org.springframework.transaction.annotation.Transactional; @CommandType(entity = "CURRENTACCOUNT", action = "ACTIVATE") public class ActivateCurrentAccountCommandHandler implements NewCommandSourceHandler { - private final SavingsAccountWritePlatformService writePlatformService; + private final CurrentAccountWritePlatformService writePlatformService; @Autowired - public ActivateCurrentAccountCommandHandler(final SavingsAccountWritePlatformService writePlatformService) { + public ActivateCurrentAccountCommandHandler(final CurrentAccountWritePlatformService writePlatformService) { this.writePlatformService = writePlatformService; } @Transactional @Override public CommandProcessingResult processCommand(final JsonCommand command) { - return this.writePlatformService.activate(command.getSavingsId(), command); + return this.writePlatformService.activate(command.entityId(), command); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CloseSavingsCurrentAccountCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CloseSavingsCurrentAccountCommandHandler.java index e35ab2855..b67fc318f 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CloseSavingsCurrentAccountCommandHandler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CloseSavingsCurrentAccountCommandHandler.java @@ -22,7 +22,7 @@ import org.apache.fineract.commands.annotation.CommandType; import org.apache.fineract.commands.handler.NewCommandSourceHandler; import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; -import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService; +import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountWritePlatformService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -31,16 +31,16 @@ import org.springframework.transaction.annotation.Transactional; @CommandType(entity = "CURRENTACCOUNT", action = "CLOSE") public class CloseSavingsCurrentAccountCommandHandler implements NewCommandSourceHandler { - private final SavingsAccountWritePlatformService writePlatformService; + private final CurrentAccountWritePlatformService writePlatformService; @Autowired - public CloseSavingsCurrentAccountCommandHandler(final SavingsAccountWritePlatformService writePlatformService) { + public CloseSavingsCurrentAccountCommandHandler(final CurrentAccountWritePlatformService writePlatformService) { this.writePlatformService = writePlatformService; } @Transactional @Override public CommandProcessingResult processCommand(final JsonCommand command) { - return this.writePlatformService.close(command.getSavingsId(), command); + return this.writePlatformService.closeAccount(command.entityId(), command); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationApprovalCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationApprovalCommandHandler.java index 8b06c11c5..179b7d658 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationApprovalCommandHandler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationApprovalCommandHandler.java @@ -22,7 +22,7 @@ import org.apache.fineract.commands.annotation.CommandType; import org.apache.fineract.commands.handler.NewCommandSourceHandler; import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; -import org.apache.fineract.portfolio.savings.service.SavingsApplicationProcessWritePlatformService; +import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountWritePlatformService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -31,16 +31,16 @@ import org.springframework.transaction.annotation.Transactional; @CommandType(entity = "CURRENTACCOUNT", action = "APPROVE") public class CurrentAccountApplicationApprovalCommandHandler implements NewCommandSourceHandler { - private final SavingsApplicationProcessWritePlatformService applicationProcessService; + private final CurrentAccountWritePlatformService writePlatformService; @Autowired - public CurrentAccountApplicationApprovalCommandHandler(final SavingsApplicationProcessWritePlatformService applicationProcessService) { - this.applicationProcessService = applicationProcessService; + public CurrentAccountApplicationApprovalCommandHandler(final CurrentAccountWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; } @Transactional @Override public CommandProcessingResult processCommand(final JsonCommand command) { - return this.applicationProcessService.approveApplication(command.getSavingsId(), command); + return this.writePlatformService.approveApplication(command.entityId(), command); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationApprovalUndoCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationApprovalUndoCommandHandler.java index 0ed4e8466..b5606d47b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationApprovalUndoCommandHandler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationApprovalUndoCommandHandler.java @@ -22,7 +22,7 @@ import org.apache.fineract.commands.annotation.CommandType; import org.apache.fineract.commands.handler.NewCommandSourceHandler; import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; -import org.apache.fineract.portfolio.savings.service.SavingsApplicationProcessWritePlatformService; +import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountWritePlatformService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -31,16 +31,16 @@ import org.springframework.transaction.annotation.Transactional; @CommandType(entity = "CURRENTACCOUNT", action = "APPROVALUNDO") public class CurrentAccountApplicationApprovalUndoCommandHandler implements NewCommandSourceHandler { - private final SavingsApplicationProcessWritePlatformService applicationProcessService; + private final CurrentAccountWritePlatformService writePlatformService; @Autowired - public CurrentAccountApplicationApprovalUndoCommandHandler(final SavingsApplicationProcessWritePlatformService applicationProcessService) { - this.applicationProcessService = applicationProcessService; + public CurrentAccountApplicationApprovalUndoCommandHandler(final CurrentAccountWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; } @Transactional @Override public CommandProcessingResult processCommand(final JsonCommand command) { - return this.applicationProcessService.undoApplicationApproval(command.getSavingsId(), command); + return this.writePlatformService.undoApproval(command.entityId(), command); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationDeletionCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationDeletionCommandHandler.java index 135c146c6..05d732076 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationDeletionCommandHandler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationDeletionCommandHandler.java @@ -22,7 +22,7 @@ import org.apache.fineract.commands.annotation.CommandType; import org.apache.fineract.commands.handler.NewCommandSourceHandler; import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; -import org.apache.fineract.portfolio.savings.service.SavingsApplicationProcessWritePlatformService; +import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountWritePlatformService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -31,16 +31,16 @@ import org.springframework.transaction.annotation.Transactional; @CommandType(entity = "CURRENTACCOUNT", action = "DELETE") public class CurrentAccountApplicationDeletionCommandHandler implements NewCommandSourceHandler { - private final SavingsApplicationProcessWritePlatformService applicationProcessService; + private final CurrentAccountWritePlatformService writePlatformService; @Autowired - public CurrentAccountApplicationDeletionCommandHandler(final SavingsApplicationProcessWritePlatformService applicationProcessService) { - this.applicationProcessService = applicationProcessService; + public CurrentAccountApplicationDeletionCommandHandler(final CurrentAccountWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; } @Transactional @Override public CommandProcessingResult processCommand(final JsonCommand command) { - return this.applicationProcessService.deleteApplication(command.getSavingsId()); + return this.writePlatformService.deleteApplication(command.entityId()); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationModificationCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationModificationCommandHandler.java index ce731650b..a23f47d71 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationModificationCommandHandler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationModificationCommandHandler.java @@ -22,7 +22,7 @@ import org.apache.fineract.commands.annotation.CommandType; import org.apache.fineract.commands.handler.NewCommandSourceHandler; import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; -import org.apache.fineract.portfolio.savings.service.SavingsApplicationProcessWritePlatformService; +import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountWritePlatformService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -31,16 +31,16 @@ import org.springframework.transaction.annotation.Transactional; @CommandType(entity = "CURRENTACCOUNT", action = "UPDATE") public class CurrentAccountApplicationModificationCommandHandler implements NewCommandSourceHandler { - private final SavingsApplicationProcessWritePlatformService applicationProcessService; + private final CurrentAccountWritePlatformService writePlatformService; @Autowired - public CurrentAccountApplicationModificationCommandHandler(final SavingsApplicationProcessWritePlatformService applicationProcessService) { - this.applicationProcessService = applicationProcessService; + public CurrentAccountApplicationModificationCommandHandler(final CurrentAccountWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; } @Transactional @Override public CommandProcessingResult processCommand(final JsonCommand command) { - return this.applicationProcessService.modifyApplication(command.getSavingsId(), command); + return this.writePlatformService.modifyApplication(command.entityId(), command); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationRejectedCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationRejectedCommandHandler.java index a3219d2ed..07984f1c7 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationRejectedCommandHandler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationRejectedCommandHandler.java @@ -22,7 +22,7 @@ import org.apache.fineract.commands.annotation.CommandType; import org.apache.fineract.commands.handler.NewCommandSourceHandler; import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; -import org.apache.fineract.portfolio.savings.service.SavingsApplicationProcessWritePlatformService; +import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountWritePlatformService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -31,16 +31,16 @@ import org.springframework.transaction.annotation.Transactional; @CommandType(entity = "CURRENTACCOUNT", action = "REJECT") public class CurrentAccountApplicationRejectedCommandHandler implements NewCommandSourceHandler { - private final SavingsApplicationProcessWritePlatformService applicationProcessService; + private final CurrentAccountWritePlatformService writePlatformService; @Autowired - public CurrentAccountApplicationRejectedCommandHandler(final SavingsApplicationProcessWritePlatformService applicationProcessService) { - this.applicationProcessService = applicationProcessService; + public CurrentAccountApplicationRejectedCommandHandler(final CurrentAccountWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; } @Transactional @Override public CommandProcessingResult processCommand(final JsonCommand command) { - return this.applicationProcessService.rejectApplication(command.getSavingsId(), command); + return this.writePlatformService.rejectApplication(command.entityId(), command); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationSubmittalCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationSubmittalCommandHandler.java index fc0a4e455..a98804672 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationSubmittalCommandHandler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationSubmittalCommandHandler.java @@ -22,7 +22,7 @@ import org.apache.fineract.commands.annotation.CommandType; import org.apache.fineract.commands.handler.NewCommandSourceHandler; import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; -import org.apache.fineract.portfolio.savings.service.SavingsApplicationProcessWritePlatformService; +import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountWritePlatformService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -31,16 +31,16 @@ import org.springframework.transaction.annotation.Transactional; @CommandType(entity = "CURRENTACCOUNT", action = "CREATE") public class CurrentAccountApplicationSubmittalCommandHandler implements NewCommandSourceHandler { - private final SavingsApplicationProcessWritePlatformService applicationProcessService; + private final CurrentAccountWritePlatformService writePlatformService; @Autowired - public CurrentAccountApplicationSubmittalCommandHandler(final SavingsApplicationProcessWritePlatformService applicationProcessService) { - this.applicationProcessService = applicationProcessService; + public CurrentAccountApplicationSubmittalCommandHandler(final CurrentAccountWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; } @Transactional @Override public CommandProcessingResult processCommand(final JsonCommand command) { - return this.applicationProcessService.submitApplication(command); + return this.writePlatformService.submitApplication(command); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationWithdrawnCommandHandler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationWithdrawnCommandHandler.java index 52d761c43..5c9c70f6b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationWithdrawnCommandHandler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/handler/current/CurrentAccountApplicationWithdrawnCommandHandler.java @@ -22,7 +22,7 @@ import org.apache.fineract.commands.annotation.CommandType; import org.apache.fineract.commands.handler.NewCommandSourceHandler; import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; -import org.apache.fineract.portfolio.savings.service.SavingsApplicationProcessWritePlatformService; +import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountWritePlatformService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -31,16 +31,16 @@ import org.springframework.transaction.annotation.Transactional; @CommandType(entity = "CURRENTACCOUNT", action = "WITHDRAW") public class CurrentAccountApplicationWithdrawnCommandHandler implements NewCommandSourceHandler { - private final SavingsApplicationProcessWritePlatformService applicationProcessService; + private final CurrentAccountWritePlatformService writePlatformService; @Autowired - public CurrentAccountApplicationWithdrawnCommandHandler(final SavingsApplicationProcessWritePlatformService applicationProcessService) { - this.applicationProcessService = applicationProcessService; + public CurrentAccountApplicationWithdrawnCommandHandler(final CurrentAccountWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; } @Transactional @Override public CommandProcessingResult processCommand(final JsonCommand command) { - return this.applicationProcessService.applicantWithdrawsFromApplication(command.getSavingsId(), command); + return this.writePlatformService.withdrawApplication(command.entityId(), command); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/CurrentAccountReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/CurrentAccountReadPlatformServiceImpl.java index 37d489877..42752b631 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/CurrentAccountReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/CurrentAccountReadPlatformServiceImpl.java @@ -297,12 +297,21 @@ public class CurrentAccountReadPlatformServiceImpl implements CurrentAccountRead hasWhere = true; } if (StringUtils.isNotBlank(status)) { - final Integer statusEnum = resolveStatusEnum(status); - if (statusEnum != null) { + if ("terminated".equalsIgnoreCase(status)) { sqlBuilder.append(hasWhere ? " AND " : " WHERE "); - sqlBuilder.append("ca.status_enum = ?"); - params.add(statusEnum); + sqlBuilder.append("ca.terminate_true = true"); hasWhere = true; + } else { + final Integer statusEnum = resolveStatusEnum(status); + if (statusEnum != null) { + sqlBuilder.append(hasWhere ? " AND " : " WHERE "); + sqlBuilder.append("ca.status_enum = ?"); + params.add(statusEnum); + hasWhere = true; + if (statusEnum == 100) { + sqlBuilder.append(" AND (ca.terminate_true = false OR ca.terminate_true IS NULL)"); + } + } } } if (fromDate != null) { @@ -356,6 +365,7 @@ public class CurrentAccountReadPlatformServiceImpl implements CurrentAccountRead case "withdrawn" -> 400; case "rejected" -> 500; case "closed" -> 600; + case "terminated" -> 900; default -> { try { yield Integer.parseInt(status); @@ -389,6 +399,7 @@ public class CurrentAccountReadPlatformServiceImpl implements CurrentAccountRead // status int statusEnum = toInt(row.get("status_enum"), 100); out.put("status", buildStatus(statusEnum)); + out.put("terminateTrue", toBoolean(row.get("terminate_true"))); // subStatus int subStatusEnum = toInt(row.get("sub_status_enum"), 0); @@ -502,6 +513,13 @@ public class CurrentAccountReadPlatformServiceImpl implements CurrentAccountRead s.put("approved", false); s.put("active", false); s.put("rejected", false); s.put("withdrawnByApplicant", false); s.put("closed", true); } + case 900 -> { + s.put("code", "savingsAccountStatusType.terminated"); + s.put("value", "Terminated"); + s.put("submittedAndPendingApproval", false); + s.put("approved", false); s.put("active", false); + s.put("rejected", false); s.put("withdrawnByApplicant", false); s.put("closed", false); + } default -> { s.put("code", "savingsAccountStatusType.invalid"); s.put("value", "Invalid"); @@ -659,6 +677,14 @@ public class CurrentAccountReadPlatformServiceImpl implements CurrentAccountRead try { return new BigDecimal(val.toString().trim()); } catch (Exception e) { return null; } } + private boolean toBoolean(Object val) { + if (val == null) return false; + if (val instanceof Boolean) return (Boolean) val; + if (val instanceof Number) return ((Number) val).intValue() == 1; + String s = val.toString().trim(); + return "true".equalsIgnoreCase(s) || "1".equals(s); + } + private static class FlatRowMapper implements RowMapper> { @Override public Map mapRow(ResultSet rs, int rowNum) throws SQLException { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/CurrentAccountWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/CurrentAccountWritePlatformServiceImpl.java index 17c70f8fd..cf9f24db0 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/CurrentAccountWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/CurrentAccountWritePlatformServiceImpl.java @@ -251,6 +251,9 @@ public class CurrentAccountWritePlatformServiceImpl implements CurrentAccountWri throw e; } + log.info("Current Account created successfully: [id={}, accountNo={}, clientId={}, officeId={}, submittedOnDate={}]", + account.getId(), account.getAccountNo(), clientId, office.getId(), submittedOnDate); + return new CommandProcessingResultBuilder() .withEntityId(account.getId()) .withClientId(clientId) @@ -507,6 +510,30 @@ public class CurrentAccountWritePlatformServiceImpl implements CurrentAccountWri return new CommandProcessingResultBuilder().withEntityId(accountId).build(); } + @Override + @Transactional + public CommandProcessingResult terminateAccount(final Long accountId, final JsonCommand command) { + context.authenticatedUser(); + final CurrentAccount account = findAccount(accountId); + account.terminate(); + currentAccountRepository.saveAndFlush(account); + + final java.util.Map changes = new java.util.LinkedHashMap<>(); + changes.put("terminateTrue", true); + changes.put("status", 900); + + final Long officeId = account.getOffice() != null ? account.getOffice().getId() : null; + final Long clientId = account.getClient() != null ? account.getClient().getId() : null; + + return new CommandProcessingResultBuilder() + .withEntityId(accountId) + .withOfficeId(officeId) + .withClientId(clientId) + .withSavingsId(accountId) + .with(changes) + .build(); + } + // ─── helpers ────────────────────────────────────────────────────────────── private CurrentAccount findAccount(Long accountId) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java index 50ca2d653..471e82962 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java @@ -172,10 +172,17 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead if (searchParameters != null) { if (StringUtils.isNotBlank(searchParameters.getStatus())) { - final Integer statusEnum = resolveStatusEnum(searchParameters.getStatus()); - if (statusEnum != null) { - sqlBuilder.append(" and sa.status_enum = ?"); - objectArray[arrayPos++] = statusEnum; + if ("terminated".equalsIgnoreCase(searchParameters.getStatus())) { + sqlBuilder.append(" and sa.terminate_true = true"); + } else { + final Integer statusEnum = resolveStatusEnum(searchParameters.getStatus()); + if (statusEnum != null) { + sqlBuilder.append(" and sa.status_enum = ?"); + objectArray[arrayPos++] = statusEnum; + if (statusEnum == 100) { + sqlBuilder.append(" and (sa.terminate_true = false or sa.terminate_true is null)"); + } + } } } @@ -248,6 +255,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead case "withdrawn" -> 400; case "rejected" -> 500; case "closed" -> 600; + case "terminated" -> 900; default -> { try { yield Integer.parseInt(status); @@ -881,7 +889,8 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead sqlBuilder.append("safc.inter_bank_total_cap_facility as interBankTotalCapFacility, "); sqlBuilder.append("safc.withdrawal_facility as withdrawalFacility, "); sqlBuilder.append("safc.deposit_facility_kyc as depositFacilityKyc, "); - sqlBuilder.append("safc.virtual_debit_card as virtualDebitCard "); + sqlBuilder.append("safc.virtual_debit_card as virtualDebitCard, "); + sqlBuilder.append("sa.terminate_true as terminateTrue "); 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 "); @@ -1122,6 +1131,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead accountData.setAutoDebitFacility(rs.getObject("autoDebitFacility") != null ? rs.getBoolean("autoDebitFacility") : null); accountData.setIntroducerRequired(rs.getObject("introducerRequired") != null ? rs.getBoolean("introducerRequired") : null); accountData.setShareLinkingEnabled(rs.getObject("shareLinkingEnabled") != null ? rs.getBoolean("shareLinkingEnabled") : null); + accountData.setTerminateTrue(rs.getObject("terminateTrue") != null ? rs.getBoolean("terminateTrue") : null); // Nominee as parsed map final String nomineeDataStr = rs.getString("nomineeData"); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java index 74bed6cfd..6ec884712 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java @@ -1770,6 +1770,19 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi .withClientId(account.clientId()).withGroupId(account.groupId()).withSavingsId(savingsId).with(changes).build(); } + @Override + @Transactional + public CommandProcessingResult terminate(final Long savingsId, final JsonCommand command) { + this.context.authenticatedUser(); + final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId, false); + final Map changes = account.terminate(); + if (!changes.isEmpty()) { + this.savingAccountRepositoryWrapper.save(account); + } + return new CommandProcessingResultBuilder().withEntityId(savingsId).withOfficeId(account.officeId()) + .withClientId(account.clientId()).withGroupId(account.groupId()).withSavingsId(savingsId).with(changes).build(); + } + @Override public CommandProcessingResult unblockAccount(final Long savingsId) { this.context.authenticatedUser(); diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml index 14d4ccb1f..9d1ccba1a 100644 --- a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml +++ b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml @@ -367,4 +367,5 @@ + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0340_add_terminate_true_to_savings_and_current_account.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0340_add_terminate_true_to_savings_and_current_account.xml new file mode 100644 index 000000000..677356c90 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0340_add_terminate_true_to_savings_and_current_account.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/fineract-savings/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java b/fineract-savings/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java index e3dc2e17e..a3d54240d 100644 --- a/fineract-savings/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java +++ b/fineract-savings/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsAccount.java @@ -4216,6 +4216,21 @@ public class SavingsAccount extends AbstractAuditableWithUTCDateTimeCustom @Column(name = "senior_citizen_interest_rate", scale = 6, precision = 19, nullable = true) private BigDecimal seniorCitizenInterestRate; + @Column(name = "terminate_true", nullable = false, columnDefinition = "boolean default false") + private boolean terminateTrue = false; + + public boolean isTerminateTrue() { return terminateTrue; } + public void setTerminateTrue(boolean terminateTrue) { this.terminateTrue = terminateTrue; } + + public Map terminate() { + final Map actualChanges = new LinkedHashMap<>(); + this.terminateTrue = true; + this.status = SavingsAccountStatusType.TERMINATED.getValue(); + actualChanges.put("terminateTrue", true); + actualChanges.put("status", SavingsAccountStatusType.TERMINATED.getValue()); + return actualChanges; + } + @jakarta.persistence.OneToOne(cascade = jakarta.persistence.CascadeType.ALL, mappedBy = "savingsAccount", orphanRemoval = true, fetch = FetchType.LAZY) private SavingsAccountFacilityConfig facilityConfig; diff --git a/fineract-savings/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformService.java b/fineract-savings/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformService.java index 8b2979591..e6daf5577 100644 --- a/fineract-savings/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformService.java +++ b/fineract-savings/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformService.java @@ -118,4 +118,6 @@ public interface SavingsAccountWritePlatformService { CommandProcessingResult gsimDeposit(Long gsimId, JsonCommand command); CommandProcessingResult bulkGSIMClose(Long gsimId, JsonCommand command); + + CommandProcessingResult terminate(Long savingsId, JsonCommand command); }