current account save api update

This commit is contained in:
Nitesh Yadav
2026-04-29 15:18:45 +05:30
parent cbdcee690d
commit a7965f8792
21 changed files with 25453 additions and 9573 deletions
File diff suppressed because it is too large Load Diff
@@ -36,10 +36,12 @@ import org.apache.fineract.portfolio.client.domain.ClientRepository;
import org.apache.fineract.portfolio.group.domain.Group;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
import org.apache.fineract.portfolio.currentaccount.domain.CurrentAccount;
import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
import org.apache.fineract.portfolio.savings.domain.SavingsAccountRepository;
import org.apache.fineract.portfolio.savings.domain.SavingsProductRepository;
import org.apache.fineract.portfolio.shareaccounts.domain.ShareAccount;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
/**
@@ -69,6 +71,7 @@ public class AccountNumberGenerator {
private final SavingsAccountRepository savingsAccountRepository;
private final GLAccountRepository glAccountRepository;
private final SavingsProductRepository savingsProductRepository;
private final JdbcTemplate jdbcTemplate;
public String generate(Client client, AccountNumberFormat accountNumberFormat) {
Map<String, String> propertyMap = new HashMap<>();
@@ -119,6 +122,35 @@ public class AccountNumberGenerator {
return CBS_FIXED_PREFIX + glCode + officeId + accountId;
}
/**
* Generate CBS account number for a current account.
* GL code is fetched directly from m_current_product using the current account's product_id.
* Format: 00 + GL_CODE(6) + OFFICE_ID(2) + ACCOUNT_ID(5) = 15 digits
*/
public String generateForCurrentAccount(CurrentAccount currentAccount) {
Long productId = currentAccount.getProductId();
Long glAccountId = jdbcTemplate.query(
"SELECT gl_account_id FROM m_current_product WHERE id = ?",
rs -> rs.next() ? rs.getLong("gl_account_id") : null,
productId);
String glCode = "000000";
if (glAccountId != null && glAccountId > 0) {
glCode = glAccountRepository.findById(glAccountId)
.map(gl -> StringUtils.leftPad(gl.getGlCode(), 6, '0'))
.orElse("000000");
}
glCode = glCode.length() > 6 ? glCode.substring(glCode.length() - 6) : StringUtils.leftPad(glCode, 6, '0');
String officeId = StringUtils.leftPad(currentAccount.getOffice().getId().toString(), 2, '0');
if (officeId.length() > 2) officeId = officeId.substring(officeId.length() - 2);
String accountId = StringUtils.leftPad(currentAccount.getId().toString(), 5, '0');
if (accountId.length() > 5) accountId = accountId.substring(accountId.length() - 5);
return CBS_FIXED_PREFIX + glCode + officeId + accountId;
}
public String previewAccountNumber(Long productId, Long officeId) {
String glCode = "000000";
if (productId != null) {
@@ -40,9 +40,6 @@ import java.util.Collection;
import java.util.Set;
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.api.ApiParameterHelper;
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
@@ -59,6 +56,7 @@ import org.apache.fineract.portfolio.savings.SavingsApiConstants;
import org.apache.fineract.portfolio.savings.data.SavingsAccountChargeData;
import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionData;
import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountWritePlatformService;
import org.apache.fineract.portfolio.savings.service.CurrentAccountTemplateReadPlatformService;
import org.apache.fineract.portfolio.savings.service.SavingsAccountChargeReadPlatformService;
import org.apache.fineract.portfolio.savings.service.SavingsAccountReadPlatformService;
@@ -75,10 +73,10 @@ public class CurrentAccountsApiResource {
private final CurrentAccountTemplateReadPlatformService currentAccountTemplateReadPlatformService;
private final PlatformSecurityContext context;
private final DefaultToApiJsonSerializer<SavingsAccountData> toApiJsonSerializer;
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
private final ApiRequestParameterHelper apiRequestParameterHelper;
private final SavingsAccountChargeReadPlatformService savingsAccountChargeReadPlatformService;
private final SqlValidator sqlValidator;
private final CurrentAccountWritePlatformService currentAccountWritePlatformService;
@GET
@Path("template")
@@ -128,8 +126,9 @@ 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 CommandWrapper commandRequest = new CommandWrapperBuilder().createCurrentAccount().withJson(apiRequestBodyAsJson).build();
final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
final org.apache.fineract.infrastructure.core.api.JsonCommand command =
org.apache.fineract.infrastructure.core.api.JsonCommand.from(apiRequestBodyAsJson);
final CommandProcessingResult result = currentAccountWritePlatformService.submitApplication(command);
return toApiJsonSerializer.serialize(result);
}
@@ -164,16 +163,9 @@ public class CurrentAccountsApiResource {
@Parameter(hidden = true) final String apiRequestBodyAsJson,
@QueryParam("command") final String commandParam) {
if (is(commandParam, "updateWithHoldTax")) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().withJson(apiRequestBodyAsJson)
.updateWithHoldTaxCurrentAccount(accountId).build();
final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
return toApiJsonSerializer.serialize(result);
}
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateCurrentAccount(accountId).withJson(apiRequestBodyAsJson)
.build();
final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
final org.apache.fineract.infrastructure.core.api.JsonCommand command =
org.apache.fineract.infrastructure.core.api.JsonCommand.from(apiRequestBodyAsJson);
final CommandProcessingResult result = currentAccountWritePlatformService.modifyApplication(accountId, command);
return toApiJsonSerializer.serialize(result);
}
@@ -192,53 +184,27 @@ public class CurrentAccountsApiResource {
jsonApiRequest = "{}";
}
final CommandWrapperBuilder builder = new CommandWrapperBuilder().withJson(jsonApiRequest);
final org.apache.fineract.infrastructure.core.api.JsonCommand command =
org.apache.fineract.infrastructure.core.api.JsonCommand.from(jsonApiRequest);
CommandProcessingResult result = null;
if (is(commandParam, "reject")) {
result = commandsSourceWritePlatformService.logCommandSource(builder.rejectCurrentAccountApplication(accountId).build());
result = currentAccountWritePlatformService.rejectApplication(accountId, command);
} else if (is(commandParam, "withdrawnByApplicant")) {
result = commandsSourceWritePlatformService.logCommandSource(builder.withdrawCurrentAccountApplication(accountId).build());
result = currentAccountWritePlatformService.withdrawApplication(accountId, command);
} else if (is(commandParam, "approve")) {
result = commandsSourceWritePlatformService.logCommandSource(builder.approveCurrentAccountApplication(accountId).build());
result = currentAccountWritePlatformService.approveApplication(accountId, command);
} else if (is(commandParam, "undoapproval")) {
result = commandsSourceWritePlatformService.logCommandSource(builder.undoCurrentAccountApplication(accountId).build());
result = currentAccountWritePlatformService.undoApproval(accountId, command);
} else if (is(commandParam, "activate")) {
result = commandsSourceWritePlatformService.logCommandSource(builder.currentAccountActivation(accountId).build());
} else if (is(commandParam, "calculateInterest")) {
result = commandsSourceWritePlatformService
.logCommandSource(builder.withNoJsonBody().currentAccountInterestCalculation(accountId).build());
} else if (is(commandParam, "postInterest")) {
result = commandsSourceWritePlatformService.logCommandSource(builder.currentAccountInterestPosting(accountId).build());
} else if (is(commandParam, "applyAnnualFees")) {
result = commandsSourceWritePlatformService.logCommandSource(builder.currentAccountApplyAnnualFees(accountId).build());
result = currentAccountWritePlatformService.activate(accountId, command);
} else if (is(commandParam, "close")) {
result = commandsSourceWritePlatformService.logCommandSource(builder.closeCurrentAccountApplication(accountId).build());
} else if (is(commandParam, "assignSavingsOfficer")) {
result = commandsSourceWritePlatformService.logCommandSource(builder.assignCurrentAccountOfficer(accountId).build());
} else if (is(commandParam, "unassignSavingsOfficer")) {
result = commandsSourceWritePlatformService.logCommandSource(builder.unassignCurrentAccountOfficer(accountId).build());
} else if (is(commandParam, SavingsApiConstants.COMMAND_BLOCK_DEBIT)) {
result = commandsSourceWritePlatformService.logCommandSource(builder.blockDebitsFromCurrentAccount(accountId).build());
} else if (is(commandParam, SavingsApiConstants.COMMAND_UNBLOCK_DEBIT)) {
result = commandsSourceWritePlatformService.logCommandSource(builder.unblockDebitsFromCurrentAccount(accountId).build());
} else if (is(commandParam, SavingsApiConstants.COMMAND_BLOCK_CREDIT)) {
result = commandsSourceWritePlatformService.logCommandSource(builder.blockCreditsToCurrentAccount(accountId).build());
} else if (is(commandParam, SavingsApiConstants.COMMAND_UNBLOCK_CREDIT)) {
result = commandsSourceWritePlatformService.logCommandSource(builder.unblockCreditsToCurrentAccount(accountId).build());
} else if (is(commandParam, SavingsApiConstants.COMMAND_BLOCK_ACCOUNT)) {
result = commandsSourceWritePlatformService.logCommandSource(builder.blockCurrentAccount(accountId).build());
} else if (is(commandParam, SavingsApiConstants.COMMAND_UNBLOCK_ACCOUNT)) {
result = commandsSourceWritePlatformService.logCommandSource(builder.unblockCurrentAccount(accountId).build());
result = currentAccountWritePlatformService.closeAccount(accountId, command);
}
if (result == null) {
throw new UnrecognizedQueryParamException("command", commandParam,
new Object[] { "reject", "withdrawnByApplicant", "approve", "undoapproval", "activate", "calculateInterest",
"postInterest", "close", "assignSavingsOfficer", "unassignSavingsOfficer",
SavingsApiConstants.COMMAND_BLOCK_DEBIT, SavingsApiConstants.COMMAND_UNBLOCK_DEBIT,
SavingsApiConstants.COMMAND_BLOCK_CREDIT, SavingsApiConstants.COMMAND_UNBLOCK_CREDIT,
SavingsApiConstants.COMMAND_BLOCK_ACCOUNT, SavingsApiConstants.COMMAND_UNBLOCK_ACCOUNT });
new Object[] { "reject", "withdrawnByApplicant", "approve", "undoapproval", "activate", "close" });
}
return toApiJsonSerializer.serialize(result);
@@ -251,8 +217,7 @@ public class CurrentAccountsApiResource {
@Operation(summary = "Delete a current account application")
@ApiResponse(responseCode = "200", description = "OK")
public String delete(@PathParam("accountId") final Long accountId) {
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteCurrentAccount(accountId).build();
final CommandProcessingResult result = commandsSourceWritePlatformService.logCommandSource(commandRequest);
final CommandProcessingResult result = currentAccountWritePlatformService.deleteApplication(accountId);
return toApiJsonSerializer.serialize(result);
}
@@ -0,0 +1,370 @@
/**
* 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.service;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.time.LocalDate;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.organisation.office.domain.Office;
import org.apache.fineract.organisation.office.domain.OfficeRepositoryWrapper;
import org.apache.fineract.organisation.staff.domain.Staff;
import org.apache.fineract.portfolio.client.domain.Client;
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
import org.apache.fineract.portfolio.currentaccount.domain.CurrentAccount;
import org.apache.fineract.portfolio.currentaccount.domain.CurrentAccountFacilityConfig;
import org.apache.fineract.portfolio.currentaccount.domain.CurrentAccountJointHolder;
import org.apache.fineract.portfolio.currentaccount.domain.CurrentAccountPartner;
import org.apache.fineract.portfolio.currentaccount.domain.CurrentAccountRepository;
import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountWritePlatformService;
import org.apache.fineract.portfolio.currentaccount.service.CurrentAccountNumberGenerator;
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProduct;
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProductRepository;
import org.apache.fineract.portfolio.savings.exception.SavingsAccountNotFoundException;
import org.apache.fineract.portfolio.savings.exception.SavingsProductNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Slf4j
@Service
@RequiredArgsConstructor
public class CurrentAccountWritePlatformServiceImpl implements CurrentAccountWritePlatformService {
private final PlatformSecurityContext context;
private final CurrentAccountRepository currentAccountRepository;
private final CurrentProductRepository currentProductRepository;
private final ClientRepositoryWrapper clientRepository;
private final OfficeRepositoryWrapper officeRepository;
private final CurrentAccountNumberGenerator accountNumberGenerator;
@Override
@Transactional
public CommandProcessingResult submitApplication(final JsonCommand command) {
context.authenticatedUser();
final Long clientId = command.longValueOfParameterNamed("clientId");
final Long productId = command.longValueOfParameterNamed("productId");
final Long officeId = command.parameterExists("officeId") ? command.longValueOfParameterNamed("officeId") : null;
final Long staffId = command.parameterExists("fieldOfficerId")
&& !isBlankString(command.parsedJson().getAsJsonObject(), "fieldOfficerId")
? command.longValueOfParameterNamed("fieldOfficerId") : null;
final Client client = clientRepository.findOneWithNotFoundDetection(clientId);
final CurrentProduct product = currentProductRepository.findById(productId)
.orElseThrow(() -> new SavingsProductNotFoundException(productId));
final Office office = officeId != null
? officeRepository.findOneWithNotFoundDetection(officeId)
: client.getOffice();
Staff staff = null;
// staff loaded lazily if needed — keep null for now if not in scope
LocalDate submittedOnDate = command.localDateValueOfParameterNamed("submittedOnDate");
if (submittedOnDate == null) submittedOnDate = LocalDate.now();
// accountType may arrive as integer or string — store null if absent/unparseable
Integer accountTypeEnum = null;
if (command.parameterExists("accountType")) {
try {
accountTypeEnum = command.integerValueOfParameterNamed("accountType");
} catch (Exception ignored) {
// string value like "Standard Account" — ignore, store null
}
}
// Override from request if provided, else use product defaults
boolean msme = command.parameterExists("msme")
? command.booleanPrimitiveValueOfParameterNamed("msme") : product.isMsme();
boolean autoDebitFacility = command.parameterExists("autoDebitFacility")
? command.booleanPrimitiveValueOfParameterNamed("autoDebitFacility") : product.isAutoDebitFacility();
boolean balanceSwapOption = command.parameterExists("balanceSwapOption")
? command.booleanPrimitiveValueOfParameterNamed("balanceSwapOption") : product.isBalanceSwapOption();
final CurrentAccount account = CurrentAccount.createNew(
client, productId, office, staff, "TEMP", submittedOnDate, accountTypeEnum,
product.currency().getCode(), product.currency().getDigitsAfterDecimal(),
product.currency().getInMultiplesOf(),
product.nominalAnnualInterestRate(),
product.getInterestCompoundingPeriodType(), product.getInterestPostingPeriodType(),
product.getInterestCalculationType(), product.getInterestCalculationDaysInYearType(),
product.isAllowOverdraft(), product.getOverdraftLimit(),
msme, autoDebitFacility, balanceSwapOption,
product.getCustomerSegment(), product.isAutoPost(),
product.getInterestCalculateSelector(), product.getAveragePeriod(),
product.getAvgBalanceCalcPeriod());
if (command.parameterExists("establishmentDate")) {
account.setEstablishmentDate(command.localDateValueOfParameterNamed("establishmentDate"));
}
if (command.parameterExists("startOperationDate")) {
account.setStartOperationDate(command.localDateValueOfParameterNamed("startOperationDate"));
}
if (command.parameterExists("isNonIndividualClient")) {
account.setNonIndividualClient(command.booleanPrimitiveValueOfParameterNamed("isNonIndividualClient"));
}
if (command.parameterExists("signatoryRights")) {
account.setSignatoryRights(command.stringValueOfParameterNamed("signatoryRights"));
}
if (command.parameterExists("modeOfOperation")) {
account.setModeOfOperation(command.stringValueOfParameterNamed("modeOfOperation"));
}
if (command.parameterExists("introducerName")) {
account.setIntroducerName(command.stringValueOfParameterNamed("introducerName"));
}
if (command.parameterExists("introducerClientId")) {
account.setIntroducerClientId(command.longValueOfParameterNamed("introducerClientId"));
} else if (command.parameterExists("introducerId")) {
account.setIntroducerClientId(command.longValueOfParameterNamed("introducerId"));
}
if (command.parameterExists("externalId")) {
account.setExternalId(command.stringValueOfParameterNamed("externalId"));
}
if (command.parameterExists("accountStatus")) {
account.setAccountStatus(command.stringValueOfParameterNamed("accountStatus"));
}
if (command.parameterExists("customerSegment")) {
account.setCustomerSegment(command.stringValueOfParameterNamed("customerSegment"));
}
// Save first to get ID
currentAccountRepository.saveAndFlush(account);
// Generate account number: 00 + GL_CODE(6) + OFFICE_ID(2) + ACCOUNT_ID(5)
final String accountNo = accountNumberGenerator.generate(account);
account.updateAccountNo(accountNo);
// Facility config — UI sends "accountFacilityConfig", internal uses "facilityConfig"
if (command.parameterExists("accountFacilityConfig") || command.parameterExists("facilityConfig")) {
final CurrentAccountFacilityConfig facilityConfig = assembleFacilityConfig(account, command);
account.setFacilityConfig(facilityConfig);
}
// Joint holders
if (command.parameterExists("jointHolders")) {
assembleJointHolders(account, command);
}
// Partners (non-individual)
if (command.parameterExists("partners")) {
assemblePartners(account, command);
}
currentAccountRepository.saveAndFlush(account);
return new CommandProcessingResultBuilder()
.withEntityId(account.getId())
.withClientId(clientId)
.withOfficeId(office.getId())
.build();
}
@Override
@Transactional
public CommandProcessingResult approveApplication(final Long accountId, final JsonCommand command) {
context.authenticatedUser();
final CurrentAccount account = findAccount(accountId);
LocalDate approvedOnDate = command.localDateValueOfParameterNamed("approvedOnDate");
if (approvedOnDate == null) approvedOnDate = LocalDate.now();
account.approve(approvedOnDate);
currentAccountRepository.saveAndFlush(account);
return new CommandProcessingResultBuilder().withEntityId(accountId).build();
}
@Override
@Transactional
public CommandProcessingResult undoApproval(final Long accountId, final JsonCommand command) {
context.authenticatedUser();
final CurrentAccount account = findAccount(accountId);
account.setStatusEnum(100);
account.setApprovedOnDate(null);
currentAccountRepository.saveAndFlush(account);
return new CommandProcessingResultBuilder().withEntityId(accountId).build();
}
@Override
@Transactional
public CommandProcessingResult activate(final Long accountId, final JsonCommand command) {
context.authenticatedUser();
final CurrentAccount account = findAccount(accountId);
LocalDate activatedOnDate = command.localDateValueOfParameterNamed("activatedOnDate");
if (activatedOnDate == null) activatedOnDate = LocalDate.now();
account.activate(activatedOnDate);
currentAccountRepository.saveAndFlush(account);
return new CommandProcessingResultBuilder().withEntityId(accountId).build();
}
@Override
@Transactional
public CommandProcessingResult rejectApplication(final Long accountId, final JsonCommand command) {
context.authenticatedUser();
final CurrentAccount account = findAccount(accountId);
LocalDate rejectedOnDate = command.localDateValueOfParameterNamed("rejectedOnDate");
if (rejectedOnDate == null) rejectedOnDate = LocalDate.now();
account.reject(rejectedOnDate);
currentAccountRepository.saveAndFlush(account);
return new CommandProcessingResultBuilder().withEntityId(accountId).build();
}
@Override
@Transactional
public CommandProcessingResult withdrawApplication(final Long accountId, final JsonCommand command) {
context.authenticatedUser();
final CurrentAccount account = findAccount(accountId);
LocalDate withdrawnOnDate = command.localDateValueOfParameterNamed("withdrawnOnDate");
if (withdrawnOnDate == null) withdrawnOnDate = LocalDate.now();
account.withdraw(withdrawnOnDate);
currentAccountRepository.saveAndFlush(account);
return new CommandProcessingResultBuilder().withEntityId(accountId).build();
}
@Override
@Transactional
public CommandProcessingResult closeAccount(final Long accountId, final JsonCommand command) {
context.authenticatedUser();
final CurrentAccount account = findAccount(accountId);
LocalDate closedOnDate = command.localDateValueOfParameterNamed("closedOnDate");
if (closedOnDate == null) closedOnDate = LocalDate.now();
account.close(closedOnDate);
currentAccountRepository.saveAndFlush(account);
return new CommandProcessingResultBuilder().withEntityId(accountId).build();
}
@Override
@Transactional
public CommandProcessingResult modifyApplication(final Long accountId, final JsonCommand command) {
context.authenticatedUser();
final CurrentAccount account = findAccount(accountId);
if (command.parameterExists("msme")) {
account.setMsme(command.booleanPrimitiveValueOfParameterNamed("msme"));
}
if (command.parameterExists("signatoryRights")) {
account.setSignatoryRights(command.stringValueOfParameterNamed("signatoryRights"));
}
if (command.parameterExists("modeOfOperation")) {
account.setModeOfOperation(command.stringValueOfParameterNamed("modeOfOperation"));
}
currentAccountRepository.saveAndFlush(account);
return new CommandProcessingResultBuilder().withEntityId(accountId).build();
}
@Override
@Transactional
public CommandProcessingResult deleteApplication(final Long accountId) {
context.authenticatedUser();
final CurrentAccount account = findAccount(accountId);
currentAccountRepository.delete(account);
return new CommandProcessingResultBuilder().withEntityId(accountId).build();
}
// ─── helpers ──────────────────────────────────────────────────────────────
private CurrentAccount findAccount(Long accountId) {
return currentAccountRepository.findById(accountId)
.orElseThrow(() -> new SavingsAccountNotFoundException(accountId));
}
private CurrentAccountFacilityConfig assembleFacilityConfig(CurrentAccount account, JsonCommand command) {
final CurrentAccountFacilityConfig cfg = CurrentAccountFacilityConfig.createFor(account);
final JsonObject root = command.parsedJson().getAsJsonObject();
JsonObject fcJson = root.getAsJsonObject("accountFacilityConfig");
if (fcJson == null) fcJson = root.getAsJsonObject("facilityConfig");
if (fcJson == null) return cfg;
cfg.setAtmFacility(getBool(fcJson, "atmFacility"));
cfg.setAtmWithdrawalFacility(getBool(fcJson, "atmWithdrawalFacility"));
cfg.setUpiFacility(getBool(fcJson, "upiFacility"));
cfg.setPosTransactionsFacility(getBool(fcJson, "posTransactionsFacility"));
cfg.setChequeBook(getBool(fcJson, "chequeBook"));
cfg.setImpsFacility(getBool(fcJson, "impsFacility"));
cfg.setSmsAlerts(getBool(fcJson, "smsAlerts"));
cfg.setBbpsFacility(getBool(fcJson, "bbpsFacility"));
cfg.setInsuranceCover(getBool(fcJson, "insuranceCover"));
cfg.setBepgFacility(getBool(fcJson, "bepgFacility"));
cfg.setNeftFacility(getBool(fcJson, "neftFacility"));
cfg.setRtgsFacility(getBool(fcJson, "rtgsFacility"));
cfg.setInterBankTotalCapFacility(getBool(fcJson, "interBankTotalCapFacility"));
cfg.setWithdrawalFacility(getBool(fcJson, "withdrawalFacility"));
cfg.setDepositFacilityKyc(getBool(fcJson, "depositFacilityKyc"));
cfg.setVirtualDebitCard(getBool(fcJson, "virtualDebitCard"));
cfg.setInternetBanking(getBool(fcJson, "internetBanking"));
cfg.setMobileBanking(getBool(fcJson, "mobileBanking"));
return cfg;
}
private void assembleJointHolders(CurrentAccount account, JsonCommand command) {
final JsonArray arr = command.arrayOfParameterNamed("jointHolders");
if (arr == null) return;
for (JsonElement el : arr) {
final JsonObject jo = el.getAsJsonObject();
final CurrentAccountJointHolder holder = new CurrentAccountJointHolder();
holder.setCurrentAccount(account);
if (jo.has("clientId") && !jo.get("clientId").isJsonNull()) {
holder.setClientId(jo.get("clientId").getAsLong());
}
if (jo.has("cifNumber") && !jo.get("cifNumber").isJsonNull()) {
holder.setCifNumber(jo.get("cifNumber").getAsString());
}
if (jo.has("displayName") && !jo.get("displayName").isJsonNull()) {
holder.setDisplayName(jo.get("displayName").getAsString());
}
if (jo.has("signingAuthority") && !jo.get("signingAuthority").isJsonNull()) {
holder.setSigningAuthority(jo.get("signingAuthority").getAsString());
}
if (jo.has("role") && !jo.get("role").isJsonNull()) {
holder.setRole(jo.get("role").getAsString());
}
account.getJointHolders().add(holder);
}
}
private void assemblePartners(CurrentAccount account, JsonCommand command) {
final JsonArray arr = command.arrayOfParameterNamed("partners");
if (arr == null) return;
for (JsonElement el : arr) {
final JsonObject jo = el.getAsJsonObject();
final CurrentAccountPartner partner = new CurrentAccountPartner();
partner.setCurrentAccount(account);
if (jo.has("clientId") && !jo.get("clientId").isJsonNull()) {
partner.setClientId(jo.get("clientId").getAsLong());
}
if (jo.has("clientCif") && !jo.get("clientCif").isJsonNull()) {
partner.setClientCif(jo.get("clientCif").getAsString());
}
if (jo.has("clientName") && !jo.get("clientName").isJsonNull()) {
partner.setClientName(jo.get("clientName").getAsString());
}
account.getPartners().add(partner);
}
}
private boolean getBool(JsonObject obj, String key) {
return obj.has(key) && !obj.get(key).isJsonNull() && obj.get(key).getAsBoolean();
}
private boolean isBlankString(JsonObject obj, String key) {
if (!obj.has(key) || obj.get(key).isJsonNull()) return true;
return obj.get(key).getAsString().isBlank();
}
}
@@ -277,4 +277,5 @@
<include file="parts/0271_create_rd_base_interest_rate_tables.xml" relativeToChangelogFile="true"/>
<include file="parts/0272_seed_rd_base_interest_rate_data.xml" relativeToChangelogFile="true"/>
<include file="parts/0273_add_gl_account_id_to_current_product.xml" relativeToChangelogFile="true"/>
<include file="parts/0276_create_current_account_tables.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>
@@ -0,0 +1,393 @@
<?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.3.xsd">
<!-- =========================================================
m_current_account — main current account table
(fully separate from m_savings_account)
========================================================= -->
<changeSet id="0276_create_current_account_tables" author="system">
<createTable tableName="m_current_account">
<column name="id" type="bigint" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="account_no" type="varchar(20)">
<constraints nullable="false" unique="true" uniqueConstraintName="ca_unq_account_no"/>
</column>
<column name="external_id" type="varchar(100)">
<constraints nullable="true" unique="true" uniqueConstraintName="ca_unq_external_id"/>
</column>
<!-- Ownership -->
<column name="client_id" type="bigint">
<constraints nullable="true" foreignKeyName="fk_ca_client" referencedTableName="m_client" referencedColumnNames="id"/>
</column>
<column name="group_id" type="bigint">
<constraints nullable="true" foreignKeyName="fk_ca_group" referencedTableName="m_group" referencedColumnNames="id"/>
</column>
<column name="product_id" type="bigint">
<constraints nullable="false" foreignKeyName="fk_ca_product" referencedTableName="m_current_product" referencedColumnNames="id"/>
</column>
<column name="office_id" type="bigint">
<constraints nullable="false" foreignKeyName="fk_ca_office" referencedTableName="m_office" referencedColumnNames="id"/>
</column>
<column name="staff_id" type="bigint">
<constraints nullable="true" foreignKeyName="fk_ca_staff" referencedTableName="m_staff" referencedColumnNames="id"/>
</column>
<!-- Status -->
<column name="status_enum" type="smallint" defaultValue="100">
<constraints nullable="false"/>
</column>
<!-- 100=Submitted, 200=Approved, 300=Active, 400=Withdrawn, 500=Rejected, 600=Closed -->
<column name="sub_status_enum" type="smallint" defaultValue="0">
<constraints nullable="false"/>
</column>
<!-- 0=None, 100=Inactive, 200=Dormant, 300=Escheat, 400=Block, 500=BlockDebit, 600=BlockCredit -->
<column name="account_type_enum" type="smallint" defaultValue="1">
<constraints nullable="false"/>
</column>
<!-- 1=Individual, 2=Group, 3=JLG -->
<!-- Lifecycle dates -->
<column name="submittedon_date" type="date"><constraints nullable="true"/></column>
<column name="submittedon_userid" type="bigint">
<constraints nullable="true" foreignKeyName="fk_ca_submit_user" referencedTableName="m_appuser" referencedColumnNames="id"/>
</column>
<column name="approvedon_date" type="date"><constraints nullable="true"/></column>
<column name="approvedon_userid" type="bigint">
<constraints nullable="true" foreignKeyName="fk_ca_approve_user" referencedTableName="m_appuser" referencedColumnNames="id"/>
</column>
<column name="activatedon_date" type="date"><constraints nullable="true"/></column>
<column name="activatedon_userid" type="bigint">
<constraints nullable="true" foreignKeyName="fk_ca_activate_user" referencedTableName="m_appuser" referencedColumnNames="id"/>
</column>
<column name="rejectedon_date" type="date"><constraints nullable="true"/></column>
<column name="rejectedon_userid" type="bigint">
<constraints nullable="true" foreignKeyName="fk_ca_reject_user" referencedTableName="m_appuser" referencedColumnNames="id"/>
</column>
<column name="withdrawnon_date" type="date"><constraints nullable="true"/></column>
<column name="withdrawnon_userid" type="bigint">
<constraints nullable="true" foreignKeyName="fk_ca_withdraw_user" referencedTableName="m_appuser" referencedColumnNames="id"/>
</column>
<column name="closedon_date" type="date"><constraints nullable="true"/></column>
<column name="closedon_userid" type="bigint">
<constraints nullable="true" foreignKeyName="fk_ca_close_user" referencedTableName="m_appuser" referencedColumnNames="id"/>
</column>
<!-- Currency (copied from product at account creation) -->
<column name="currency_code" type="varchar(3)"><constraints nullable="false"/></column>
<column name="currency_digits" type="smallint"><constraints nullable="false"/></column>
<column name="currency_multiplesof" type="smallint"><constraints nullable="true"/></column>
<!-- Interest settings (copied from product) -->
<column name="nominal_annual_interest_rate" type="decimal(19,6)" defaultValue="0"><constraints nullable="false"/></column>
<column name="interest_compounding_period_enum" type="smallint"><constraints nullable="false"/></column>
<column name="interest_posting_period_enum" type="smallint"><constraints nullable="false"/></column>
<column name="interest_calculation_type_enum" type="smallint"><constraints nullable="false"/></column>
<column name="interest_calculation_days_in_year_type_enum" type="smallint"><constraints nullable="false"/></column>
<column name="min_balance_for_interest_calculation" type="decimal(19,6)"><constraints nullable="true"/></column>
<column name="start_interest_calculation_date" type="date"><constraints nullable="true"/></column>
<column name="accrued_till_date" type="date"><constraints nullable="true"/></column>
<column name="last_interest_calculation_date" type="date"><constraints nullable="true"/></column>
<column name="last_closed_business_date" type="date"><constraints nullable="true"/></column>
<!-- Tax -->
<column name="withhold_tax" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="tax_group_id" type="bigint">
<constraints nullable="true" foreignKeyName="fk_ca_tax_group" referencedTableName="m_tax_group" referencedColumnNames="id"/>
</column>
<!-- Balance rules (copied from product) -->
<column name="min_required_opening_balance" type="decimal(19,6)"><constraints nullable="true"/></column>
<column name="lockin_period_frequency" type="smallint"><constraints nullable="true"/></column>
<column name="lockin_period_frequency_enum" type="smallint"><constraints nullable="true"/></column>
<column name="lockedin_until_date_derived" type="date"><constraints nullable="true"/></column>
<column name="enforce_min_required_balance" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="min_required_balance" type="decimal(19,6)"><constraints nullable="true"/></column>
<!-- Overdraft (copied from product) -->
<column name="allow_overdraft" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="overdraft_limit" type="decimal(19,6)"><constraints nullable="true"/></column>
<column name="nominal_annual_interest_rate_overdraft" type="decimal(19,6)"><constraints nullable="true"/></column>
<column name="min_overdraft_for_interest_calculation" type="decimal(19,6)"><constraints nullable="true"/></column>
<!-- Lien -->
<column name="is_lien_allowed" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="max_allowed_lien_limit" type="decimal(19,6)"><constraints nullable="true"/></column>
<column name="on_hold_funds_derived" type="decimal(19,6)" defaultValue="0"><constraints nullable="false"/></column>
<!-- Running balance summary -->
<column name="account_balance_derived" type="decimal(19,6)" defaultValue="0"><constraints nullable="false"/></column>
<column name="total_deposits_derived" type="decimal(19,6)" defaultValue="0"><constraints nullable="false"/></column>
<column name="total_withdrawals_derived" type="decimal(19,6)" defaultValue="0"><constraints nullable="false"/></column>
<column name="total_interest_earned_derived" type="decimal(19,6)" defaultValue="0"><constraints nullable="false"/></column>
<column name="total_interest_posted_derived" type="decimal(19,6)" defaultValue="0"><constraints nullable="false"/></column>
<column name="total_overdraft_interest_derived" type="decimal(19,6)" defaultValue="0"><constraints nullable="false"/></column>
<column name="total_withhold_tax_derived" type="decimal(19,6)" defaultValue="0"><constraints nullable="false"/></column>
<column name="total_savings_amount_on_hold" type="decimal(19,6)" defaultValue="0"><constraints nullable="false"/></column>
<column name="withdrawal_fee_for_transfer" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<!-- Block reason -->
<column name="reason_for_block" type="varchar(500)"><constraints nullable="true"/></column>
<!-- Current-account-specific fields -->
<column name="msme" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="auto_debit_facility" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="balance_swap_option" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="establishment_date" type="date"><constraints nullable="true"/></column>
<column name="start_operation_date" type="date"><constraints nullable="true"/></column>
<column name="is_non_individual_client" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="signatory_rights" type="varchar(100)"><constraints nullable="true"/></column>
<!-- CBS account type / segment -->
<column name="cbs_account_type" type="varchar(100)"><constraints nullable="true"/></column>
<column name="customer_segment" type="varchar(100)"><constraints nullable="true"/></column>
<column name="account_status" type="varchar(50)"><constraints nullable="true"/></column>
<column name="mode_of_operation" type="varchar(50)"><constraints nullable="true"/></column>
<column name="special_category" type="varchar(100)"><constraints nullable="true"/></column>
<!-- Introducer -->
<column name="introducer_client_id" type="bigint"><constraints nullable="true"/></column>
<column name="introducer_name" type="varchar(200)"><constraints nullable="true"/></column>
<column name="introducer_cif_number" type="varchar(50)"><constraints nullable="true"/></column>
<!-- Nominee (JSON) -->
<column name="nominee_data" type="text"><constraints nullable="true"/></column>
<!-- Interest calculation settings from product -->
<column name="interest_calculate_selector" type="smallint"><constraints nullable="true"/></column>
<column name="average_period" type="varchar(20)"><constraints nullable="true"/></column>
<column name="auto_post" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="frequency_fix_day" type="smallint"><constraints nullable="true"/></column>
<column name="enable_lockin_period" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="balance_frequency" type="varchar(50)"><constraints nullable="true"/></column>
<column name="avg_balance_calc_period" type="varchar(10)"><constraints nullable="true"/></column>
<!-- Audit -->
<column name="created_by" type="bigint"><constraints nullable="true"/></column>
<column name="created_date" type="datetime"><constraints nullable="true"/></column>
<column name="last_modified_by" type="bigint"><constraints nullable="true"/></column>
<column name="last_modified_date" type="datetime"><constraints nullable="true"/></column>
</createTable>
<!-- =========================================================
m_current_account_transaction
========================================================= -->
<createTable tableName="m_current_account_transaction">
<column name="id" type="bigint" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="current_account_id" type="bigint">
<constraints nullable="false" foreignKeyName="fk_cat_account" referencedTableName="m_current_account" referencedColumnNames="id"/>
</column>
<column name="office_id" type="bigint">
<constraints nullable="false" foreignKeyName="fk_cat_office" referencedTableName="m_office" referencedColumnNames="id"/>
</column>
<column name="payment_detail_id" type="bigint">
<constraints nullable="true" foreignKeyName="fk_cat_payment" referencedTableName="m_payment_detail" referencedColumnNames="id"/>
</column>
<!-- Type: 1=Deposit, 2=Withdrawal, 3=Interest, 4=Charge, 5=ChargeWaiver, 6=Transfer, 7=Reversal -->
<column name="transaction_type_enum" type="smallint"><constraints nullable="false"/></column>
<column name="transaction_date" type="date"><constraints nullable="false"/></column>
<column name="amount" type="decimal(19,6)"><constraints nullable="false"/></column>
<column name="ref_no" type="varchar(100)"><constraints nullable="true"/></column>
<column name="remarks" type="varchar(500)"><constraints nullable="true"/></column>
<!-- State -->
<column name="is_reversed" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="is_reversal" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="original_transaction_id" type="bigint"><constraints nullable="true"/></column>
<column name="is_manual" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<!-- Balance -->
<column name="running_balance_derived" type="decimal(19,6)"><constraints nullable="true"/></column>
<column name="cumulative_balance_derived" type="decimal(19,6)"><constraints nullable="true"/></column>
<column name="balance_end_date_derived" type="date"><constraints nullable="true"/></column>
<column name="balance_number_of_days_derived" type="integer"><constraints nullable="true"/></column>
<column name="overdraft_amount_derived" type="decimal(19,6)"><constraints nullable="true"/></column>
<!-- Lien / Hold -->
<column name="is_lien_transaction" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="release_id_of_hold_amount_transaction" type="bigint"><constraints nullable="true"/></column>
<column name="reason_for_block" type="varchar(200)"><constraints nullable="true"/></column>
<column name="submitted_on_date" type="date"><constraints nullable="true"/></column>
<column name="created_date" type="datetime"><constraints nullable="true"/></column>
<column name="created_by" type="bigint"><constraints nullable="true"/></column>
</createTable>
<!-- =========================================================
m_current_account_charge
========================================================= -->
<createTable tableName="m_current_account_charge">
<column name="id" type="bigint" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="current_account_id" type="bigint">
<constraints nullable="false" foreignKeyName="fk_cac_account" referencedTableName="m_current_account" referencedColumnNames="id"/>
</column>
<column name="charge_id" type="bigint">
<constraints nullable="false" foreignKeyName="fk_cac_charge" referencedTableName="m_charge" referencedColumnNames="id"/>
</column>
<column name="charge_time_enum" type="smallint"><constraints nullable="false"/></column>
<column name="charge_due_date" type="date"><constraints nullable="true"/></column>
<column name="fee_on_month" type="smallint"><constraints nullable="true"/></column>
<column name="fee_on_day" type="smallint"><constraints nullable="true"/></column>
<column name="fee_interval" type="smallint"><constraints nullable="true"/></column>
<column name="charge_calculation_enum" type="smallint"><constraints nullable="false"/></column>
<column name="calculation_percentage" type="decimal(19,6)"><constraints nullable="true"/></column>
<column name="calculation_on_amount" type="decimal(19,6)"><constraints nullable="true"/></column>
<column name="amount" type="decimal(19,6)"><constraints nullable="false"/></column>
<column name="amount_paid_derived" type="decimal(19,6)" defaultValue="0"><constraints nullable="false"/></column>
<column name="amount_waived_derived" type="decimal(19,6)" defaultValue="0"><constraints nullable="false"/></column>
<column name="amount_writtenoff_derived" type="decimal(19,6)" defaultValue="0"><constraints nullable="false"/></column>
<column name="amount_outstanding_derived" type="decimal(19,6)"><constraints nullable="false"/></column>
<column name="is_paid_derived" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="waived" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="is_penalty" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="is_active" type="boolean" defaultValueBoolean="true"><constraints nullable="false"/></column>
<column name="inactivated_on_date" type="date"><constraints nullable="true"/></column>
<column name="free_withdrawal_count" type="integer"><constraints nullable="true"/></column>
<column name="charge_reset_date" type="date"><constraints nullable="true"/></column>
</createTable>
<!-- =========================================================
m_current_account_facility_config
ATM / NEFT / RTGS / Cheque Book etc.
========================================================= -->
<createTable tableName="m_current_account_facility_config">
<column name="id" type="bigint" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="current_account_id" type="bigint">
<constraints nullable="false" unique="true" uniqueConstraintName="ca_fac_unq_account"
foreignKeyName="fk_cafac_account" referencedTableName="m_current_account" referencedColumnNames="id"/>
</column>
<column name="atm_facility" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="atm_withdrawal_facility" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="upi_facility" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="pos_transactions_facility" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="cheque_book" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="imps_facility" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="sms_alerts" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="bbps_facility" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="insurance_cover" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="bepg_facility" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="neft_facility" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="rtgs_facility" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="inter_bank_total_cap_facility" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="withdrawal_facility" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="deposit_facility_kyc" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="virtual_debit_card" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="internet_banking" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
<column name="mobile_banking" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
</createTable>
<!-- =========================================================
m_current_account_joint_holder
Joint account holders
========================================================= -->
<createTable tableName="m_current_account_joint_holder">
<column name="id" type="bigint" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="current_account_id" type="bigint">
<constraints nullable="false" foreignKeyName="fk_cajh_account" referencedTableName="m_current_account" referencedColumnNames="id"/>
</column>
<column name="client_id" type="bigint">
<constraints nullable="true" foreignKeyName="fk_cajh_client" referencedTableName="m_client" referencedColumnNames="id"/>
</column>
<column name="cif_number" type="varchar(50)"><constraints nullable="true"/></column>
<column name="display_name" type="varchar(200)"><constraints nullable="true"/></column>
<column name="share_percentage" type="decimal(5,2)"><constraints nullable="true"/></column>
<column name="signing_authority" type="varchar(100)"><constraints nullable="true"/></column>
<column name="role" type="varchar(100)"><constraints nullable="true"/></column>
<column name="is_primary" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
</createTable>
<!-- =========================================================
m_current_account_partner
Partners for non-individual (business) current accounts
========================================================= -->
<createTable tableName="m_current_account_partner">
<column name="id" type="bigint" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="current_account_id" type="bigint">
<constraints nullable="false" foreignKeyName="fk_cap_account" referencedTableName="m_current_account" referencedColumnNames="id"/>
</column>
<column name="client_id" type="bigint">
<constraints nullable="true" foreignKeyName="fk_cap_client" referencedTableName="m_client" referencedColumnNames="id"/>
</column>
<column name="client_cif" type="varchar(50)"><constraints nullable="true"/></column>
<column name="client_name" type="varchar(200)"><constraints nullable="true"/></column>
<column name="share_percentage" type="decimal(5,2)"><constraints nullable="true"/></column>
<column name="is_mandatory" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
</createTable>
<!-- =========================================================
m_current_account_officer_history
Officer assignment history
========================================================= -->
<createTable tableName="m_current_account_officer_history">
<column name="id" type="bigint" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="current_account_id" type="bigint">
<constraints nullable="false" foreignKeyName="fk_caoh_account" referencedTableName="m_current_account" referencedColumnNames="id"/>
</column>
<column name="staff_id" type="bigint">
<constraints nullable="true" foreignKeyName="fk_caoh_staff" referencedTableName="m_staff" referencedColumnNames="id"/>
</column>
<column name="start_date" type="date"><constraints nullable="false"/></column>
<column name="end_date" type="date"><constraints nullable="true"/></column>
<column name="created_by_id" type="bigint"><constraints nullable="true"/></column>
</createTable>
<!-- =========================================================
m_current_account_on_hold_transaction
On-hold / lien funds
========================================================= -->
<createTable tableName="m_current_account_on_hold_transaction">
<column name="id" type="bigint" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="current_account_id" type="bigint">
<constraints nullable="false" foreignKeyName="fk_caoht_account" referencedTableName="m_current_account" referencedColumnNames="id"/>
</column>
<column name="amount" type="decimal(19,6)"><constraints nullable="false"/></column>
<!-- 1=Hold, 2=Release -->
<column name="transaction_type_enum" type="smallint"><constraints nullable="false"/></column>
<column name="transaction_date" type="date"><constraints nullable="false"/></column>
<column name="is_reversed" type="boolean" defaultValueBoolean="false"><constraints nullable="false"/></column>
</createTable>
<!-- Indexes for fast lookup -->
<createIndex indexName="idx_ca_client_id" tableName="m_current_account">
<column name="client_id"/>
</createIndex>
<createIndex indexName="idx_ca_product_id" tableName="m_current_account">
<column name="product_id"/>
</createIndex>
<createIndex indexName="idx_ca_status" tableName="m_current_account">
<column name="status_enum"/>
</createIndex>
<createIndex indexName="idx_cat_account_id" tableName="m_current_account_transaction">
<column name="current_account_id"/>
</createIndex>
<createIndex indexName="idx_cat_date" tableName="m_current_account_transaction">
<column name="transaction_date"/>
</createIndex>
</changeSet>
</databaseChangeLog>
@@ -151,6 +151,15 @@
<class>org.apache.fineract.portfolio.self.pockets.domain.PocketAccountMapping</class>
<class>org.apache.fineract.portfolio.self.registration.domain.SelfServiceRegistration</class>
<!-- Current Account Entities -->
<class>org.apache.fineract.portfolio.currentaccount.domain.CurrentAccount</class>
<class>org.apache.fineract.portfolio.currentaccount.domain.CurrentAccountTransaction</class>
<class>org.apache.fineract.portfolio.currentaccount.domain.CurrentAccountCharge</class>
<class>org.apache.fineract.portfolio.currentaccount.domain.CurrentAccountFacilityConfig</class>
<class>org.apache.fineract.portfolio.currentaccount.domain.CurrentAccountJointHolder</class>
<class>org.apache.fineract.portfolio.currentaccount.domain.CurrentAccountPartner</class>
<class>org.apache.fineract.portfolio.currentaccount.domain.CurrentAccountOfficerHistory</class>
<!-- Charge Module Entities -->
<class>org.apache.fineract.portfolio.charge.domain.Charge</class>