feat: multi-nominee support, duplicate validation, and FD/RD required fields
Account Creation Enhancements: - Added multi-nominee support for SB, CA, FD, RD accounts (nominees[] array) - Backend: saveNomineesIfPresent() validates total share <= 100% before saving - Added 'nominees' to parameter whitelists (SavingsAccountConstant, DepositsApiConstants) Duplicate Validation Fixes: - SB/FD/RD: Fixed duplicate externalId error handler to walk full exception cause chain (EclipseLink wraps PSQLException deep) — now matches constraint 'm_savings_account_external_id_key' and returns proper 400 error - CA: Added try-catch around both saveAndFlush calls for duplicate externalId (constraint: ca_unq_external_id) with throwIfDuplicateExternalId() helper - CA: Added duplicate product check — blocks creating same product twice for client - SB/FD/RD: Added JpaSystemException handling via getAllCauseMessages() helper Current Account (CA) Improvements: - CurrentAccount entity: added @UniqueConstraint for external_id (ca_unq_external_id) - CurrentAccountRepository: added countActiveByClientAndProduct() JPQL query - Liquibase 0298: unique constraint on m_current_account.external_id FD/RD Required Field Validation (Backend): - DepositAccountDataValidator: depositPeriod now required for RD (was FD-only) - DepositAccountDataValidator: mandatoryRecommendedDepositAmount now notNull+positive for RD - DepositAccountDataValidator: customerSegment now required (notBlank) for both FD and RD Liquibase Migrations: - 0297: fix unique nominee per account constraint - 0298: unique external_id on m_current_account - 2014: add is_mandatory column to m_savings_account_joint_holders Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
9d67afec3e
commit
cc0ccbb461
+1
-1
@@ -46,7 +46,7 @@ public class SavingsAccountConstant extends SavingsApiConstants {
|
||||
guardianNameParamName, guardianCifNumberParamName, guardianRelationshipParamName,
|
||||
guardianClientIdParamName, minorDateOfBirthParamName,
|
||||
introducerIdParamName, introducerNameParamName, introducerCifNumberParamName,
|
||||
nomineeParamName, linkedAccountIdParamName, linkedAccountTypeParamName, linkedAccountNoParamName,
|
||||
nomineeParamName, "nominees", linkedAccountIdParamName, linkedAccountTypeParamName, linkedAccountNoParamName,
|
||||
accountFacilityConfigParamName, jointHoldersParamName,
|
||||
balanceSwapOptionParamName, msmeParamName, autoDebitFacilityParamName));
|
||||
|
||||
|
||||
+3
@@ -56,6 +56,9 @@ public interface SavingsAccountRepository extends JpaRepository<SavingsAccount,
|
||||
@Query("select case when (count (saving) > 0) then 'true' else 'false' end from SavingsAccount saving where saving.client.id = :clientId and saving.status in (100,200,300,303,304)")
|
||||
boolean doNonClosedSavingAccountsExistForClient(@Param("clientId") Long clientId);
|
||||
|
||||
@Query("SELECT COUNT(sa) FROM SavingsAccount sa WHERE sa.client.id = :clientId AND sa.product.id = :productId AND sa.status IN (100, 200, 300, 303, 304)")
|
||||
long countActiveAccountsByClientAndProduct(@Param("clientId") Long clientId, @Param("productId") Long productId);
|
||||
|
||||
@Query("select sa from SavingsAccount sa where sa.client.id is null and sa.group.id = :groupId")
|
||||
List<SavingsAccount> findByGroupId(@Param("groupId") Long groupId);
|
||||
|
||||
|
||||
+4
@@ -181,4 +181,8 @@ public class SavingsAccountRepositoryWrapper {
|
||||
public List<Long> findLoanIdsByStatusId(Integer status) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public long countActiveAccountsByClientAndProduct(final Long clientId, final Long productId) {
|
||||
return this.repository.countActiveAccountsByClientAndProduct(clientId, productId);
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -36,4 +36,5 @@
|
||||
<include file="parts/2011_add_facility_charge_mapping.xml" relativeToChangelogFile="true" />
|
||||
<include file="parts/2012_add_current_account_permissions.xml" relativeToChangelogFile="true" />
|
||||
<include file="parts/2013_add_missing_current_account_columns.xml" relativeToChangelogFile="true" />
|
||||
<include file="parts/2014_add_is_mandatory_to_joint_holders.xml" relativeToChangelogFile="true" />
|
||||
</databaseChangeLog>
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
<?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.
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||
|
||||
<changeSet id="2014_add_is_mandatory_to_joint_holders" author="CBS">
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<tableExists tableName="m_savings_account_joint_holders"/>
|
||||
<not><columnExists tableName="m_savings_account_joint_holders" columnName="is_mandatory"/></not>
|
||||
</preConditions>
|
||||
<addColumn tableName="m_savings_account_joint_holders">
|
||||
<column name="is_mandatory" type="BOOLEAN" defaultValueBoolean="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
Reference in New Issue
Block a user