feat(chequebook): add cheque book module with Maker-Checker workflow
Adds cheque series, stock lot/transfer, cheque book issuance, stop-payment/lost/cancel-leaf actions, and pending-request approval APIs with Maker-Checker command handlers and liquibase changelogs.
This commit is contained in:
@@ -46,7 +46,7 @@ fineract.security.oauth2.client.registrations.frontend-client.require-authorizat
|
||||
fineract.tenant.host=${FINERACT_DEFAULT_TENANTDB_HOSTNAME:localhost}
|
||||
fineract.tenant.port=${FINERACT_DEFAULT_TENANTDB_PORT:5432}
|
||||
fineract.tenant.username=${FINERACT_DEFAULT_TENANTDB_UID:postgres}
|
||||
fineract.tenant.password=${FINERACT_DEFAULT_TENANTDB_PWD:Keshav@898966}
|
||||
fineract.tenant.password=${FINERACT_DEFAULT_TENANTDB_PWD:313863}
|
||||
fineract.tenant.parameters=${FINERACT_DEFAULT_TENANTDB_CONN_PARAMS:}
|
||||
fineract.tenant.timezone=${FINERACT_DEFAULT_TENANTDB_TIMEZONE:Asia/Kolkata}
|
||||
fineract.tenant.identifier=${FINERACT_DEFAULT_TENANTDB_IDENTIFIER:default}
|
||||
@@ -407,7 +407,7 @@ server.tomcat.mbeanregistry.enabled=${FINERACT_SERVER_TOMCAT_MBEANREGISTRY_ENABL
|
||||
spring.datasource.hikari.driverClassName=${FINERACT_HIKARI_DRIVER_SOURCE_CLASS_NAME:org.postgresql.Driver}
|
||||
spring.datasource.hikari.jdbcUrl=${FINERACT_HIKARI_JDBC_URL:jdbc:postgresql://localhost:5432/fineract_tenants}
|
||||
spring.datasource.hikari.username=${FINERACT_HIKARI_USERNAME:postgres}
|
||||
spring.datasource.hikari.password=${FINERACT_HIKARI_PASSWORD:Keshav@898966}
|
||||
spring.datasource.hikari.password=${FINERACT_HIKARI_PASSWORD:313863}
|
||||
spring.datasource.hikari.minimumIdle=${FINERACT_HIKARI_MINIMUM_IDLE:3}
|
||||
spring.datasource.hikari.maximumPoolSize=${FINERACT_HIKARI_MAXIMUM_POOL_SIZE:10}
|
||||
spring.datasource.hikari.idleTimeout=${FINERACT_HIKARI_IDLE_TIMEOUT:60000}
|
||||
@@ -689,4 +689,4 @@ fineract.email.from-name=${FINERACT_EMAIL_FROM_NAME:CBSnexora}
|
||||
fineract.email.support-address=${FINERACT_EMAIL_SUPPORT_ADDRESS:support@cbsnexora.com}
|
||||
|
||||
# Frontend base URL — used for email links (voting, etc.)
|
||||
cbs.frontend.base-url=${CBS_FRONTEND_BASE_URL:http://localhost:4200}
|
||||
cbs.frontend.base-url=${CBS_FRONTEND_BASE_URL:https://cbs.godemo.in}
|
||||
|
||||
@@ -399,4 +399,13 @@
|
||||
<include file="parts/0340_add_terminate_true_to_savings_and_current_account.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0368_catchup_savings_account_columns.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0369_catchup_saving_product_temp_table.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0379_chequebook_module.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0380_cheque_series_account_type.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0381_chequebook_no_of_books.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0382_chequeleaf_used_status.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0383_cheque_series_no_both.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0384_chequebook_maker_checker.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0385_chequebook_pending_requests.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0386_enable_global_maker_checker.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0387_chequeleaf_serial_unique_per_lot.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
|
||||
+287
@@ -0,0 +1,287 @@
|
||||
<?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">
|
||||
|
||||
<!--
|
||||
Cheque Book Inventory module: stationery master, a unified stock ledger (HO receipt and branch
|
||||
transfer-in are the same "range of leaf serials sitting at an office, with a drawdown cursor"
|
||||
concept), issuance to an account (Savings or Current — both exist in this codebase and are not
|
||||
interchangeable, so a discriminator column is used instead of a JPA relation), and per-leaf
|
||||
tracking (materialized at issuance, OR directly against a stock lot when unissued stock is
|
||||
reported lost/stolen — see m_cheque_leaf.cheque_book_id being nullable).
|
||||
|
||||
Scope is deliberately limited to inventory + stop-payment/hotlisting. It does not model RBI's
|
||||
Positive Pay System, "used/cleared" leaf status, or automatic cheque-validity staleness — all three
|
||||
require clearing/presentment integration this CBS does not have; see the design plan for why
|
||||
faking any of them would be actively wrong rather than merely incomplete.
|
||||
|
||||
Every changeSet is guarded so this migration is a safe no-op where already applied.
|
||||
-->
|
||||
|
||||
<changeSet id="0379-cheque-series" author="CBS">
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<not><tableExists tableName="m_cheque_series"/></not>
|
||||
</preConditions>
|
||||
<createTable tableName="m_cheque_series">
|
||||
<column name="id" type="BIGINT" autoIncrement="true">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="series_code" type="VARCHAR(20)">
|
||||
<constraints nullable="false" unique="true" uniqueConstraintName="uk_cheque_series_code"/>
|
||||
</column>
|
||||
<column name="name" type="VARCHAR(100)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="leaves_per_book" type="INTEGER">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="cts_compliant" type="BOOLEAN" defaultValueBoolean="true">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="reorder_level" type="INTEGER"/>
|
||||
<column name="is_active" type="BOOLEAN" defaultValueBoolean="true">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="created_by" type="BIGINT"/>
|
||||
<column name="created_on" type="TIMESTAMP WITH TIME ZONE"/>
|
||||
</createTable>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="0379-cheque-stock-lot" author="CBS">
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<not><tableExists tableName="m_cheque_stock_lot"/></not>
|
||||
</preConditions>
|
||||
<createTable tableName="m_cheque_stock_lot">
|
||||
<column name="id" type="BIGINT" autoIncrement="true">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="series_id" type="BIGINT">
|
||||
<constraints nullable="false" foreignKeyName="fk_cheque_stock_lot_series" references="m_cheque_series(id)"/>
|
||||
</column>
|
||||
<column name="office_id" type="BIGINT">
|
||||
<constraints nullable="false" foreignKeyName="fk_cheque_stock_lot_office" references="m_office(id)"/>
|
||||
</column>
|
||||
<column name="range_start" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="range_end" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="next_serial_no" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="source" type="VARCHAR(20)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="source_ref_id" type="BIGINT"/>
|
||||
<column name="batch_ref" type="VARCHAR(100)"/>
|
||||
<column name="status" type="VARCHAR(25)" defaultValue="AVAILABLE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="created_by" type="BIGINT"/>
|
||||
<column name="created_on" type="TIMESTAMP WITH TIME ZONE"/>
|
||||
<column name="received_by" type="BIGINT"/>
|
||||
<column name="received_on" type="TIMESTAMP WITH TIME ZONE"/>
|
||||
<column name="version" type="INTEGER" defaultValueNumeric="0"/>
|
||||
</createTable>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="0379-cheque-stock-transfer" author="CBS">
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<not><tableExists tableName="m_cheque_stock_transfer"/></not>
|
||||
</preConditions>
|
||||
<createTable tableName="m_cheque_stock_transfer">
|
||||
<column name="id" type="BIGINT" autoIncrement="true">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="series_id" type="BIGINT">
|
||||
<constraints nullable="false" foreignKeyName="fk_cheque_stock_transfer_series" references="m_cheque_series(id)"/>
|
||||
</column>
|
||||
<column name="from_office_id" type="BIGINT">
|
||||
<constraints nullable="false" foreignKeyName="fk_cheque_stock_transfer_from_office" references="m_office(id)"/>
|
||||
</column>
|
||||
<column name="to_office_id" type="BIGINT">
|
||||
<constraints nullable="false" foreignKeyName="fk_cheque_stock_transfer_to_office" references="m_office(id)"/>
|
||||
</column>
|
||||
<column name="from_lot_id" type="BIGINT">
|
||||
<constraints nullable="false" foreignKeyName="fk_cheque_stock_transfer_from_lot" references="m_cheque_stock_lot(id)"/>
|
||||
</column>
|
||||
<column name="to_lot_id" type="BIGINT">
|
||||
<constraints nullable="false" foreignKeyName="fk_cheque_stock_transfer_to_lot" references="m_cheque_stock_lot(id)"/>
|
||||
</column>
|
||||
<column name="range_start" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="range_end" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="total_leaves" type="INTEGER">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="dispatch_date" type="DATE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="status" type="VARCHAR(20)" defaultValue="DISPATCHED">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="received_date" type="DATE"/>
|
||||
<column name="dispatched_by" type="BIGINT"/>
|
||||
<column name="received_by" type="BIGINT"/>
|
||||
<column name="created_on" type="TIMESTAMP WITH TIME ZONE"/>
|
||||
</createTable>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="0379-cheque-book" author="CBS">
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<not><tableExists tableName="m_cheque_book"/></not>
|
||||
</preConditions>
|
||||
<createTable tableName="m_cheque_book">
|
||||
<column name="id" type="BIGINT" autoIncrement="true">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="account_type" type="VARCHAR(10)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="account_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="office_id" type="BIGINT">
|
||||
<constraints nullable="false" foreignKeyName="fk_cheque_book_office" references="m_office(id)"/>
|
||||
</column>
|
||||
<column name="series_id" type="BIGINT">
|
||||
<constraints nullable="true" foreignKeyName="fk_cheque_book_series" references="m_cheque_series(id)"/>
|
||||
</column>
|
||||
<column name="requested_date" type="DATE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="requested_by" type="BIGINT"/>
|
||||
<column name="no_of_leaves_requested" type="INTEGER">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="status" type="VARCHAR(20)" defaultValue="REQUESTED">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="issue_date" type="DATE"/>
|
||||
<column name="issued_by" type="BIGINT"/>
|
||||
<column name="lot_id" type="BIGINT">
|
||||
<constraints nullable="true" foreignKeyName="fk_cheque_book_lot" references="m_cheque_stock_lot(id)"/>
|
||||
</column>
|
||||
<column name="range_start" type="BIGINT"/>
|
||||
<column name="range_end" type="BIGINT"/>
|
||||
<column name="total_leaves" type="INTEGER"/>
|
||||
<column name="rejection_reason" type="VARCHAR(500)"/>
|
||||
<column name="collection_acknowledged" type="BOOLEAN" defaultValueBoolean="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="collected_date" type="DATE"/>
|
||||
<column name="collected_by" type="BIGINT"/>
|
||||
<column name="created_on" type="TIMESTAMP WITH TIME ZONE"/>
|
||||
<column name="version" type="INTEGER" defaultValueNumeric="0"/>
|
||||
</createTable>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="0379-cheque-leaf" author="CBS">
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<not><tableExists tableName="m_cheque_leaf"/></not>
|
||||
</preConditions>
|
||||
<createTable tableName="m_cheque_leaf">
|
||||
<column name="id" type="BIGINT" autoIncrement="true">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="cheque_book_id" type="BIGINT">
|
||||
<constraints nullable="true" foreignKeyName="fk_cheque_leaf_book" references="m_cheque_book(id)"/>
|
||||
</column>
|
||||
<column name="lot_id" type="BIGINT">
|
||||
<constraints nullable="false" foreignKeyName="fk_cheque_leaf_lot" references="m_cheque_stock_lot(id)"/>
|
||||
</column>
|
||||
<column name="leaf_serial_no" type="BIGINT">
|
||||
<constraints nullable="false" unique="true" uniqueConstraintName="uk_cheque_leaf_serial_no"/>
|
||||
</column>
|
||||
<column name="leaf_seq_no" type="INTEGER"/>
|
||||
<column name="status" type="VARCHAR(20)" defaultValue="ACTIVE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="stop_reason" type="VARCHAR(500)"/>
|
||||
<column name="stopped_by" type="BIGINT"/>
|
||||
<column name="stopped_on" type="TIMESTAMP WITH TIME ZONE"/>
|
||||
<column name="lost_reason" type="VARCHAR(500)"/>
|
||||
<column name="lost_reported_by" type="BIGINT"/>
|
||||
<column name="lost_reported_on" type="TIMESTAMP WITH TIME ZONE"/>
|
||||
<column name="cancelled_reason" type="VARCHAR(500)"/>
|
||||
<column name="cancelled_by" type="BIGINT"/>
|
||||
<column name="cancelled_on" type="TIMESTAMP WITH TIME ZONE"/>
|
||||
<column name="created_on" type="TIMESTAMP WITH TIME ZONE"/>
|
||||
</createTable>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="0379-permissions" author="CBS" runOnChange="false">
|
||||
<sql>
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'READ_CHEQUESERIES', 'CHEQUESERIES', 'READ', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'READ_CHEQUESERIES');
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'CREATE_CHEQUESERIES', 'CHEQUESERIES', 'CREATE', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'CREATE_CHEQUESERIES');
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'UPDATE_CHEQUESERIES', 'CHEQUESERIES', 'UPDATE', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'UPDATE_CHEQUESERIES');
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'DELETE_CHEQUESERIES', 'CHEQUESERIES', 'DELETE', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'DELETE_CHEQUESERIES');
|
||||
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'READ_CHEQUESTOCKLOT', 'CHEQUESTOCKLOT', 'READ', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'READ_CHEQUESTOCKLOT');
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'CREATE_CHEQUESTOCKLOT', 'CHEQUESTOCKLOT', 'CREATE', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'CREATE_CHEQUESTOCKLOT');
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'REPORTLOST_CHEQUESTOCKLOT', 'CHEQUESTOCKLOT', 'REPORTLOST', true
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'REPORTLOST_CHEQUESTOCKLOT');
|
||||
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'CREATE_CHEQUESTOCKTRANSFER', 'CHEQUESTOCKTRANSFER', 'CREATE', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'CREATE_CHEQUESTOCKTRANSFER');
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'RECEIVE_CHEQUESTOCKTRANSFER', 'CHEQUESTOCKTRANSFER', 'RECEIVE', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'RECEIVE_CHEQUESTOCKTRANSFER');
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'REJECT_CHEQUESTOCKTRANSFER', 'CHEQUESTOCKTRANSFER', 'REJECT', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'REJECT_CHEQUESTOCKTRANSFER');
|
||||
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'READ_CHEQUEBOOK', 'CHEQUEBOOK', 'READ', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'READ_CHEQUEBOOK');
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'CREATE_CHEQUEBOOK', 'CHEQUEBOOK', 'CREATE', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'CREATE_CHEQUEBOOK');
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'ISSUE_CHEQUEBOOK', 'CHEQUEBOOK', 'ISSUE', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'ISSUE_CHEQUEBOOK');
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'REJECT_CHEQUEBOOK', 'CHEQUEBOOK', 'REJECT', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'REJECT_CHEQUEBOOK');
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'WITHDRAW_CHEQUEBOOK', 'CHEQUEBOOK', 'WITHDRAW', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'WITHDRAW_CHEQUEBOOK');
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'CANCELLEAF_CHEQUEBOOK', 'CHEQUEBOOK', 'CANCELLEAF', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'CANCELLEAF_CHEQUEBOOK');
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'STOPPAYMENT_CHEQUEBOOK', 'CHEQUEBOOK', 'STOPPAYMENT', true
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'STOPPAYMENT_CHEQUEBOOK');
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'REVOKESTOPPAYMENT_CHEQUEBOOK', 'CHEQUEBOOK', 'REVOKESTOPPAYMENT', true
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'REVOKESTOPPAYMENT_CHEQUEBOOK');
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'REPORTLOST_CHEQUEBOOK', 'CHEQUEBOOK', 'REPORTLOST', true
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'REPORTLOST_CHEQUEBOOK');
|
||||
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'heading_menu', 'MENU_CHEQUEBOOK', 'MENU', 'CHEQUEBOOK', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'MENU_CHEQUEBOOK');
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
<?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">
|
||||
|
||||
<!--
|
||||
Segregate cheque stationery by account scheme (Savings vs Current). Real banks stock physically
|
||||
different cheque books for SB and CA accounts, so each series is tagged SAVINGS / CURRENT / BOTH.
|
||||
Existing rows default to BOTH (backward compatible: any series stays issuable to any account type
|
||||
until an operator narrows it). Issuance is validated against this at issue time.
|
||||
-->
|
||||
|
||||
<changeSet id="0380-cheque-series-applicable-account-type" author="CBS">
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<not><columnExists tableName="m_cheque_series" columnName="applicable_account_type"/></not>
|
||||
</preConditions>
|
||||
<addColumn tableName="m_cheque_series">
|
||||
<column name="applicable_account_type" type="VARCHAR(10)" defaultValue="BOTH">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
<?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">
|
||||
|
||||
<!--
|
||||
Cheque books are requested and issued in whole BOOKS of a fixed denomination (25-leaf, 50-leaf, ...),
|
||||
not in an arbitrary leaf count. A requisition captures how many books the customer wants; the actual
|
||||
leaves handed over are derived at issue time as books x series.leavesPerBook, and that leaf count plus
|
||||
the per-leaf serials are persisted. no_of_leaves_requested becomes optional/legacy.
|
||||
-->
|
||||
|
||||
<changeSet id="0381-cheque-book-no-of-books" author="CBS">
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<not><columnExists tableName="m_cheque_book" columnName="no_of_books"/></not>
|
||||
</preConditions>
|
||||
<addColumn tableName="m_cheque_book">
|
||||
<column name="no_of_books" type="INTEGER" defaultValueNumeric="1">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="0381-cheque-book-leaves-requested-optional" author="CBS">
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<columnExists tableName="m_cheque_book" columnName="no_of_leaves_requested"/>
|
||||
</preConditions>
|
||||
<dropNotNullConstraint tableName="m_cheque_book" columnName="no_of_leaves_requested" columnDataType="INTEGER"/>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
<?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">
|
||||
|
||||
<!--
|
||||
A manually-recorded USED status for a cheque leaf. This CBS has no clearing/presentment integration,
|
||||
so the system cannot detect on its own when a specific leaf was honoured — a branch marks it USED
|
||||
after seeing it clear on the bank/clearing statement (the same manual-recording pattern already used
|
||||
for the settlement module's "actual bank settlement" entry, where automatic detection isn't feasible
|
||||
either). This is a record-keeping status, not a fraud control, so it is not maker-checker.
|
||||
-->
|
||||
|
||||
<changeSet id="0382-cheque-leaf-used-columns" author="CBS">
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<not><columnExists tableName="m_cheque_leaf" columnName="used_reason"/></not>
|
||||
</preConditions>
|
||||
<addColumn tableName="m_cheque_leaf">
|
||||
<column name="used_reason" type="VARCHAR(500)"/>
|
||||
<column name="used_by" type="BIGINT"/>
|
||||
<column name="used_on" type="TIMESTAMP WITH TIME ZONE"/>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="0382-permission" author="CBS" runOnChange="false">
|
||||
<sql>
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'MARKUSED_CHEQUEBOOK', 'CHEQUEBOOK', 'MARKUSED', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'MARKUSED_CHEQUEBOOK');
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
<?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">
|
||||
|
||||
<!--
|
||||
"BOTH" is removed as a cheque series applicability: every series must now be tagged explicitly as
|
||||
SAVINGS or CURRENT (real banks stock physically different stationery per scheme, so "applies to
|
||||
everything" was never a genuine stationery category). Any pre-existing BOTH-tagged row is narrowed
|
||||
to SAVINGS — an operator can re-create a CURRENT-tagged series if that stock is also needed there.
|
||||
-->
|
||||
|
||||
<changeSet id="0383-cheque-series-no-both-data" author="CBS" runOnChange="false">
|
||||
<sql>
|
||||
UPDATE m_cheque_series SET applicable_account_type = 'SAVINGS' WHERE applicable_account_type = 'BOTH';
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="0383-cheque-series-no-both-default" author="CBS">
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<columnExists tableName="m_cheque_series" columnName="applicable_account_type"/>
|
||||
</preConditions>
|
||||
<dropDefaultValue tableName="m_cheque_series" columnName="applicable_account_type"/>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<?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">
|
||||
|
||||
<!--
|
||||
Extend maker-checker to the three cheque-book creation actions (series master, stock receipt, book
|
||||
requisition) so every request now needs a second user's approval before it takes effect, matching
|
||||
the fraud-sensitive actions (stop-payment/report-lost/revoke) that already required it. No bespoke
|
||||
approval logic is needed - can_maker_checker=true on the permission row is all the generic
|
||||
command-processing pipeline needs; pending requests surface in the existing Checker Inbox screen.
|
||||
-->
|
||||
|
||||
<changeSet id="0384-chequebook-maker-checker" author="CBS" runOnChange="false">
|
||||
<sql>
|
||||
UPDATE m_permission SET can_maker_checker = true
|
||||
WHERE code IN ('CREATE_CHEQUESERIES', 'CREATE_CHEQUESTOCKLOT', 'CREATE_CHEQUEBOOK');
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
<?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">
|
||||
|
||||
<!--
|
||||
Bespoke maker-checker for the three cheque-book creation actions (series master, stock receipt, book
|
||||
requisition), mirroring the existing m_clerk_disbursement_request pattern rather than the native
|
||||
Fineract command-approval engine: the native engine's maker-checker hold is bypassed by any user
|
||||
whose role carries ALL_FUNCTIONS (Super user, Clerk in this tenant), which made it useless for this
|
||||
CBS's actual admin accounts. This table instead holds a request as PENDING with its raw request JSON;
|
||||
approval replays that JSON through the same creation logic used elsewhere in this module. The
|
||||
submitting user (maker) can never approve/reject their own request (enforced in code, not just by
|
||||
role) - any OTHER user with the same create permission can act as checker.
|
||||
-->
|
||||
|
||||
<changeSet id="0385-chequebook-pending-requests-table" author="CBS">
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<not><tableExists tableName="m_chequebook_pending_request"/></not>
|
||||
</preConditions>
|
||||
<createTable tableName="m_chequebook_pending_request">
|
||||
<column name="id" type="BIGSERIAL">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="request_type" type="VARCHAR(30)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="payload_json" type="TEXT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="status" type="VARCHAR(20)" defaultValue="PENDING">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="maker_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="maker_name" type="VARCHAR(150)"/>
|
||||
<column name="maker_username" type="VARCHAR(100)"/>
|
||||
<column name="submitted_on" type="TIMESTAMP WITH TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="checker_id" type="BIGINT"/>
|
||||
<column name="checker_name" type="VARCHAR(150)"/>
|
||||
<column name="checker_username" type="VARCHAR(100)"/>
|
||||
<column name="checked_on" type="TIMESTAMP WITH TIME ZONE"/>
|
||||
<column name="rejection_reason" type="VARCHAR(500)"/>
|
||||
<column name="created_resource_id" type="BIGINT"/>
|
||||
<column name="activity_log" type="TEXT"/>
|
||||
</createTable>
|
||||
<sql>CREATE INDEX IF NOT EXISTS idx_cbpr_status ON m_chequebook_pending_request(status)</sql>
|
||||
<sql>CREATE INDEX IF NOT EXISTS idx_cbpr_maker_id ON m_chequebook_pending_request(maker_id)</sql>
|
||||
<sql>CREATE INDEX IF NOT EXISTS idx_cbpr_submitted_on ON m_chequebook_pending_request(submitted_on)</sql>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="0385-chequebook-revert-native-maker-checker" author="CBS" runOnChange="false">
|
||||
<!-- the native engine's hold is replaced by this table's bespoke workflow for these three actions -->
|
||||
<sql>
|
||||
UPDATE m_permission SET can_maker_checker = false
|
||||
WHERE code IN ('CREATE_CHEQUESERIES', 'CREATE_CHEQUESTOCKLOT', 'CREATE_CHEQUEBOOK');
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="0385-chequebook-pending-request-permission" author="CBS" runOnChange="false">
|
||||
<sql>
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'READ_CHEQUEBOOKPENDINGREQUEST', 'CHEQUEBOOKPENDINGREQUEST', 'READ', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'READ_CHEQUEBOOKPENDINGREQUEST');
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'APPROVE_CHEQUEBOOKPENDINGREQUEST', 'CHEQUEBOOKPENDINGREQUEST', 'APPROVE', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'APPROVE_CHEQUEBOOKPENDINGREQUEST');
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'REJECT_CHEQUEBOOKPENDINGREQUEST', 'CHEQUEBOOKPENDINGREQUEST', 'REJECT', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'REJECT_CHEQUEBOOKPENDINGREQUEST');
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?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">
|
||||
|
||||
<!--
|
||||
Fineract holds a per-permission can_maker_checker flag AND a single global "maker-checker" switch in
|
||||
c_configuration - the global switch is checked FIRST (ConfigurationDomainServiceJpa.isMakerCheckerEnabledForTask),
|
||||
and if it is disabled, every maker-checker-eligible permission in the whole system is bypassed
|
||||
regardless of its own flag. It shipped disabled in this tenant, which meant the fraud-sensitive
|
||||
actions built earlier (stop-payment/report-lost/revoke) were never actually holding for approval
|
||||
either. Enabling it here turns on real maker-checker enforcement platform-wide, not just for the
|
||||
cheque-book module. NB: a user whose role carries ALL_FUNCTIONS or CHECKER_SUPER_USER (Super user,
|
||||
Clerk in this tenant) still bypasses the hold regardless of this switch - see AppUser.isCheckerSuperUser().
|
||||
-->
|
||||
|
||||
<changeSet id="0386-enable-global-maker-checker" author="CBS" runOnChange="false">
|
||||
<sql>
|
||||
UPDATE c_configuration SET enabled = true WHERE name = 'maker-checker';
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
<?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">
|
||||
|
||||
<!--
|
||||
leaf_serial_no was originally unique bank-wide, which matched the OLD global stock-numbering
|
||||
design. Per-series numbering (0383) intentionally lets two different series share a serial number
|
||||
(each is a separate stationery order from the press, numbered independently) - so a bare
|
||||
leaf_serial_no can no longer be unique on its own once real leaves are materialized for two series
|
||||
that happen to overlap. Uniqueness now needs to be scoped to the stock lot a leaf was drawn from
|
||||
(every lot belongs to exactly one series, and lots within one series never overlap), not the whole
|
||||
table.
|
||||
-->
|
||||
|
||||
<changeSet id="0387-chequeleaf-serial-unique-per-lot" author="CBS" runOnChange="false">
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<indexExists indexName="uk_cheque_leaf_serial_no"/>
|
||||
</preConditions>
|
||||
<dropUniqueConstraint tableName="m_cheque_leaf" constraintName="uk_cheque_leaf_serial_no"/>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="0387-chequeleaf-serial-unique-per-lot-add" author="CBS" runOnChange="false">
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<not>
|
||||
<indexExists indexName="uk_cheque_leaf_lot_serial_no"/>
|
||||
</not>
|
||||
</preConditions>
|
||||
<addUniqueConstraint tableName="m_cheque_leaf" columnNames="lot_id, leaf_serial_no"
|
||||
constraintName="uk_cheque_leaf_lot_serial_no"/>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
Reference in New Issue
Block a user