CTR/STR report and Risk Category auto mark on bases of person occupation and anual salary enter
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-4) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, build-core) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, cucumber) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (progressive-loan, build-progressive-loan) (push) Canceled after 0s
Fineract Docker Builds / build (false, docker-compose-postgresql.yml, postgresql) (push) Canceled after 0s
Fineract Docker Builds / build (true, docker-compose.yml, mariadb) (push) Canceled after 0s
Fineract Documentation build / build (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 1 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 10 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 2 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 3 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 4 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 5 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 6 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 7 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 8 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 9 of 10) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-5) (push) Canceled after 0s
Fineract Liquibase Only mode - PostgreSQL / test (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with ActiveMQ (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with Kafka (push) Canceled after 0s

This commit is contained in:
2026-07-29 10:22:27 +05:30
parent 3c58bb231f
commit f45d5890ea
8 changed files with 601 additions and 0 deletions
@@ -0,0 +1,55 @@
/**
* 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.client.api;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.portfolio.client.data.KycRiskRuleData;
import org.apache.fineract.portfolio.client.service.KycRiskRulesReadPlatformService;
import org.springframework.stereotype.Component;
@Path("/v1/kyc/risk-rules")
@Component
@Tag(name = "KYC Risk Rules", description = "Retrieve database-driven master rules for client AML/CFT risk rating calculation.")
@RequiredArgsConstructor
public class KycRiskRulesApiResource {
private final PlatformSecurityContext context;
private final KycRiskRulesReadPlatformService readPlatformService;
private final DefaultToApiJsonSerializer<KycRiskRuleData> toApiJsonSerializer;
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Retrieve KYC risk rules", description = "Returns list of database-defined risk rules ordered by precedence.")
public String retrieveRiskRules() {
this.context.authenticatedUser();
final List<KycRiskRuleData> rules = this.readPlatformService.retrieveAllRules();
return this.toApiJsonSerializer.serialize(rules);
}
}
@@ -0,0 +1,133 @@
/**
* 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.client.data;
import java.io.Serializable;
import java.math.BigDecimal;
public final class KycRiskRuleData implements Serializable {
private static final long serialVersionUID = 1L;
private final Long id;
private final String ruleName;
private final Integer legalFormId;
private final Long occupationCategoryCvId;
private final String occupationCategoryName;
private final Long occupationCvId;
private final String occupationName;
private final BigDecimal minMonthlyIncome;
private final BigDecimal maxMonthlyIncome;
private final BigDecimal minAnnualIncome;
private final BigDecimal maxAnnualIncome;
private final BigDecimal minAnnualTurnover;
private final BigDecimal maxAnnualTurnover;
private final Integer riskCategory;
private final String reason;
private final Integer orderPosition;
public KycRiskRuleData(final Long id, final String ruleName, final Integer legalFormId,
final Long occupationCategoryCvId, final String occupationCategoryName,
final Long occupationCvId, final String occupationName,
final BigDecimal minMonthlyIncome, final BigDecimal maxMonthlyIncome,
final BigDecimal minAnnualIncome, final BigDecimal maxAnnualIncome,
final BigDecimal minAnnualTurnover, final BigDecimal maxAnnualTurnover,
final Integer riskCategory, final String reason, final Integer orderPosition) {
this.id = id;
this.ruleName = ruleName;
this.legalFormId = legalFormId;
this.occupationCategoryCvId = occupationCategoryCvId;
this.occupationCategoryName = occupationCategoryName;
this.occupationCvId = occupationCvId;
this.occupationName = occupationName;
this.minMonthlyIncome = minMonthlyIncome;
this.maxMonthlyIncome = maxMonthlyIncome;
this.minAnnualIncome = minAnnualIncome;
this.maxAnnualIncome = maxAnnualIncome;
this.minAnnualTurnover = minAnnualTurnover;
this.maxAnnualTurnover = maxAnnualTurnover;
this.riskCategory = riskCategory;
this.reason = reason;
this.orderPosition = orderPosition;
}
public Long getId() {
return id;
}
public String getRuleName() {
return ruleName;
}
public Integer getLegalFormId() {
return legalFormId;
}
public Long getOccupationCategoryCvId() {
return occupationCategoryCvId;
}
public String getOccupationCategoryName() {
return occupationCategoryName;
}
public Long getOccupationCvId() {
return occupationCvId;
}
public String getOccupationName() {
return occupationName;
}
public BigDecimal getMinMonthlyIncome() {
return minMonthlyIncome;
}
public BigDecimal getMaxMonthlyIncome() {
return maxMonthlyIncome;
}
public BigDecimal getMinAnnualIncome() {
return minAnnualIncome;
}
public BigDecimal getMaxAnnualIncome() {
return maxAnnualIncome;
}
public BigDecimal getMinAnnualTurnover() {
return minAnnualTurnover;
}
public BigDecimal getMaxAnnualTurnover() {
return maxAnnualTurnover;
}
public Integer getRiskCategory() {
return riskCategory;
}
public String getReason() {
return reason;
}
public Integer getOrderPosition() {
return orderPosition;
}
}
@@ -0,0 +1,26 @@
/**
* 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.client.service;
import java.util.List;
import org.apache.fineract.portfolio.client.data.KycRiskRuleData;
public interface KycRiskRulesReadPlatformService {
List<KycRiskRuleData> retrieveAllRules();
}
@@ -0,0 +1,68 @@
/**
* 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.client.service;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.portfolio.client.data.KycRiskRuleData;
import org.apache.fineract.portfolio.client.domain.ClientRiskRule;
import org.apache.fineract.portfolio.client.domain.ClientRiskRuleRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class KycRiskRulesReadPlatformServiceImpl implements KycRiskRulesReadPlatformService {
private final ClientRiskRuleRepository repository;
@Override
public List<KycRiskRuleData> retrieveAllRules() {
final List<ClientRiskRule> rules = this.repository.findAllOrderedByOrderPosition();
return rules.stream().map(this::mapToData).collect(Collectors.toList());
}
private KycRiskRuleData mapToData(final ClientRiskRule rule) {
final Long occCatId = rule.getOccupationCategory() != null ? rule.getOccupationCategory().getId() : null;
final String occCatName = rule.getOccupationCategory() != null ? rule.getOccupationCategory().getLabel() : null;
final Long occId = rule.getOccupation() != null ? rule.getOccupation().getId() : null;
final String occName = rule.getOccupation() != null ? rule.getOccupation().getLabel() : null;
return new KycRiskRuleData(
rule.getId(),
rule.getRuleName(),
rule.getLegalFormId(),
occCatId,
occCatName,
occId,
occName,
rule.getMinMonthlyIncome(),
rule.getMaxMonthlyIncome(),
rule.getMinAnnualIncome(),
rule.getMaxAnnualIncome(),
rule.getMinAnnualTurnover(),
rule.getMaxAnnualTurnover(),
rule.getRiskCategory(),
rule.getReason(),
rule.getOrderPosition()
);
}
}
@@ -478,4 +478,5 @@
<include file="parts/0361_add_share_account_pending_edit_table.xml" relativeToChangelogFile="true"/>
<include file="parts/0362_add_share_account_edit_approval_permissions.xml" relativeToChangelogFile="true"/>
<include file="parts/0421_add_master_salutation_value.xml" relativeToChangelogFile="true"/>
<include file="parts/0428_add_client_risk_rules.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>
@@ -0,0 +1,151 @@
<?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="0428-1">
<preConditions onFail="MARK_RAN">
<not><tableExists tableName="m_client_risk_rule"/></not>
</preConditions>
<createTable tableName="m_client_risk_rule">
<column name="id" type="BIGINT" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="rule_name" type="VARCHAR(100)">
<constraints nullable="false"/>
</column>
<column name="legal_form_id" type="INT">
<constraints nullable="true"/>
</column>
<column name="occupation_category_cv_id" type="BIGINT">
<constraints nullable="true"/>
</column>
<column name="occupation_cv_id" type="BIGINT">
<constraints nullable="true"/>
</column>
<column name="min_monthly_income" type="DECIMAL(19,6)">
<constraints nullable="true"/>
</column>
<column name="max_monthly_income" type="DECIMAL(19,6)">
<constraints nullable="true"/>
</column>
<column name="min_annual_income" type="DECIMAL(19,6)">
<constraints nullable="true"/>
</column>
<column name="max_annual_income" type="DECIMAL(19,6)">
<constraints nullable="true"/>
</column>
<column name="min_annual_turnover" type="DECIMAL(19,6)">
<constraints nullable="true"/>
</column>
<column name="max_annual_turnover" type="DECIMAL(19,6)">
<constraints nullable="true"/>
</column>
<column name="risk_category" type="INT">
<constraints nullable="false"/>
</column>
<column name="reason" type="VARCHAR(255)">
<constraints nullable="false"/>
</column>
<column name="order_position" type="INT">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
<changeSet author="fineract" id="0428-2">
<preConditions onFail="MARK_RAN">
<not><foreignKeyConstraintExists foreignKeyName="FK_m_client_risk_rule_occupation_category_cv_id"/></not>
</preConditions>
<addForeignKeyConstraint baseTableName="m_client_risk_rule" baseColumnNames="occupation_category_cv_id"
referencedTableName="m_code_value" referencedColumnNames="id"
constraintName="FK_m_client_risk_rule_occupation_category_cv_id" />
</changeSet>
<changeSet author="fineract" id="0428-3">
<preConditions onFail="MARK_RAN">
<not><foreignKeyConstraintExists foreignKeyName="FK_m_client_risk_rule_occupation_cv_id"/></not>
</preConditions>
<addForeignKeyConstraint baseTableName="m_client_risk_rule" baseColumnNames="occupation_cv_id"
referencedTableName="m_code_value" referencedColumnNames="id"
constraintName="FK_m_client_risk_rule_occupation_cv_id" />
</changeSet>
<changeSet author="fineract" id="0428-4">
<preConditions onFail="MARK_RAN">
<sqlCheck expectedResult="0">SELECT COUNT(*) FROM m_client_risk_rule</sqlCheck>
</preConditions>
<sql>
INSERT INTO m_client_risk_rule (rule_name, legal_form_id, occupation_category_cv_id, occupation_cv_id, min_monthly_income, min_annual_income, min_annual_turnover, risk_category, reason, order_position)
VALUES
('Politician / Elected Representative', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Politician / Elected Representative' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 3, 'Politically Exposed Person (PEP) / Elected Representative', 10),
('Real Estate Dealer', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Real Estate / Property Dealer' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 3, 'High Risk Industry (Real Estate / Property Dealing)', 20),
('Importer / Exporter', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Importer / Exporter' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 3, 'High Risk Trade (Import / Export)', 30),
('Commission Agent', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Commission Agent' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 3, 'High Risk Business Type (Commission Agent)', 40),
('Financial Advisor', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Financial Advisor' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 3, 'High Risk Professional (Financial Advisor)', 50),
('High Monthly Income (> 2 Lakhs)', 1, null, null, 200000.0, null, null, 3, 'High Income threshold (> ₹2L Monthly)', 60),
('High Annual Income (> 20 Lakhs)', 1, null, null, null, 2000000.0, null, 3, 'High Income threshold (> ₹20L Annual)', 70),
('High Business Turnover (> 1 Crore)', 1, null, null, null, null, 10000000.0, 3, 'High Business Turnover (> ₹1 Crore Annual)', 80),
('NRI Account Profile', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'NRI (Non-Resident Indian)' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 2, 'Non-Resident Indian (NRI) account profile', 90),
('PIO / OCI Profile', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'PIO / OCI' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 2, 'Foreign/Overseas Citizen profile (PIO / OCI)', 100),
('Business Owner / Proprietor', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Business Owner / Proprietor' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 2, 'Self-Employed / Business owner profile', 110),
('Trader / Merchant', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Trader / Merchant' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 2, 'Self-Employed / Business owner profile', 120),
('Manufacturer', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Manufacturer' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 2, 'Self-Employed / Business owner profile', 130),
('Contractor', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Contractor' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 2, 'Self-Employed / Business owner profile', 140),
('Doctor (Private Practice)', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Doctor (Private Practice)' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 2, 'Self-Employed Professional profile', 150),
('Lawyer / Advocate', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Lawyer / Advocate' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 2, 'Self-Employed Professional profile', 160),
('Chartered Accountant', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Chartered Accountant' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 2, 'Self-Employed Professional profile', 170),
('Company Secretary', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Company Secretary' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 2, 'Self-Employed Professional profile', 180),
('Architect', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Architect' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 2, 'Self-Employed Professional profile', 190),
('Consultant', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Consultant' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 2, 'Self-Employed Professional profile', 200),
('IT Professional / Freelancer', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'IT Professional / Freelancer' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 2, 'Self-Employed Professional profile', 210),
('Auditor', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Auditor' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 2, 'Self-Employed Professional profile', 220),
('Business / Self Employed Category', 1, (SELECT id FROM m_code_value WHERE code_value = 'Business / Self Employed' AND code_id = (SELECT id FROM m_code WHERE code_name = 'OccupationCategory')), null, null, null, null, 2, 'Business / Self-Employed Category', 230),
('Professional Category', 1, (SELECT id FROM m_code_value WHERE code_value = 'Professional' AND code_id = (SELECT id FROM m_code WHERE code_name = 'OccupationCategory')), null, null, null, null, 2, 'Professional Category', 240),
('Medium Monthly Income (> 50K)', 1, null, null, 50000.0, null, null, 2, 'Medium Income threshold (> ₹50K Monthly)', 250),
('Medium Annual Income (> 6 Lakhs)', 1, null, null, null, 600000.0, null, 2, 'Medium Income threshold (> ₹6L Annual)', 260),
('Medium Business Turnover (> 20 Lakhs)', 1, null, null, null, null, 2000000.0, 2, 'Medium Business Turnover (> ₹20L Annual)', 270),
('Student Profile', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Student' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 1, 'Non-Earning profile (Student)', 280),
('Housewife / Homemaker Profile', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Housewife / Homemaker' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 1, 'Non-Earning profile (Homemaker)', 290),
('Dependent / Minor Profile', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Dependent / Minor' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 1, 'Non-Earning profile (Dependent / Minor)', 300),
('Unemployed Profile', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Unemployed' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 1, 'Non-Earning profile (Unemployed)', 310),
('Government Employee', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Government Employee' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 1, 'Low risk employment (Government Employee)', 320),
('PSU Employee', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Public Sector Undertaking (PSU) Employee' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 1, 'Low risk employment (PSU Employee)', 330),
('Defence Personnel', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Defence / Armed Forces Personnel' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 1, 'Low risk employment (Defence Personnel)', 340),
('Police / Paramilitary', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Police / Paramilitary' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 1, 'Low risk employment (Police / Paramilitary)', 350),
('Teacher / Professor', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Teacher / Professor' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 1, 'Low risk employment (Teacher / Professor)', 360),
('Bank Employee', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Bank Employee' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 1, 'Low risk employment (Bank Employee)', 370),
('Railway Employee', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Railway Employee' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 1, 'Low risk employment (Railway Employee)', 380),
('Farmer (Own Land)', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Farmer (Own Land)' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 1, 'Low risk agricultural occupation', 390),
('Tenant Farmer', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Tenant Farmer' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 1, 'Low risk agricultural occupation', 400),
('Agricultural Labourer', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Agricultural Labourer' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 1, 'Low risk manual/agricultural labour', 410),
('Labourer / Daily Wage', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Labourer / Daily Wage' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 1, 'Low risk manual labour', 420),
('Domestic Worker', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Domestic Worker' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 1, 'Low risk manual/domestic service', 430),
('Driver / Operator', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Driver / Operator' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 1, 'Low risk manual/transport service', 440),
('Artisan / Craftsman', 1, null, (SELECT id FROM m_code_value WHERE code_value = 'Artisan / Craftsman' AND code_id = (SELECT id FROM m_code WHERE code_name = 'Occupation')), null, null, null, 1, 'Low risk manual/artisan profile', 450),
('Non-Individual Default Medium Risk', 2, null, null, null, null, null, 2, 'Non-Individual / Entity profile (Default Medium Risk)', 460),
('Global Default Low Risk', null, null, null, null, null, null, 1, 'Default Low Risk profile (Salary / Service / Agriculture / Others)', 500);
</sql>
</changeSet>
</databaseChangeLog>