pending account terminate feature develop

This commit is contained in:
keshav898966
2026-07-01 17:25:04 +05:30
parent 1bd41cff43
commit 99c153830c
34 changed files with 641 additions and 76 deletions
@@ -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<Integer, CommandProcessingResultType> 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;
}
}
@@ -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";
@@ -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);
@@ -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;
@@ -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());
}
}
@@ -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;
}
@@ -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;
}
}
@@ -40,4 +40,6 @@ public interface CurrentAccountWritePlatformService {
CommandProcessingResult modifyApplication(Long accountId, JsonCommand command);
CommandProcessingResult deleteApplication(Long accountId);
CommandProcessingResult terminateAccount(Long accountId, JsonCommand command);
}
@@ -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<CommandProcessingResult> 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);
}
}
@@ -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);
}
}
@@ -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);
}
@@ -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.");
};
}
}
@@ -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);
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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());
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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<Map<String, Object>> {
@Override
public Map<String, Object> mapRow(ResultSet rs, int rowNum) throws SQLException {
@@ -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<String, Object> 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) {
@@ -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");
@@ -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<String, Object> 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();
@@ -367,4 +367,5 @@
<include file="parts/0337_create_election_module.xml" relativeToChangelogFile="true"/>
<include file="parts/0338_add_soft_delete_to_tellers.xml" relativeToChangelogFile="true"/>
<include file="parts/0339_add_share_linking_enabled_to_current_account.xml" relativeToChangelogFile="true"/>
<include file="parts/0340_add_terminate_true_to_savings_and_current_account.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<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">
<changeSet id="0340_1" author="fineract">
<addColumn tableName="m_savings_account">
<column name="terminate_true" type="boolean" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
</addColumn>
</changeSet>
<changeSet id="0340_2" author="fineract">
<addColumn tableName="m_current_account">
<column name="terminate_true" type="boolean" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
</addColumn>
</changeSet>
</databaseChangeLog>
@@ -4216,6 +4216,21 @@ public class SavingsAccount extends AbstractAuditableWithUTCDateTimeCustom<Long>
@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<String, Object> terminate() {
final Map<String, Object> 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;
@@ -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);
}