diff --git a/fineract-core/src/main/java/org/apache/fineract/portfolio/aml/domain/AmlTransactionRule.java b/fineract-core/src/main/java/org/apache/fineract/portfolio/aml/domain/AmlTransactionRule.java index 1099f7f37..44c110345 100644 --- a/fineract-core/src/main/java/org/apache/fineract/portfolio/aml/domain/AmlTransactionRule.java +++ b/fineract-core/src/main/java/org/apache/fineract/portfolio/aml/domain/AmlTransactionRule.java @@ -60,6 +60,18 @@ public class AmlTransactionRule { @Column(name = "threshold_amount_high_risk", precision = 19, scale = 6) private BigDecimal thresholdAmountHighRisk; + /** + * Declarative band the rule covers, shown on the AML Rules Master screen. Purely + * descriptive: unlike the tiered columns above these never take part in matching, so + * changing them cannot alter which transactions raise an alert. A null maximum means + * the rule is genuinely open-ended. + */ + @Column(name = "min_limit_amount", precision = 19, scale = 6) + private BigDecimal minLimitAmount; + + @Column(name = "max_limit_amount", precision = 19, scale = 6) + private BigDecimal maxLimitAmount; + @Column(name = "rule_type", nullable = false, length = 20) private String ruleType; @@ -102,6 +114,14 @@ public class AmlTransactionRule { return thresholdAmountHighRisk; } + public BigDecimal getMinLimitAmount() { + return minLimitAmount; + } + + public BigDecimal getMaxLimitAmount() { + return maxLimitAmount; + } + public AmlRuleType getRuleType() { return AmlRuleType.valueOf(ruleType); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/KycRiskRuleData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/KycRiskRuleData.java index 2c0ac90f4..7eebbe34a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/KycRiskRuleData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/data/KycRiskRuleData.java @@ -56,6 +56,10 @@ public final class KycRiskRuleData implements Serializable { * linked {@code m_aml_transaction_rule} row has tiering configured (e.g. RTGS monitoring). */ private final BigDecimal txnThresholdAmountMediumRisk; private final BigDecimal txnThresholdAmountHighRisk; + /** Declarative band the rule covers, for display on the AML Rules Master screen. Never + * used in matching; a null maximum means the rule is genuinely open-ended. */ + private final BigDecimal txnMinLimitAmount; + private final BigDecimal txnMaxLimitAmount; public KycRiskRuleData(final Long id, final String ruleName, final Integer legalFormId, final Long occupationCategoryCvId, final String occupationCategoryName, @@ -67,7 +71,8 @@ public final class KycRiskRuleData implements Serializable { final String amlCheckStatus, final String bannedEntityMatch, final String willfulDefaulter, final String ecgcSalFlag, final String dormantFlag, final BigDecimal txnThresholdAmount, final String txnRuleType, final Integer txnWindowDays, - final BigDecimal txnThresholdAmountMediumRisk, final BigDecimal txnThresholdAmountHighRisk) { + final BigDecimal txnThresholdAmountMediumRisk, final BigDecimal txnThresholdAmountHighRisk, + final BigDecimal txnMinLimitAmount, final BigDecimal txnMaxLimitAmount) { this.id = id; this.ruleName = ruleName; this.legalFormId = legalFormId; @@ -94,6 +99,8 @@ public final class KycRiskRuleData implements Serializable { this.txnWindowDays = txnWindowDays; this.txnThresholdAmountMediumRisk = txnThresholdAmountMediumRisk; this.txnThresholdAmountHighRisk = txnThresholdAmountHighRisk; + this.txnMinLimitAmount = txnMinLimitAmount; + this.txnMaxLimitAmount = txnMaxLimitAmount; } public Long getId() { @@ -199,4 +206,12 @@ public final class KycRiskRuleData implements Serializable { public BigDecimal getTxnThresholdAmountHighRisk() { return txnThresholdAmountHighRisk; } + + public BigDecimal getTxnMinLimitAmount() { + return txnMinLimitAmount; + } + + public BigDecimal getTxnMaxLimitAmount() { + return txnMaxLimitAmount; + } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/KycRiskRulesReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/KycRiskRulesReadPlatformServiceImpl.java index 649ee68b4..4e6893ab9 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/KycRiskRulesReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/KycRiskRulesReadPlatformServiceImpl.java @@ -80,7 +80,9 @@ public class KycRiskRulesReadPlatformServiceImpl implements KycRiskRulesReadPlat txnRule != null ? txnRule.getRuleType().name() : null, txnRule != null ? txnRule.getWindowDays() : null, txnRule != null ? txnRule.getThresholdAmountMediumRisk() : null, - txnRule != null ? txnRule.getThresholdAmountHighRisk() : null + txnRule != null ? txnRule.getThresholdAmountHighRisk() : null, + txnRule != null ? txnRule.getMinLimitAmount() : null, + txnRule != null ? txnRule.getMaxLimitAmount() : null ); } } diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml index 1d5428c9d..fbff88481 100644 --- a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml +++ b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml @@ -493,4 +493,6 @@ + + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0441_add_aml_rule_limit_bands.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0441_add_aml_rule_limit_bands.xml new file mode 100644 index 000000000..abe1d7e92 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0441_add_aml_rule_limit_bands.xml @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + UPDATE m_aml_transaction_rule SET min_limit_amount = 1000000, max_limit_amount = 2500000 + WHERE rule_code = 'CTR_THRESHOLD_10L'; + UPDATE m_aml_transaction_rule SET min_limit_amount = 1000000, max_limit_amount = 2500000 + WHERE rule_code = 'STRUCTURED_CTR_10L_MONTHLY'; + UPDATE m_aml_transaction_rule SET min_limit_amount = 2500000, max_limit_amount = 5000000 + WHERE rule_code = 'LARGE_CASH_TXN_25L'; + -- Structuring rules watch the band immediately BELOW the reporting threshold. + UPDATE m_aml_transaction_rule SET min_limit_amount = 700000, max_limit_amount = 1000000 + WHERE rule_code = 'STRUCTURING_BELOW_10L'; + UPDATE m_aml_transaction_rule SET min_limit_amount = 35000, max_limit_amount = 50000 + WHERE rule_code = 'STRUCTURING_BELOW_50K'; + UPDATE m_aml_transaction_rule SET min_limit_amount = 900000, max_limit_amount = 1000000 + WHERE rule_code = 'FREQUENT_CASH_NEAR_10L'; + UPDATE m_aml_transaction_rule SET min_limit_amount = 50000, max_limit_amount = 200000 + WHERE rule_code = 'FREQUENT_LOW_CASH_DEPOSIT'; + UPDATE m_aml_transaction_rule SET min_limit_amount = 50000, max_limit_amount = 200000 + WHERE rule_code = 'FREQUENT_LOW_CASH_WITHDRAWAL'; + UPDATE m_aml_transaction_rule SET min_limit_amount = 500000, max_limit_amount = 2000000 + WHERE rule_code = 'RTGS_HIGH_VALUE'; + UPDATE m_aml_transaction_rule SET min_limit_amount = 2000000, max_limit_amount = 5000000 + WHERE rule_code = 'JEWELLER_ACCOUNT_LARGE_TXN'; + UPDATE m_aml_transaction_rule SET min_limit_amount = 50000, max_limit_amount = 200000 + WHERE rule_code = 'CHARITABLE_ORG_CASH_WITHDRAWAL'; + UPDATE m_aml_transaction_rule SET min_limit_amount = 50000, max_limit_amount = 500000 + WHERE rule_code = 'PEP_ACCOUNT_MONITORING'; + UPDATE m_aml_transaction_rule SET min_limit_amount = 500000, max_limit_amount = 1000000 + WHERE rule_code = 'NEW_ACCOUNT_LARGE_TXN'; + UPDATE m_aml_transaction_rule SET min_limit_amount = 200000, max_limit_amount = 500000 + WHERE rule_code = 'LOAN_REPAYMENT_IN_CASH'; + UPDATE m_aml_transaction_rule SET min_limit_amount = 1000000, max_limit_amount = 2500000 + WHERE rule_code = 'LOW_BALANCE_HIGH_ACTIVITY'; + -- RAPID_MOVEMENT_IN_ACCOUNTS is a pure velocity rule with no monetary threshold, + -- so it is intentionally left without a band. + + + + + + + UPDATE m_client_risk_rule SET max_monthly_income = NULL WHERE max_monthly_income = 0; + UPDATE m_client_risk_rule SET max_annual_income = NULL WHERE max_annual_income = 0; + UPDATE m_client_risk_rule SET max_annual_turnover = NULL WHERE max_annual_turnover = 0; + UPDATE m_client_risk_rule SET min_monthly_income = NULL WHERE min_monthly_income = 0; + UPDATE m_client_risk_rule SET min_annual_income = NULL WHERE min_annual_income = 0; + UPDATE m_client_risk_rule SET min_annual_turnover = NULL WHERE min_annual_turnover = 0; + + + + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0442_seed_branch_offices.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0442_seed_branch_offices.xml new file mode 100644 index 000000000..bc0a1846a --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0442_seed_branch_offices.xml @@ -0,0 +1,59 @@ + + + + + + + + SELECT COUNT(*) FROM m_office WHERE external_id IN ('0002','0003','0004','0005','0006') + + + INSERT INTO m_office (parent_id, hierarchy, external_id, name, opening_date) + VALUES + ((SELECT id FROM m_office WHERE hierarchy = '.'), '.2.', '0002', 'Andheri (E)', DATE '2018-04-01'), + ((SELECT id FROM m_office WHERE hierarchy = '.'), '.3.', '0003', 'Bandra (W)', DATE '2018-04-01'), + ((SELECT id FROM m_office WHERE hierarchy = '.'), '.4.', '0004', 'Borivali', DATE '2019-07-01'), + ((SELECT id FROM m_office WHERE hierarchy = '.'), '.5.', '0005', 'Dadar', DATE '2020-01-02'), + ((SELECT id FROM m_office WHERE hierarchy = '.'), '.6.', '0006', 'Thane', DATE '2021-06-01'); + + + + + + + SELECT COUNT(*) FROM m_office WHERE external_id = 'HO' + + + UPDATE m_office SET external_id = 'HO' WHERE hierarchy = '.'; + + + +