Add CIF number, Occupation Category & Occupation fields to Client module

- Added mandatory unique CIF number (auto-generated as CIF+padded ID)
- Added Occupation Category dropdown (6 categories: Salaried, Business, Professional, Agriculture, Student, Others)
- Added Occupation dropdown (54 occupations mapped to categories)
- Both stored in m_code/m_code_value tables (same pattern as Gender)
- Visible in client create/update API and personal data view
- Includes Liquibase migrations 0227 & 0228
- Added Postman collection for User Management APIs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Aditya
2026-03-20 18:51:26 +05:30
co-authored by Claude Opus 4.6
parent ba5365d4af
commit 90c21d40c1
12 changed files with 1116 additions and 75 deletions
@@ -245,4 +245,6 @@
<include file="parts/0224_add_mobile_lookup_log.xml" relativeToChangelogFile="true"/>
<include file="parts/0225_add_current_account_support.xml" relativeToChangelogFile="true"/>
<include file="parts/0226_add_cfcfrms_tables.xml" relativeToChangelogFile="true"/>
<include file="parts/0227_add_client_cif_number.xml" relativeToChangelogFile="true"/>
<include file="parts/0228_add_occupation_fields.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>
@@ -0,0 +1,58 @@
<?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. 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.
-->
<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.13.xsd">
<changeSet author="fineract" id="0227-1">
<preConditions onFail="MARK_RAN">
<not><columnExists tableName="m_client" columnName="cif_number"/></not>
</preConditions>
<addColumn tableName="m_client">
<column name="cif_number" type="VARCHAR(20)">
<constraints nullable="true" />
</column>
</addColumn>
</changeSet>
<changeSet author="fineract" id="0227-2">
<preConditions onFail="MARK_RAN">
<columnExists tableName="m_client" columnName="cif_number"/>
</preConditions>
<sql>UPDATE m_client SET cif_number = CONCAT('CIF', LPAD(CAST(id AS VARCHAR), 10, '0')) WHERE cif_number IS NULL</sql>
</changeSet>
<changeSet author="fineract" id="0227-3">
<preConditions onFail="MARK_RAN">
<columnExists tableName="m_client" columnName="cif_number"/>
</preConditions>
<addNotNullConstraint tableName="m_client" columnName="cif_number" columnDataType="VARCHAR(20)" />
</changeSet>
<changeSet author="fineract" id="0227-4">
<preConditions onFail="MARK_RAN">
<not><indexExists indexName="cif_number_UNIQUE"/></not>
</preConditions>
<addUniqueConstraint tableName="m_client" columnNames="cif_number" constraintName="cif_number_UNIQUE" />
</changeSet>
</databaseChangeLog>
@@ -0,0 +1,167 @@
<?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. 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.
-->
<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.13.xsd">
<!-- ==================== Add OccupationCategory code ==================== -->
<changeSet author="fineract" id="0228-1">
<preConditions onFail="MARK_RAN">
<sqlCheck expectedResult="0">SELECT COUNT(*) FROM m_code WHERE code_name = 'OccupationCategory'</sqlCheck>
</preConditions>
<insert tableName="m_code">
<column name="code_name" value="OccupationCategory"/>
<column name="is_system_defined" valueBoolean="true"/>
</insert>
</changeSet>
<changeSet author="fineract" id="0228-2">
<preConditions onFail="MARK_RAN">
<sqlCheck expectedResult="0">SELECT COUNT(*) FROM m_code_value WHERE code_id = (SELECT id FROM m_code WHERE code_name = 'OccupationCategory')</sqlCheck>
</preConditions>
<sql>
INSERT INTO m_code_value (code_id, code_value, order_position, is_active, is_mandatory)
SELECT id, val, pos, true, false FROM m_code
CROSS JOIN (VALUES
('Salaried / Service', 1),
('Business / Self Employed', 2),
('Professional', 3),
('Agriculture', 4),
('Student / Non-Earning', 5),
('Others', 6)
) AS t(val, pos)
WHERE code_name = 'OccupationCategory';
</sql>
</changeSet>
<!-- ==================== Add Occupation code ==================== -->
<changeSet author="fineract" id="0228-3">
<preConditions onFail="MARK_RAN">
<sqlCheck expectedResult="0">SELECT COUNT(*) FROM m_code WHERE code_name = 'Occupation'</sqlCheck>
</preConditions>
<insert tableName="m_code">
<column name="code_name" value="Occupation"/>
<column name="is_system_defined" valueBoolean="true"/>
</insert>
</changeSet>
<changeSet author="fineract" id="0228-4">
<preConditions onFail="MARK_RAN">
<sqlCheck expectedResult="0">SELECT COUNT(*) FROM m_code_value WHERE code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')</sqlCheck>
</preConditions>
<sql>
INSERT INTO m_code_value (code_id, code_value, order_position, is_active, is_mandatory)
SELECT id, val, pos, true, false FROM m_code
CROSS JOIN (VALUES
('Government Employee', 1),
('Public Sector Undertaking (PSU) Employee', 2),
('Private Sector Employee', 3),
('Defence / Armed Forces Personnel', 4),
('Police / Paramilitary', 5),
('Teacher / Professor', 6),
('Doctor (Salaried)', 7),
('Engineer (Salaried)', 8),
('Bank Employee', 9),
('Railway Employee', 10),
('Business Owner / Proprietor', 11),
('Trader / Merchant', 12),
('Manufacturer', 13),
('Contractor', 14),
('Real Estate / Property Dealer', 15),
('Retailer', 16),
('Wholesaler', 17),
('Importer / Exporter', 18),
('Commission Agent', 19),
('Transport / Logistics Owner', 20),
('Doctor (Private Practice)', 21),
('Lawyer / Advocate', 22),
('Chartered Accountant', 23),
('Company Secretary', 24),
('Architect', 25),
('Consultant', 26),
('Engineer (Self Employed)', 27),
('IT Professional / Freelancer', 28),
('Financial Advisor', 29),
('Auditor', 30),
('Farmer (Own Land)', 31),
('Tenant Farmer', 32),
('Agricultural Labourer', 33),
('Horticulture / Floriculture', 34),
('Dairy / Animal Husbandry', 35),
('Fisherman', 36),
('Poultry Farmer', 37),
('Agri Allied Activities', 38),
('Student', 39),
('Housewife / Homemaker', 40),
('Dependent / Minor', 41),
('Unemployed', 42),
('Retired (Pension)', 43),
('Retired (Non-Pension)', 44),
('NRI (Non-Resident Indian)', 45),
('PIO / OCI', 46),
('Politician / Elected Representative', 47),
('Religious / Trust Worker', 48),
('NGO / Social Worker', 49),
('Artisan / Craftsman', 50),
('Labourer / Daily Wage', 51),
('Domestic Worker', 52),
('Driver / Operator', 53),
('Others', 54)
) AS t(val, pos)
WHERE code_name = 'Occupation';
</sql>
</changeSet>
<!-- ==================== Add columns to m_client table ==================== -->
<changeSet author="fineract" id="0228-5">
<preConditions onFail="MARK_RAN">
<not><columnExists tableName="m_client" columnName="occupation_category_cv_id"/></not>
</preConditions>
<addColumn tableName="m_client">
<column name="occupation_category_cv_id" type="BIGINT">
<constraints nullable="true" />
</column>
<column name="occupation_cv_id" type="BIGINT">
<constraints nullable="true" />
</column>
</addColumn>
</changeSet>
<changeSet author="fineract" id="0228-6">
<preConditions onFail="MARK_RAN">
<not><foreignKeyConstraintExists foreignKeyName="FK_m_client_occupation_category_cv_id"/></not>
</preConditions>
<addForeignKeyConstraint baseTableName="m_client" baseColumnNames="occupation_category_cv_id"
referencedTableName="m_code_value" referencedColumnNames="id"
constraintName="FK_m_client_occupation_category_cv_id" />
</changeSet>
<changeSet author="fineract" id="0228-7">
<preConditions onFail="MARK_RAN">
<not><foreignKeyConstraintExists foreignKeyName="FK_m_client_occupation_cv_id"/></not>
</preConditions>
<addForeignKeyConstraint baseTableName="m_client" baseColumnNames="occupation_cv_id"
referencedTableName="m_code_value" referencedColumnNames="id"
constraintName="FK_m_client_occupation_cv_id" />
</changeSet>
</databaseChangeLog>