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 = '.';
+
+
+
+