feat: denomination save+validation for all deposit types + cash exchange backend

- DenominationBreakdownWriter helper: validates breakdown total == amount and
  persists per-denomination rows; wired into current, FD and RD deposit flows
  (savings already had inline save) so all 4 deposit types now record the
  cash denomination breakdown.
- CIF on denomination rows now sourced from the client (getCifNumber) instead
  of the account external id.
- Allow denominationBreakdown param in the FD/RD transaction validator.
- Cash Exchange backend: m_cash_exchange + m_cash_exchange_detail tables,
  entities, repositories and JAX-RS API with received==given validation;
  registered the 0013 migration in changelog-tenant.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jaanu423
2026-05-27 18:36:00 +05:30
co-authored by Claude Opus 4.7
parent ee915e395a
commit 9a30ede278
15 changed files with 2355 additions and 1698 deletions
@@ -319,4 +319,5 @@
<include file="parts/0300_rename_fd_base_interest_rate_tables_to_cbs.xml" relativeToChangelogFile="true"/>
<include file="parts/0301_add_current_account_to_transfer_details.xml" relativeToChangelogFile="true"/>
<include file="parts/0012_denomination_master.xml" relativeToChangelogFile="true"/>
<include file="parts/0013_cash_exchange.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>
@@ -177,4 +177,28 @@
</addColumn>
</changeSet>
<!-- =====================================================================
Migration: Add txn_type, officer_id, officer_username to
m_savings_txn_denomination.
txn_type distinguishes DEPOSIT from WITHDRAWAL.
officer_id / officer_username record who performed the transaction.
===================================================================== -->
<changeSet id="savings_txn_denomination_add_txn_type_officer_001" author="CBS">
<addColumn tableName="m_savings_txn_denomination">
<column name="txn_type" type="VARCHAR(20)" defaultValue="DEPOSIT">
<constraints nullable="false"/>
</column>
<column name="officer_id" type="BIGINT"/>
<column name="officer_username" type="VARCHAR(100)"/>
</addColumn>
<createIndex tableName="m_savings_txn_denomination"
indexName="idx_savings_txn_denom_txntype">
<column name="txn_type"/>
</createIndex>
<createIndex tableName="m_savings_txn_denomination"
indexName="idx_savings_txn_denom_officer">
<column name="officer_id"/>
</createIndex>
</changeSet>
</databaseChangeLog>
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
<changeSet id="cash_exchange_table_001" author="CBS">
<createTable tableName="m_cash_exchange">
<column name="id" type="BIGINT" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="account_id" type="BIGINT"/>
<column name="account_no" type="VARCHAR(50)"/>
<column name="client_id" type="BIGINT"/>
<column name="exchange_amount" type="DECIMAL(19,6)">
<constraints nullable="false"/>
</column>
<column name="exchange_date" type="DATE"/>
<column name="note" type="VARCHAR(500)"/>
<column name="performed_by" type="BIGINT"/>
<column name="performed_by_username" type="VARCHAR(100)"/>
<column name="created_at" type="TIMESTAMP" defaultValueComputed="CURRENT_TIMESTAMP"/>
</createTable>
</changeSet>
<changeSet id="cash_exchange_detail_table_001" author="CBS">
<createTable tableName="m_cash_exchange_detail">
<column name="id" type="BIGINT" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="exchange_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="direction" type="VARCHAR(10)">
<constraints nullable="false"/>
</column>
<column name="denomination_id" type="BIGINT"/>
<column name="denomination_value" type="INT">
<constraints nullable="false"/>
</column>
<column name="count" type="INT">
<constraints nullable="false"/>
</column>
<column name="total_amount" type="DECIMAL(19,6)">
<constraints nullable="false"/>
</column>
</createTable>
<createIndex tableName="m_cash_exchange_detail" indexName="idx_cash_exchange_detail_eid">
<column name="exchange_id"/>
</createIndex>
</changeSet>
</databaseChangeLog>