feat: update savings product backend changes

This commit is contained in:
Nitesh Yadav
2026-04-28 13:12:27 +05:30
parent 72adbf6305
commit dc4a720ae2
16 changed files with 17339 additions and 35 deletions
@@ -281,4 +281,31 @@ public class SavingsApiConstants {
public static final String avgBalanceCalcPeriodParamName = "avgBalanceCalcPeriod";
public static final String validForPeriodParamName = "validForPeriod";
public static final String odAccountClosedZeroBalanceInDayClosingParamName = "odAccountClosedZeroBalanceInDayClosing";
// Status of Account fields
public static final String accountStatusParamName = "accountStatus";
public static final String modeOfOperationParamName = "modeOfOperation";
public static final String guardianClientIdParamName = "guardianClientId";
public static final String specialCategoryParamName = "specialCategory";
public static final String weakerSectionParamName = "weakerSection";
public static final String guardianNameParamName = "guardianName";
public static final String guardianCifNumberParamName = "guardianCifNumber";
public static final String guardianRelationshipParamName = "guardianRelationship";
public static final String minorDateOfBirthParamName = "minorDateOfBirth";
// Introducer fields
public static final String introducerIdParamName = "introducerId";
public static final String introducerNameParamName = "introducerName";
public static final String introducerCifNumberParamName = "introducerCifNumber";
// Joint holders
public static final String jointHoldersParamName = "jointHolders";
// Nominee
public static final String nomineeParamName = "nominee";
// Deposit Account Link (DAL)
public static final String linkedAccountIdParamName = "linkedAccountId";
public static final String linkedAccountTypeParamName = "linkedAccountType";
public static final String linkedAccountNoParamName = "linkedAccountNo";
}
@@ -126,6 +126,26 @@ public final class SavingsAccountData implements Serializable {
private List<DatatableData> datatables = null;
// CBS Account fields (saved per account)
private String cbsAccountType;
private String accountStatus;
private String modeOfOperation;
private String specialCategory;
private String weakerSection;
private String guardianName;
private String guardianCifNumber;
private String guardianRelationship;
private LocalDate minorDateOfBirth;
private Long guardianClientId;
private Long introducerClientId;
private String introducerName;
private String introducerCifNumber;
private Map<String, Object> nomineeData;
private Long linkedAccountId;
private String linkedAccountType;
private String linkedAccountNo;
private List<java.util.Map<String, Object>> jointHolders;
// CBS Product fields (populated in template response from selected product)
private String accountType;
private String customerSegment;
@@ -731,37 +751,50 @@ public final class SavingsAccountData implements Serializable {
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account, final SavingsAccountData template,
final Collection<SavingsAccountTransactionData> transactions, final Collection<SavingsAccountChargeData> charges) {
if (template == null) {
final Collection<SavingsProductData> productOptions = null;
final Collection<StaffData> fieldOfficerOptions = null;
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
final Collection<EnumOptionData> interestPostingPeriodTypeOptions = null;
final Collection<EnumOptionData> interestCalculationTypeOptions = null;
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null;
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null;
final Collection<EnumOptionData> withdrawalFeeTypeOptions = null;
final Collection<ChargeData> chargeOptions = null;
final Collection<SavingsProductData> productOptions = template == null ? null : template.productOptions;
final Collection<StaffData> fieldOfficerOptions = template == null ? null : template.fieldOfficerOptions;
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = template == null ? null
: template.interestCompoundingPeriodTypeOptions;
final Collection<EnumOptionData> interestPostingPeriodTypeOptions = template == null ? null
: template.interestPostingPeriodTypeOptions;
final Collection<EnumOptionData> interestCalculationTypeOptions = template == null ? null
: template.interestCalculationTypeOptions;
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = template == null ? null
: template.interestCalculationDaysInYearTypeOptions;
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = template == null ? null
: template.lockinPeriodFrequencyTypeOptions;
final Collection<EnumOptionData> withdrawalFeeTypeOptions = template == null ? null
: template.withdrawalFeeTypeOptions;
final Collection<ChargeData> chargeOptions = template == null ? null : template.chargeOptions;
return withTemplateOptions(account, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions,
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, transactions, charges, chargeOptions);
}
return new SavingsAccountData(account.id, account.accountNo, account.depositType, account.externalId, account.groupId,
final SavingsAccountData result = new SavingsAccountData(account.id, account.accountNo, account.depositType, account.externalId,
account.groupId,
account.groupName, account.clientId, account.clientName, account.savingsProductId, account.savingsProductName,
account.fieldOfficerId, account.fieldOfficerName, account.status, account.subStatus, account.reasonForBlock,
account.timeline, account.currency, account.nominalAnnualInterestRate, account.interestCompoundingPeriodType,
account.interestPostingPeriodType, account.interestCalculationType, account.interestCalculationDaysInYearType,
account.minRequiredOpeningBalance, account.lockinPeriodFrequency, account.lockinPeriodFrequencyType,
account.withdrawalFeeForTransfers, account.summary, transactions, template.productOptions, template.fieldOfficerOptions,
template.interestCompoundingPeriodTypeOptions, template.interestPostingPeriodTypeOptions,
template.interestCalculationTypeOptions, template.interestCalculationDaysInYearTypeOptions,
template.lockinPeriodFrequencyTypeOptions, template.withdrawalFeeTypeOptions, charges, template.chargeOptions,
account.withdrawalFeeForTransfers, account.summary, transactions, productOptions, fieldOfficerOptions,
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, charges, chargeOptions,
account.allowOverdraft, account.overdraftLimit, account.minRequiredBalance, account.enforceMinRequiredBalance,
account.maxAllowedLienLimit, account.lienAllowed, account.minBalanceForInterestCalculation, account.onHoldFunds,
account.nominalAnnualInterestRateOverdraft, account.minOverdraftForInterestCalculation, account.withHoldTax,
account.taxGroup, account.lastActiveTransactionDate, account.isDormancyTrackingActive, account.daysToInactive,
account.daysToDormancy, account.daysToEscheat, account.savingsAmountOnHold);
copyPresentationFields(result, template);
copyPresentationFields(result, account);
result.setProductOptions(productOptions);
result.setFieldOfficerOptions(fieldOfficerOptions);
result.setInterestCompoundingPeriodTypeOptions(interestCompoundingPeriodTypeOptions);
result.setInterestPostingPeriodTypeOptions(interestPostingPeriodTypeOptions);
result.setInterestCalculationTypeOptions(interestCalculationTypeOptions);
result.setInterestCalculationDaysInYearTypeOptions(interestCalculationDaysInYearTypeOptions);
result.setLockinPeriodFrequencyTypeOptions(lockinPeriodFrequencyTypeOptions);
result.setWithdrawalFeeTypeOptions(withdrawalFeeTypeOptions);
result.setChargeOptions(chargeOptions);
return result;
}
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account,
@@ -774,7 +807,8 @@ public final class SavingsAccountData implements Serializable {
final Collection<SavingsAccountTransactionData> transactions, final Collection<SavingsAccountChargeData> charges,
final Collection<ChargeData> chargeOptions) {
return new SavingsAccountData(account.id, account.accountNo, account.depositType, account.externalId, account.groupId,
final SavingsAccountData result = new SavingsAccountData(account.id, account.accountNo, account.depositType, account.externalId,
account.groupId,
account.groupName, account.clientId, account.clientName, account.savingsProductId, account.savingsProductName,
account.fieldOfficerId, account.fieldOfficerName, account.status, account.subStatus, account.reasonForBlock,
account.timeline, account.currency, account.nominalAnnualInterestRate, account.interestCompoundingPeriodType,
@@ -789,6 +823,232 @@ public final class SavingsAccountData implements Serializable {
account.minOverdraftForInterestCalculation, account.withHoldTax, account.taxGroup, account.lastActiveTransactionDate,
account.isDormancyTrackingActive, account.daysToInactive, account.daysToDormancy, account.daysToEscheat,
account.savingsAmountOnHold);
copyPresentationFields(result, account);
result.setProductOptions(productOptions);
result.setFieldOfficerOptions(fieldOfficerOptions);
result.setInterestCompoundingPeriodTypeOptions(interestCompoundingPeriodTypeOptions);
result.setInterestPostingPeriodTypeOptions(interestPostingPeriodTypeOptions);
result.setInterestCalculationTypeOptions(interestCalculationTypeOptions);
result.setInterestCalculationDaysInYearTypeOptions(interestCalculationDaysInYearTypeOptions);
result.setLockinPeriodFrequencyTypeOptions(lockinPeriodFrequencyTypeOptions);
result.setWithdrawalFeeTypeOptions(withdrawalFeeTypeOptions);
result.setChargeOptions(chargeOptions);
return result;
}
private static void copyPresentationFields(final SavingsAccountData target, final SavingsAccountData source) {
if (source == null) {
return;
}
if (source.previewAccountNo != null) {
target.setPreviewAccountNo(source.previewAccountNo);
}
if (source.cbsAccountType != null) {
target.setCbsAccountType(source.cbsAccountType);
}
if (source.customerSegment != null) {
target.setCustomerSegment(source.customerSegment);
}
if (source.accountStatus != null) {
target.setAccountStatus(source.accountStatus);
}
if (source.modeOfOperation != null) {
target.setModeOfOperation(source.modeOfOperation);
}
if (source.specialCategory != null) {
target.setSpecialCategory(source.specialCategory);
}
if (source.weakerSection != null) {
target.setWeakerSection(source.weakerSection);
}
if (source.guardianName != null) {
target.setGuardianName(source.guardianName);
}
if (source.guardianCifNumber != null) {
target.setGuardianCifNumber(source.guardianCifNumber);
}
if (source.guardianRelationship != null) {
target.setGuardianRelationship(source.guardianRelationship);
}
if (source.minorDateOfBirth != null) {
target.setMinorDateOfBirth(source.minorDateOfBirth);
}
if (source.guardianClientId != null) {
target.setGuardianClientId(source.guardianClientId);
}
if (source.introducerClientId != null) {
target.setIntroducerClientId(source.introducerClientId);
}
if (source.introducerName != null) {
target.setIntroducerName(source.introducerName);
}
if (source.introducerCifNumber != null) {
target.setIntroducerCifNumber(source.introducerCifNumber);
}
if (source.nomineeData != null) {
target.setNomineeData(source.nomineeData);
}
if (source.linkedAccountId != null) {
target.setLinkedAccountId(source.linkedAccountId);
}
if (source.linkedAccountType != null) {
target.setLinkedAccountType(source.linkedAccountType);
}
if (source.linkedAccountNo != null) {
target.setLinkedAccountNo(source.linkedAccountNo);
}
if (source.jointHolders != null) {
target.setJointHolders(new ArrayList<>(source.jointHolders));
}
if (source.accountType != null) {
target.setAccountType(source.accountType);
}
if (source.customerSegmentOptions != null) {
target.setCustomerSegmentOptions(source.customerSegmentOptions);
}
if (source.accountTypeOptions != null) {
target.setAccountTypeOptions(source.accountTypeOptions);
}
if (source.productCode != null) {
target.setProductCode(source.productCode);
}
if (source.effectiveDate != null) {
target.setEffectiveDate(source.effectiveDate);
}
if (source.effectiveTo != null) {
target.setEffectiveTo(source.effectiveTo);
}
if (source.endDate != null) {
target.setEndDate(source.endDate);
}
if (source.introducerRequired != null) {
target.setIntroducerRequired(source.introducerRequired);
}
if (source.shareLinkingEnabled != null) {
target.setShareLinkingEnabled(source.shareLinkingEnabled);
}
if (source.nominationFacility != null) {
target.setNominationFacility(source.nominationFacility);
}
if (source.dormancyAlert != null) {
target.setDormancyAlert(source.dormancyAlert);
}
if (source.isDormancyTrackingActiveFromProduct != null) {
target.setIsDormancyTrackingActiveFromProduct(source.isDormancyTrackingActiveFromProduct);
}
if (source.daysToInactiveFromProduct != null) {
target.setDaysToInactiveFromProduct(source.daysToInactiveFromProduct);
}
if (source.daysToDormancyFromProduct != null) {
target.setDaysToDormancyFromProduct(source.daysToDormancyFromProduct);
}
if (source.daysToEscheatFromProduct != null) {
target.setDaysToEscheatFromProduct(source.daysToEscheatFromProduct);
}
if (source.interestCalculationTypeName != null) {
target.setInterestCalculationTypeName(source.interestCalculationTypeName);
}
if (source.enableLockinPeriod != null) {
target.setEnableLockinPeriod(source.enableLockinPeriod);
}
if (source.balanceFrequency != null) {
target.setBalanceFrequency(source.balanceFrequency);
}
if (source.accountClosedZeroBalanceInDayClosing != null) {
target.setAccountClosedZeroBalanceInDayClosing(source.accountClosedZeroBalanceInDayClosing);
}
if (source.balanceSwapOption != null) {
target.setBalanceSwapOption(source.balanceSwapOption);
}
if (source.msme != null) {
target.setMsme(source.msme);
}
if (source.autoDebitFacility != null) {
target.setAutoDebitFacility(source.autoDebitFacility);
}
if (source.avgBalanceCalcPeriod != null) {
target.setAvgBalanceCalcPeriod(source.avgBalanceCalcPeriod);
}
if (source.validForPeriod != null) {
target.setValidForPeriod(source.validForPeriod);
}
if (source.odAccountClosedZeroBalanceInDayClosing != null) {
target.setOdAccountClosedZeroBalanceInDayClosing(source.odAccountClosedZeroBalanceInDayClosing);
}
if (source.lastInterestDate != null) {
target.setLastInterestDate(source.lastInterestDate);
}
if (source.accountFacilityConfig != null) {
target.setAccountFacilityConfig(source.accountFacilityConfig);
}
if (source.accountFacilityLimits != null) {
target.setAccountFacilityLimits(source.accountFacilityLimits);
}
if (source.depositLimitKyc != null) {
target.setDepositLimitKyc(source.depositLimitKyc);
}
if (source.interestCalculateSelector != null) {
target.setInterestCalculateSelector(source.interestCalculateSelector);
}
if (source.averagePeriod != null) {
target.setAveragePeriod(source.averagePeriod);
}
if (source.autoPost != null) {
target.setAutoPost(source.autoPost);
}
if (source.frequencyFixDay != null) {
target.setFrequencyFixDay(source.frequencyFixDay);
}
if (source.interestCalculationTypeOption != null) {
target.setInterestCalculationTypeOption(source.interestCalculationTypeOption);
}
if (source.periodFrequencyOptions != null) {
target.setPeriodFrequencyOptions(source.periodFrequencyOptions);
}
if (source.productId != null) {
target.setProductId(source.productId);
}
if (source.locale != null) {
target.setLocale(source.locale);
}
if (source.dateFormat != null) {
target.setDateFormat(source.dateFormat);
}
if (source.rowIndex != null) {
target.setRowIndex(source.rowIndex);
}
if (source.submittedOnDate != null) {
target.setSubmittedOnDate(source.submittedOnDate);
}
if (source.startInterestCalculationDate != null) {
target.setStartInterestCalculationDate(source.startInterestCalculationDate);
}
if (source.activatedOnDate != null) {
target.setActivatedOnDate(source.activatedOnDate);
}
if (source.lockedInUntilDate != null) {
target.setLockedInUntilDate(source.lockedInUntilDate);
}
if (source.officeId != null) {
target.setOfficeId(source.officeId);
}
if (source.clientData != null) {
target.setClientData(source.clientData);
}
if (source.groupGeneralData != null) {
target.setGroupGeneralData(source.groupGeneralData);
}
if (source.savingsProductData != null) {
target.setSavingsProduct(source.savingsProductData);
}
if (source.savingsAccountSummaryData != null) {
target.setSavingsAccountSummaryData(source.savingsAccountSummaryData);
}
if (source.lastSavingsAccountTransaction != null) {
target.setLastSavingsAccountTransaction(source.lastSavingsAccountTransaction);
}
}
public static SavingsAccountData withClientTemplate(final Long clientId, final String clientName, final Long groupId,
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -19,7 +19,27 @@
package org.apache.fineract.portfolio.savings.domain;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.accountFacilityConfigParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.accountNoParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.accountStatusParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.guardianClientIdParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.modeOfOperationParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.accountTypeParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.customerSegmentParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.guardianCifNumberParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.guardianNameParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.guardianRelationshipParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.introducerCifNumberParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.introducerIdParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.introducerNameParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.jointHoldersParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.linkedAccountIdParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.linkedAccountNoParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.linkedAccountTypeParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minorDateOfBirthParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nomineeParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.specialCategoryParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.weakerSectionParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.allowOverdraftParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.clientIdParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.enforceMinRequiredBalanceParamName;
@@ -45,7 +65,10 @@ import static org.apache.fineract.portfolio.savings.SavingsApiConstants.submitte
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withHoldTaxParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
@@ -336,9 +359,102 @@ public class SavingsAccountAssembler {
account.validateAccountValuesWithProduct();
// CBS extended fields
applyCbsFields(command, element, account);
return account;
}
private static final Gson GSON = new Gson();
private void applyCbsFields(final JsonCommand command, final JsonElement element, final SavingsAccount account) {
// Product classification
final String cbsAccountType = this.fromApiJsonHelper.extractStringNamed(accountTypeParamName, element);
if (cbsAccountType != null) account.setCbsAccountType(cbsAccountType);
final String customerSegment = this.fromApiJsonHelper.extractStringNamed(customerSegmentParamName, element);
if (customerSegment != null) account.setCustomerSegment(customerSegment);
// Status of Account
final String accountStatus = this.fromApiJsonHelper.extractStringNamed(accountStatusParamName, element);
if (accountStatus != null) account.setAccountStatus(accountStatus);
final String modeOfOperation = this.fromApiJsonHelper.extractStringNamed(modeOfOperationParamName, element);
if (modeOfOperation != null) account.setModeOfOperation(modeOfOperation);
account.setSpecialCategory(this.fromApiJsonHelper.extractStringNamed(specialCategoryParamName, element));
account.setWeakerSection(this.fromApiJsonHelper.extractStringNamed(weakerSectionParamName, element));
account.setGuardianName(this.fromApiJsonHelper.extractStringNamed(guardianNameParamName, element));
account.setGuardianCifNumber(this.fromApiJsonHelper.extractStringNamed(guardianCifNumberParamName, element));
account.setGuardianRelationship(this.fromApiJsonHelper.extractStringNamed(guardianRelationshipParamName, element));
if (command.parameterExists(minorDateOfBirthParamName)) {
final LocalDate minorDob = this.fromApiJsonHelper.extractLocalDateNamed(minorDateOfBirthParamName, element);
account.setMinorDateOfBirth(minorDob);
}
final Long guardianClientId = this.fromApiJsonHelper.extractLongNamed(guardianClientIdParamName, element);
if (guardianClientId != null) account.setGuardianClientId(guardianClientId);
// Introducer
final Long introducerId = this.fromApiJsonHelper.extractLongNamed(introducerIdParamName, element);
if (introducerId != null) account.setIntroducerClientId(introducerId);
account.setIntroducerName(this.fromApiJsonHelper.extractStringNamed(introducerNameParamName, element));
account.setIntroducerCifNumber(this.fromApiJsonHelper.extractStringNamed(introducerCifNumberParamName, element));
// Nominee (stored as JSON string)
if (element.getAsJsonObject().has(nomineeParamName)) {
final JsonElement nomineeEl = element.getAsJsonObject().get(nomineeParamName);
if (nomineeEl != null && !nomineeEl.isJsonNull()) {
account.setNomineeData(nomineeEl.toString());
}
}
// Deposit Account Link
final Long linkedAccountId = this.fromApiJsonHelper.extractLongNamed(linkedAccountIdParamName, element);
if (linkedAccountId != null) account.setLinkedAccountId(linkedAccountId);
account.setLinkedAccountType(this.fromApiJsonHelper.extractStringNamed(linkedAccountTypeParamName, element));
account.setLinkedAccountNo(this.fromApiJsonHelper.extractStringNamed(linkedAccountNoParamName, element));
// Account Facility Config
if (element.getAsJsonObject().has(accountFacilityConfigParamName)) {
final JsonElement configEl = element.getAsJsonObject().get(accountFacilityConfigParamName);
if (configEl != null && !configEl.isJsonNull() && configEl.isJsonObject()) {
SavingsAccountFacilityConfig facilityConfig = account.getFacilityConfig();
if (facilityConfig == null) {
facilityConfig = new SavingsAccountFacilityConfig(account);
account.setFacilityConfig(facilityConfig);
}
facilityConfig.updateFrom(configEl.getAsJsonObject());
}
}
// Joint holders
if (element.getAsJsonObject().has(jointHoldersParamName)) {
final JsonElement holdersEl = element.getAsJsonObject().get(jointHoldersParamName);
if (holdersEl != null && !holdersEl.isJsonNull() && holdersEl.isJsonArray()) {
final com.google.gson.JsonArray holdersArray = holdersEl.getAsJsonArray();
final List<SavingsAccountJointHolder> holders = new ArrayList<>();
for (int i = 0; i < holdersArray.size(); i++) {
final JsonObject h = holdersArray.get(i).getAsJsonObject();
final Long clientId = h.has("clientId") && !h.get("clientId").isJsonNull()
? h.get("clientId").getAsLong() : null;
final String cifNumber = h.has("cifNumber") ? h.get("cifNumber").getAsString() : null;
final String displayName = h.has("displayName") ? h.get("displayName").getAsString() : null;
final BigDecimal sharePercentage = h.has("sharePercentage") && !h.get("sharePercentage").isJsonNull()
? h.get("sharePercentage").getAsBigDecimal() : null;
final String signingAuthority = h.has("signingAuthority") ? h.get("signingAuthority").getAsString() : null;
final String role = h.has("role") ? h.get("role").getAsString() : null;
final boolean isPrimary = h.has("isPrimary") && h.get("isPrimary").getAsBoolean();
holders.add(new SavingsAccountJointHolder(account, clientId, cifNumber, displayName,
sharePercentage, signingAuthority, role, isPrimary));
}
account.getJointHolders().clear();
account.getJointHolders().addAll(holders);
}
}
}
public SavingsAccount assembleFrom(final Long savingsId, final boolean backdatedTxnsAllowedTill) {
SavingsAccount account = this.savingsAccountRepository.findSavingsWithNotFoundDetection(savingsId, backdatedTxnsAllowedTill);
return loadTransactionsToSavingsAccount(account, backdatedTxnsAllowedTill);
@@ -215,7 +215,22 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
try {
final String sql = "select " + this.savingAccountMapper.schema() + " where sa.id = ?";
return this.jdbcTemplate.queryForObject(sql, this.savingAccountMapper, new Object[] { accountId }); // NOSONAR
final SavingsAccountData accountData = this.jdbcTemplate.queryForObject(sql, this.savingAccountMapper,
new Object[] { accountId }); // NOSONAR
// Load joint holders
if (accountData != null) {
final String jointSql = "SELECT jh.id as id, jh.client_id as clientId, jh.cif_number as cifNumber, "
+ "jh.display_name as displayName, jh.share_percentage as sharePercentage, "
+ "jh.signing_authority as signingAuthority, jh.role as role, jh.is_primary as isPrimary "
+ "FROM m_savings_account_joint_holders jh WHERE jh.savings_account_id = ?";
final List<java.util.Map<String, Object>> jointHolders = this.jdbcTemplate.queryForList(jointSql, accountId);
if (!jointHolders.isEmpty()) {
accountData.setJointHolders(jointHolders);
}
}
return accountData;
} catch (final EmptyResultDataAccessException e) {
throw new SavingsAccountNotFoundException(accountId, e);
}
@@ -763,7 +778,43 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
sqlBuilder.append("sp.is_dormancy_tracking_active as isDormancyTrackingActive, ");
sqlBuilder.append("sp.days_to_inactive as daysToInactive, ");
sqlBuilder.append("sp.days_to_dormancy as daysToDormancy, ");
sqlBuilder.append("sp.days_to_escheat as daysToEscheat ");
sqlBuilder.append("sp.days_to_escheat as daysToEscheat, ");
// CBS extended fields
sqlBuilder.append("sa.cbs_account_type as cbsAccountType, ");
sqlBuilder.append("sa.customer_segment as customerSegment, ");
sqlBuilder.append("sa.account_status as accountStatus, ");
sqlBuilder.append("sa.mode_of_operation as modeOfOperation, ");
sqlBuilder.append("sa.special_category as specialCategory, ");
sqlBuilder.append("sa.weaker_section as weakerSection, ");
sqlBuilder.append("sa.guardian_name as guardianName, ");
sqlBuilder.append("sa.guardian_cif_number as guardianCifNumber, ");
sqlBuilder.append("sa.guardian_relationship as guardianRelationship, ");
sqlBuilder.append("sa.minor_date_of_birth as minorDateOfBirth, ");
sqlBuilder.append("sa.guardian_client_id as guardianClientId, ");
sqlBuilder.append("sa.introducer_client_id as introducerClientId, ");
sqlBuilder.append("sa.introducer_name as introducerName, ");
sqlBuilder.append("sa.introducer_cif_number as introducerCifNumber, ");
sqlBuilder.append("sa.nominee_data as nomineeData, ");
sqlBuilder.append("sa.linked_account_id as linkedAccountId, ");
sqlBuilder.append("sa.linked_account_type as linkedAccountType, ");
sqlBuilder.append("sa.linked_account_no as linkedAccountNo, ");
// Facility config fields
sqlBuilder.append("safc.atm_facility as atmFacility, ");
sqlBuilder.append("safc.atm_withdrawal_facility as atmWithdrawalFacility, ");
sqlBuilder.append("safc.upi_facility as upiFacility, ");
sqlBuilder.append("safc.pos_transactions_facility as posTransactionsFacility, ");
sqlBuilder.append("safc.cheque_book as chequeBook, ");
sqlBuilder.append("safc.imps_facility as impsFacility, ");
sqlBuilder.append("safc.sms_alerts as smsAlerts, ");
sqlBuilder.append("safc.bbps_facility as bbpsFacility, ");
sqlBuilder.append("safc.insurance_cover as insuranceCover, ");
sqlBuilder.append("safc.bepg_facility as bepgFacility, ");
sqlBuilder.append("safc.neft_facility as neftFacility, ");
sqlBuilder.append("safc.rtgs_facility as rtgsFacility, ");
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("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 ");
@@ -777,6 +828,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
sqlBuilder.append("left join m_appuser avbu on avbu.id = sa.activatedon_userid ");
sqlBuilder.append("left join m_appuser cbu on cbu.id = sa.closedon_userid ");
sqlBuilder.append("left join m_tax_group tg on tg.id = sa.tax_group_id ");
sqlBuilder.append("left join m_savings_account_facility_config safc on safc.savings_account_id = sa.id ");
this.schemaSql = sqlBuilder.toString();
}
@@ -970,14 +1022,70 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
taxGroupData = TaxGroupData.lookup(taxGroupId, taxGroupName);
}
return SavingsAccountData.instance(id, accountNo, depositType, externalId, groupId, groupName, clientId, clientName, productId,
productName, fieldOfficerId, fieldOfficerName, status, subStatus, reasonForBlock, timeline, currency,
nominalAnnualInterestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType,
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType,
withdrawalFeeForTransfers, summary, allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance,
maxAllowedLienLimit, lienAllowed, minBalanceForInterestCalculation, onHoldFunds, nominalAnnualInterestRateOverdraft,
minOverdraftForInterestCalculation, withHoldTax, taxGroupData, lastActiveTransactionDate, isDormancyTrackingActive,
daysToInactive, daysToDormancy, daysToEscheat, onHoldAmount);
final SavingsAccountData accountData = SavingsAccountData.instance(id, accountNo, depositType, externalId, groupId, groupName,
clientId, clientName, productId, productName, fieldOfficerId, fieldOfficerName, status, subStatus, reasonForBlock,
timeline, currency, nominalAnnualInterestRate, interestCompoundingPeriodType, interestPostingPeriodType,
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, allowOverdraft, overdraftLimit, minRequiredBalance,
enforceMinRequiredBalance, maxAllowedLienLimit, lienAllowed, minBalanceForInterestCalculation, onHoldFunds,
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroupData,
lastActiveTransactionDate, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat, onHoldAmount);
// CBS extended fields
accountData.setCbsAccountType(rs.getString("cbsAccountType"));
accountData.setCustomerSegment(rs.getString("customerSegment"));
accountData.setAccountStatus(rs.getString("accountStatus"));
accountData.setModeOfOperation(rs.getString("modeOfOperation"));
accountData.setSpecialCategory(rs.getString("specialCategory"));
accountData.setWeakerSection(rs.getString("weakerSection"));
accountData.setGuardianName(rs.getString("guardianName"));
accountData.setGuardianCifNumber(rs.getString("guardianCifNumber"));
accountData.setGuardianRelationship(rs.getString("guardianRelationship"));
accountData.setMinorDateOfBirth(JdbcSupport.getLocalDate(rs, "minorDateOfBirth"));
accountData.setGuardianClientId(JdbcSupport.getLong(rs, "guardianClientId"));
accountData.setIntroducerClientId(JdbcSupport.getLong(rs, "introducerClientId"));
accountData.setIntroducerName(rs.getString("introducerName"));
accountData.setIntroducerCifNumber(rs.getString("introducerCifNumber"));
accountData.setLinkedAccountId(JdbcSupport.getLong(rs, "linkedAccountId"));
accountData.setLinkedAccountType(rs.getString("linkedAccountType"));
accountData.setLinkedAccountNo(rs.getString("linkedAccountNo"));
// Nominee as parsed map
final String nomineeDataStr = rs.getString("nomineeData");
if (nomineeDataStr != null && !nomineeDataStr.isEmpty()) {
try {
com.google.gson.Gson gson = new com.google.gson.Gson();
@SuppressWarnings("unchecked")
java.util.Map<String, Object> nomineeMap = gson.fromJson(nomineeDataStr,
new com.google.gson.reflect.TypeToken<java.util.Map<String, Object>>() {}.getType());
accountData.setNomineeData(nomineeMap);
} catch (Exception ignored) {}
}
// Facility config
final boolean hasFacilityConfig = rs.getObject("atmFacility") != null;
if (hasFacilityConfig) {
final java.util.Map<String, Object> facilityConfigMap = new java.util.LinkedHashMap<>();
facilityConfigMap.put("atmFacility", rs.getBoolean("atmFacility"));
facilityConfigMap.put("atmWithdrawalFacility", rs.getBoolean("atmWithdrawalFacility"));
facilityConfigMap.put("upiFacility", rs.getBoolean("upiFacility"));
facilityConfigMap.put("posTransactionsFacility", rs.getBoolean("posTransactionsFacility"));
facilityConfigMap.put("chequeBook", rs.getBoolean("chequeBook"));
facilityConfigMap.put("impsFacility", rs.getBoolean("impsFacility"));
facilityConfigMap.put("smsAlerts", rs.getBoolean("smsAlerts"));
facilityConfigMap.put("bbpsFacility", rs.getBoolean("bbpsFacility"));
facilityConfigMap.put("insuranceCover", rs.getBoolean("insuranceCover"));
facilityConfigMap.put("bepgFacility", rs.getBoolean("bepgFacility"));
facilityConfigMap.put("neftFacility", rs.getBoolean("neftFacility"));
facilityConfigMap.put("rtgsFacility", rs.getBoolean("rtgsFacility"));
facilityConfigMap.put("interBankTotalCapFacility", rs.getBoolean("interBankTotalCapFacility"));
facilityConfigMap.put("withdrawalFacility", rs.getBoolean("withdrawalFacility"));
facilityConfigMap.put("depositFacilityKyc", rs.getBoolean("depositFacilityKyc"));
facilityConfigMap.put("virtualDebitCard", rs.getBoolean("virtualDebitCard"));
accountData.setAccountFacilityConfig(facilityConfigMap);
}
return accountData;
}
}
@@ -263,6 +263,8 @@
<class>org.apache.fineract.portfolio.savings.domain.SavingsProductDepositLimitKyc</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsProductFacilityConfig</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsProductFacilityLimit</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsAccountFacilityConfig</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsAccountJointHolder</class>
<!-- Progressive Loan Module Entities -->
<class>org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeBalance</class>
@@ -88,7 +88,13 @@ public class SavingsApiSetConstants extends SavingsApiConstants {
"interestCalculateSelector", "averagePeriod", "autoPost", "frequencyFixDay", "lastInterestDate",
"balanceSwapOption", "msme", "autoDebitFacility", "interestCalculationTypeOption",
"effectiveDate", "isDormancyTrackingActive", "daysToInactive", "daysToDormancy", "daysToEscheat",
"avgBalanceCalcPeriod", "validForPeriod", "odAccountClosedZeroBalanceInDayClosing"));
"avgBalanceCalcPeriod", "validForPeriod", "odAccountClosedZeroBalanceInDayClosing",
// CBS Account fields
"cbsAccountType", "accountStatus", "modeOfOperation", "specialCategory", "weakerSection",
"guardianName", "guardianCifNumber", "guardianRelationship", "guardianClientId", "minorDateOfBirth",
"introducerClientId", "introducerName", "introducerCifNumber",
"nomineeData", "linkedAccountId", "linkedAccountType", "linkedAccountNo",
"jointHolders"));
protected static final Set<String> SAVINGS_TRANSACTION_RESPONSE_DATA_PARAMETERS = new HashSet<>(
Arrays.asList(idParamName, "accountId", accountNoParamName, "currency", "amount", dateParamName, paymentDetailDataParamName,
@@ -39,7 +39,15 @@ public class SavingsAccountConstant extends SavingsApiConstants {
withdrawalFeeForTransfersParamName, feeAmountParamName, feeOnMonthDayParamName, chargesParamName, allowOverdraftParamName,
overdraftLimitParamName, minRequiredBalanceParamName, enforceMinRequiredBalanceParamName, lienAllowedParamName,
maxAllowedLienLimitParamName, nominalAnnualInterestRateOverdraftParamName, minOverdraftForInterestCalculationParamName,
withHoldTaxParamName, datatables, gsimApplicationId, gsimLastApplication));
withHoldTaxParamName, datatables, gsimApplicationId, gsimLastApplication,
// CBS Account fields
"accountType", "customerSegment", accountStatusParamName, modeOfOperationParamName,
specialCategoryParamName, weakerSectionParamName,
guardianNameParamName, guardianCifNumberParamName, guardianRelationshipParamName,
guardianClientIdParamName, minorDateOfBirthParamName,
introducerIdParamName, introducerNameParamName, introducerCifNumberParamName,
nomineeParamName, linkedAccountIdParamName, linkedAccountTypeParamName, linkedAccountNoParamName,
accountFacilityConfigParamName, jointHoldersParamName));
/**
* These parameters will match the class level parameters of {@link SavingsAccountData}. Where possible, we try to
@@ -3900,4 +3900,126 @@ public class SavingsAccount extends AbstractAuditableWithUTCDateTimeCustom<Long>
public DepositAccountType depositAccountType() {
return DepositAccountType.fromInt(100);
}
// ─── CBS extended fields ───────────────────────────────────────────────────
@Column(name = "cbs_account_type", length = 100)
private String cbsAccountType;
@Column(name = "customer_segment", length = 100)
private String customerSegment;
@Column(name = "account_status", length = 50)
private String accountStatus;
@Column(name = "mode_of_operation", length = 50)
private String modeOfOperation;
@Column(name = "special_category", length = 100)
private String specialCategory;
@Column(name = "weaker_section", length = 100)
private String weakerSection;
@Column(name = "guardian_name", length = 200)
private String guardianName;
@Column(name = "guardian_cif_number", length = 50)
private String guardianCifNumber;
@Column(name = "guardian_relationship", length = 100)
private String guardianRelationship;
@Column(name = "minor_date_of_birth")
private LocalDate minorDateOfBirth;
@Column(name = "guardian_client_id")
private Long guardianClientId;
@Column(name = "introducer_client_id")
private Long introducerClientId;
@Column(name = "introducer_name", length = 200)
private String introducerName;
@Column(name = "introducer_cif_number", length = 50)
private String introducerCifNumber;
@Column(name = "nominee_data", columnDefinition = "TEXT")
private String nomineeData;
@Column(name = "linked_account_id")
private Long linkedAccountId;
@Column(name = "linked_account_type", length = 20)
private String linkedAccountType;
@Column(name = "linked_account_no", length = 50)
private String linkedAccountNo;
@jakarta.persistence.OneToOne(cascade = jakarta.persistence.CascadeType.ALL, mappedBy = "savingsAccount", orphanRemoval = true, fetch = FetchType.LAZY)
private SavingsAccountFacilityConfig facilityConfig;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "savingsAccount", orphanRemoval = true, fetch = FetchType.LAZY)
private List<SavingsAccountJointHolder> jointHolders = new ArrayList<>();
public String getCbsAccountType() { return cbsAccountType; }
public void setCbsAccountType(String v) { this.cbsAccountType = v; }
public String getCustomerSegment() { return customerSegment; }
public void setCustomerSegment(String v) { this.customerSegment = v; }
public String getAccountStatus() { return accountStatus; }
public void setAccountStatus(String v) { this.accountStatus = v; }
public String getModeOfOperation() { return modeOfOperation; }
public void setModeOfOperation(String v) { this.modeOfOperation = v; }
public String getSpecialCategory() { return specialCategory; }
public void setSpecialCategory(String v) { this.specialCategory = v; }
public String getWeakerSection() { return weakerSection; }
public void setWeakerSection(String v) { this.weakerSection = v; }
public String getGuardianName() { return guardianName; }
public void setGuardianName(String v) { this.guardianName = v; }
public String getGuardianCifNumber() { return guardianCifNumber; }
public void setGuardianCifNumber(String v) { this.guardianCifNumber = v; }
public String getGuardianRelationship() { return guardianRelationship; }
public void setGuardianRelationship(String v) { this.guardianRelationship = v; }
public LocalDate getMinorDateOfBirth() { return minorDateOfBirth; }
public void setMinorDateOfBirth(LocalDate v) { this.minorDateOfBirth = v; }
public Long getGuardianClientId() { return guardianClientId; }
public void setGuardianClientId(Long v) { this.guardianClientId = v; }
public Long getIntroducerClientId() { return introducerClientId; }
public void setIntroducerClientId(Long v) { this.introducerClientId = v; }
public String getIntroducerName() { return introducerName; }
public void setIntroducerName(String v) { this.introducerName = v; }
public String getIntroducerCifNumber() { return introducerCifNumber; }
public void setIntroducerCifNumber(String v) { this.introducerCifNumber = v; }
public String getNomineeData() { return nomineeData; }
public void setNomineeData(String v) { this.nomineeData = v; }
public Long getLinkedAccountId() { return linkedAccountId; }
public void setLinkedAccountId(Long v) { this.linkedAccountId = v; }
public String getLinkedAccountType() { return linkedAccountType; }
public void setLinkedAccountType(String v) { this.linkedAccountType = v; }
public String getLinkedAccountNo() { return linkedAccountNo; }
public void setLinkedAccountNo(String v) { this.linkedAccountNo = v; }
public SavingsAccountFacilityConfig getFacilityConfig() { return facilityConfig; }
public void setFacilityConfig(SavingsAccountFacilityConfig v) { this.facilityConfig = v; }
public List<SavingsAccountJointHolder> getJointHolders() { return jointHolders; }
public void setJointHolders(List<SavingsAccountJointHolder> v) { this.jointHolders = v; }
}
@@ -0,0 +1,168 @@
/**
* 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.domain;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import java.time.LocalDateTime;
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
@Entity
@Table(name = "m_savings_account_facility_config")
public class SavingsAccountFacilityConfig extends AbstractPersistableCustom<Long> {
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "savings_account_id", nullable = false)
private SavingsAccount savingsAccount;
@Column(name = "atm_facility")
private Boolean atmFacility = false;
@Column(name = "atm_withdrawal_facility")
private Boolean atmWithdrawalFacility = false;
@Column(name = "upi_facility")
private Boolean upiFacility = false;
@Column(name = "pos_transactions_facility")
private Boolean posTransactionsFacility = false;
@Column(name = "cheque_book")
private Boolean chequeBook = false;
@Column(name = "imps_facility")
private Boolean impsFacility = false;
@Column(name = "sms_alerts")
private Boolean smsAlerts = false;
@Column(name = "bbps_facility")
private Boolean bbpsFacility = false;
@Column(name = "insurance_cover")
private Boolean insuranceCover = false;
@Column(name = "bepg_facility")
private Boolean bepgFacility = false;
@Column(name = "neft_facility")
private Boolean neftFacility = false;
@Column(name = "rtgs_facility")
private Boolean rtgsFacility = false;
@Column(name = "inter_bank_total_cap_facility")
private Boolean interBankTotalCapFacility = false;
@Column(name = "withdrawal_facility")
private Boolean withdrawalFacility = false;
@Column(name = "deposit_facility_kyc")
private Boolean depositFacilityKyc = false;
@Column(name = "virtual_debit_card")
private Boolean virtualDebitCard = false;
@Column(name = "created_date", nullable = false)
private LocalDateTime createdDate;
protected SavingsAccountFacilityConfig() {
this.createdDate = LocalDateTime.now();
}
public SavingsAccountFacilityConfig(SavingsAccount savingsAccount) {
this();
this.savingsAccount = savingsAccount;
}
public SavingsAccount getSavingsAccount() { return savingsAccount; }
public void setSavingsAccount(SavingsAccount savingsAccount) { this.savingsAccount = savingsAccount; }
public Boolean getAtmFacility() { return atmFacility; }
public void setAtmFacility(Boolean v) { this.atmFacility = v != null ? v : false; }
public Boolean getAtmWithdrawalFacility() { return atmWithdrawalFacility; }
public void setAtmWithdrawalFacility(Boolean v) { this.atmWithdrawalFacility = v != null ? v : false; }
public Boolean getUpiFacility() { return upiFacility; }
public void setUpiFacility(Boolean v) { this.upiFacility = v != null ? v : false; }
public Boolean getPosTransactionsFacility() { return posTransactionsFacility; }
public void setPosTransactionsFacility(Boolean v) { this.posTransactionsFacility = v != null ? v : false; }
public Boolean getChequeBook() { return chequeBook; }
public void setChequeBook(Boolean v) { this.chequeBook = v != null ? v : false; }
public Boolean getImpsFacility() { return impsFacility; }
public void setImpsFacility(Boolean v) { this.impsFacility = v != null ? v : false; }
public Boolean getSmsAlerts() { return smsAlerts; }
public void setSmsAlerts(Boolean v) { this.smsAlerts = v != null ? v : false; }
public Boolean getBbpsFacility() { return bbpsFacility; }
public void setBbpsFacility(Boolean v) { this.bbpsFacility = v != null ? v : false; }
public Boolean getInsuranceCover() { return insuranceCover; }
public void setInsuranceCover(Boolean v) { this.insuranceCover = v != null ? v : false; }
public Boolean getBepgFacility() { return bepgFacility; }
public void setBepgFacility(Boolean v) { this.bepgFacility = v != null ? v : false; }
public Boolean getNeftFacility() { return neftFacility; }
public void setNeftFacility(Boolean v) { this.neftFacility = v != null ? v : false; }
public Boolean getRtgsFacility() { return rtgsFacility; }
public void setRtgsFacility(Boolean v) { this.rtgsFacility = v != null ? v : false; }
public Boolean getInterBankTotalCapFacility() { return interBankTotalCapFacility; }
public void setInterBankTotalCapFacility(Boolean v) { this.interBankTotalCapFacility = v != null ? v : false; }
public Boolean getWithdrawalFacility() { return withdrawalFacility; }
public void setWithdrawalFacility(Boolean v) { this.withdrawalFacility = v != null ? v : false; }
public Boolean getDepositFacilityKyc() { return depositFacilityKyc; }
public void setDepositFacilityKyc(Boolean v) { this.depositFacilityKyc = v != null ? v : false; }
public Boolean getVirtualDebitCard() { return virtualDebitCard; }
public void setVirtualDebitCard(Boolean v) { this.virtualDebitCard = v != null ? v : false; }
public void updateFrom(com.google.gson.JsonObject config) {
if (config == null) return;
if (config.has("atmFacility")) setAtmFacility(config.get("atmFacility").getAsBoolean());
if (config.has("atmWithdrawalFacility")) setAtmWithdrawalFacility(config.get("atmWithdrawalFacility").getAsBoolean());
if (config.has("upiFacility")) setUpiFacility(config.get("upiFacility").getAsBoolean());
if (config.has("posTransactionsFacility")) setPosTransactionsFacility(config.get("posTransactionsFacility").getAsBoolean());
if (config.has("chequeBook")) setChequeBook(config.get("chequeBook").getAsBoolean());
if (config.has("impsFacility")) setImpsFacility(config.get("impsFacility").getAsBoolean());
if (config.has("smsAlerts")) setSmsAlerts(config.get("smsAlerts").getAsBoolean());
if (config.has("bbpsFacility")) setBbpsFacility(config.get("bbpsFacility").getAsBoolean());
if (config.has("insuranceCover")) setInsuranceCover(config.get("insuranceCover").getAsBoolean());
if (config.has("bepgFacility")) setBepgFacility(config.get("bepgFacility").getAsBoolean());
if (config.has("neftFacility")) setNeftFacility(config.get("neftFacility").getAsBoolean());
if (config.has("rtgsFacility")) setRtgsFacility(config.get("rtgsFacility").getAsBoolean());
if (config.has("interBankTotalCapFacility")) setInterBankTotalCapFacility(config.get("interBankTotalCapFacility").getAsBoolean());
if (config.has("withdrawalFacility")) setWithdrawalFacility(config.get("withdrawalFacility").getAsBoolean());
if (config.has("depositFacilityKyc")) setDepositFacilityKyc(config.get("depositFacilityKyc").getAsBoolean());
if (config.has("virtualDebitCard")) setVirtualDebitCard(config.get("virtualDebitCard").getAsBoolean());
}
}
@@ -0,0 +1,30 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.savings.domain;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface SavingsAccountFacilityConfigRepository extends JpaRepository<SavingsAccountFacilityConfig, Long> {
@Query("SELECT fc FROM SavingsAccountFacilityConfig fc WHERE fc.savingsAccount.id = :accountId")
Optional<SavingsAccountFacilityConfig> findBySavingsAccountId(@Param("accountId") Long accountId);
}
@@ -0,0 +1,81 @@
/**
* 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.domain;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import java.math.BigDecimal;
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
@Entity
@Table(name = "m_savings_account_joint_holders")
public class SavingsAccountJointHolder extends AbstractPersistableCustom<Long> {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "savings_account_id", nullable = false)
private SavingsAccount savingsAccount;
@Column(name = "client_id")
private Long clientId;
@Column(name = "cif_number", length = 50)
private String cifNumber;
@Column(name = "display_name", length = 200)
private String displayName;
@Column(name = "share_percentage", precision = 5, scale = 2)
private BigDecimal sharePercentage;
@Column(name = "signing_authority", length = 100)
private String signingAuthority;
@Column(name = "role", length = 100)
private String role;
@Column(name = "is_primary")
private boolean primary = false;
protected SavingsAccountJointHolder() {}
public SavingsAccountJointHolder(SavingsAccount account, Long clientId, String cifNumber,
String displayName, BigDecimal sharePercentage, String signingAuthority, String role, boolean primary) {
this.savingsAccount = account;
this.clientId = clientId;
this.cifNumber = cifNumber;
this.displayName = displayName;
this.sharePercentage = sharePercentage;
this.signingAuthority = signingAuthority;
this.role = role;
this.primary = primary;
}
public SavingsAccount getSavingsAccount() { return savingsAccount; }
public Long getClientId() { return clientId; }
public String getCifNumber() { return cifNumber; }
public String getDisplayName() { return displayName; }
public BigDecimal getSharePercentage() { return sharePercentage; }
public String getSigningAuthority() { return signingAuthority; }
public String getRole() { return role; }
public boolean isPrimary() { return primary; }
}
@@ -32,4 +32,5 @@
<include file="parts/2007_add_interest_calculation_type_option.xml" relativeToChangelogFile="true" />
<include file="parts/2008_add_other_gl_mappings_to_savings_product.xml" relativeToChangelogFile="true" />
<include file="parts/2009_add_gl_account_id_to_savings_product.xml" relativeToChangelogFile="true" />
<include file="parts/2010_add_savings_account_cbs_fields.xml" relativeToChangelogFile="true" />
</databaseChangeLog>
@@ -0,0 +1,174 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. This file is licensed under the Apache License, Version 2.0.
-->
<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">
<!-- CBS extended fields on m_savings_account -->
<changeSet author="fineract" id="2010-add-savings-account-cbs-fields">
<addColumn tableName="m_savings_account">
<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>
<column name="weaker_section" type="VARCHAR(100)">
<constraints nullable="true"/>
</column>
<column name="guardian_name" type="VARCHAR(200)">
<constraints nullable="true"/>
</column>
<column name="guardian_cif_number" type="VARCHAR(50)">
<constraints nullable="true"/>
</column>
<column name="guardian_relationship" type="VARCHAR(100)">
<constraints nullable="true"/>
</column>
<column name="minor_date_of_birth" type="DATE">
<constraints nullable="true"/>
</column>
<column name="guardian_client_id" type="BIGINT">
<constraints nullable="true"/>
</column>
<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>
<column name="nominee_data" type="TEXT">
<constraints nullable="true"/>
</column>
<column name="linked_account_id" type="BIGINT">
<constraints nullable="true"/>
</column>
<column name="linked_account_type" type="VARCHAR(20)">
<constraints nullable="true"/>
</column>
<column name="linked_account_no" type="VARCHAR(50)">
<constraints nullable="true"/>
</column>
</addColumn>
</changeSet>
<!-- Facility config table for savings accounts -->
<changeSet author="fineract" id="2010-create-savings-account-facility-config">
<createTable tableName="m_savings_account_facility_config">
<column name="id" type="BIGINT" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="savings_account_id" type="BIGINT">
<constraints nullable="false" unique="true"
foreignKeyName="fk_sa_facility_config_account"
references="m_savings_account(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="created_date" type="DATETIME">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
<!-- Joint holders table for savings accounts -->
<changeSet author="fineract" id="2010-create-savings-account-joint-holders">
<createTable tableName="m_savings_account_joint_holders">
<column name="id" type="BIGINT" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="savings_account_id" type="BIGINT">
<constraints nullable="false"
foreignKeyName="fk_sa_joint_holder_account"
references="m_savings_account(id)"/>
</column>
<column name="client_id" type="BIGINT">
<constraints nullable="true"/>
</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>
</changeSet>
</databaseChangeLog>
@@ -112,6 +112,8 @@
<class>org.apache.fineract.portfolio.savings.domain.SavingsProductDepositLimitKyc</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsProductFacilityConfig</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsProductFacilityLimit</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsAccountFacilityConfig</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsAccountJointHolder</class>
<!-- Charge Module Entities -->
<class>org.apache.fineract.portfolio.charge.domain.Charge</class>