form 91/98 report, min max value update in AML rule and whihc rule apply day, week, month and some more updates
This commit is contained in:
@@ -42,24 +42,185 @@ export class AmlRulesComponent implements OnInit {
|
||||
'orderPosition',
|
||||
'ruleName',
|
||||
'riskCategory',
|
||||
'incomeLimit',
|
||||
'limitBasis',
|
||||
'minLimit',
|
||||
'maxLimit',
|
||||
'appliesOver',
|
||||
'reason',
|
||||
'amlCheckStatus',
|
||||
'bannedEntityMatch'
|
||||
];
|
||||
|
||||
/** Every rule as returned by the API, before the period filter is applied. */
|
||||
private allRules: any[] = [];
|
||||
|
||||
/** Period buckets the rules can be separated into. */
|
||||
readonly periodFilters: { key: string; label: string }[] = [
|
||||
{ key: '', label: 'All rules' },
|
||||
{ key: 'TXN', label: 'Per transaction' },
|
||||
{ key: 'DAY', label: 'Daily' },
|
||||
{ key: 'WEEK', label: 'Weekly' },
|
||||
{ key: 'MONTH', label: 'Monthly' },
|
||||
{ key: 'OTHER', label: 'Other window' }
|
||||
];
|
||||
activePeriod = '';
|
||||
|
||||
@ViewChild(MatPaginator) paginator!: MatPaginator;
|
||||
|
||||
ngOnInit(): void {
|
||||
this.clientsService.getClientRiskRules().subscribe({
|
||||
next: (data) => {
|
||||
this.rules.data = data || [];
|
||||
this.allRules = data || [];
|
||||
this.applyPeriodFilter();
|
||||
this.rules.paginator = this.paginator;
|
||||
},
|
||||
error: () => {}
|
||||
});
|
||||
}
|
||||
|
||||
setPeriod(key: string): void {
|
||||
this.activePeriod = key;
|
||||
this.applyPeriodFilter();
|
||||
}
|
||||
|
||||
private applyPeriodFilter(): void {
|
||||
this.rules.data = this.activePeriod
|
||||
? this.allRules.filter((r) => this.periodKey(r) === this.activePeriod)
|
||||
: this.allRules;
|
||||
if (this.rules.paginator) {
|
||||
this.rules.paginator.firstPage();
|
||||
}
|
||||
}
|
||||
|
||||
/** How many rules fall in each period bucket — shown on the filter chips. */
|
||||
periodCount(key: string): number {
|
||||
return key ? this.allRules.filter((r) => this.periodKey(r) === key).length : this.allRules.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Buckets a rule by the observation window it is measured over.
|
||||
* A rule with no window is evaluated on the single transaction itself, so it is
|
||||
* in force every day rather than accumulating over a period.
|
||||
*/
|
||||
periodKey(rule: any): string {
|
||||
const days = rule.txnWindowDays;
|
||||
if (days == null || days === 0) {
|
||||
return 'TXN';
|
||||
}
|
||||
if (days === 1) {
|
||||
return 'DAY';
|
||||
}
|
||||
if (days === 7) {
|
||||
return 'WEEK';
|
||||
}
|
||||
if (days >= 28 && days <= 31) {
|
||||
return 'MONTH';
|
||||
}
|
||||
return 'OTHER';
|
||||
}
|
||||
|
||||
periodLabel(rule: any): string {
|
||||
const days = rule.txnWindowDays;
|
||||
switch (this.periodKey(rule)) {
|
||||
case 'TXN':
|
||||
return 'Per transaction';
|
||||
case 'DAY':
|
||||
return 'Daily';
|
||||
case 'WEEK':
|
||||
return 'Weekly';
|
||||
case 'MONTH':
|
||||
return 'Monthly';
|
||||
default:
|
||||
return `${days} days`;
|
||||
}
|
||||
}
|
||||
|
||||
periodClass(rule: any): string {
|
||||
return 'period-badge period-' + this.periodKey(rule).toLowerCase();
|
||||
}
|
||||
|
||||
/** Sub-caption telling the reader what the min/max figures actually measure. */
|
||||
getLimitBasis(rule: any): string {
|
||||
if (rule.minMonthlyIncome > 0 || rule.maxMonthlyIncome > 0) {
|
||||
return 'Monthly Income';
|
||||
}
|
||||
if (rule.minAnnualIncome > 0 || rule.maxAnnualIncome > 0) {
|
||||
return 'Annual Income';
|
||||
}
|
||||
if (rule.minAnnualTurnover > 0 || rule.maxAnnualTurnover > 0) {
|
||||
return 'Annual Turnover';
|
||||
}
|
||||
if (rule.txnThresholdAmountMediumRisk != null || rule.txnThresholdAmountHighRisk != null) {
|
||||
return 'Txn Amount (tiered)';
|
||||
}
|
||||
if (rule.txnThresholdAmount != null) {
|
||||
return 'Txn Amount';
|
||||
}
|
||||
if (rule.occupationName) {
|
||||
return 'Occupation';
|
||||
}
|
||||
if (rule.occupationCategoryName) {
|
||||
return 'Occupation Category';
|
||||
}
|
||||
return 'Behavioural pattern';
|
||||
}
|
||||
|
||||
private inr(n: number): string {
|
||||
return '₹' + Number(n).toLocaleString('en-IN');
|
||||
}
|
||||
|
||||
/** Lower bound of the rule, or an em dash where the criterion is not numeric. */
|
||||
getMinLimit(rule: any): string {
|
||||
if (rule.minMonthlyIncome > 0) {
|
||||
return this.inr(rule.minMonthlyIncome);
|
||||
}
|
||||
if (rule.minAnnualIncome > 0) {
|
||||
return this.inr(rule.minAnnualIncome);
|
||||
}
|
||||
if (rule.minAnnualTurnover > 0) {
|
||||
return this.inr(rule.minAnnualTurnover);
|
||||
}
|
||||
// Declarative band from m_aml_transaction_rule takes precedence over the raw threshold.
|
||||
if (rule.txnMinLimitAmount != null) {
|
||||
return this.inr(rule.txnMinLimitAmount);
|
||||
}
|
||||
if (rule.txnThresholdAmount != null) {
|
||||
return this.inr(rule.txnThresholdAmount);
|
||||
}
|
||||
return '—';
|
||||
}
|
||||
|
||||
/** Upper bound, or "No upper limit" where the rule is genuinely open-ended. */
|
||||
getMaxLimit(rule: any): string {
|
||||
if (rule.maxMonthlyIncome > 0) {
|
||||
return this.inr(rule.maxMonthlyIncome);
|
||||
}
|
||||
if (rule.maxAnnualIncome > 0) {
|
||||
return this.inr(rule.maxAnnualIncome);
|
||||
}
|
||||
if (rule.maxAnnualTurnover > 0) {
|
||||
return this.inr(rule.maxAnnualTurnover);
|
||||
}
|
||||
if (rule.txnMaxLimitAmount != null) {
|
||||
return this.inr(rule.txnMaxLimitAmount);
|
||||
}
|
||||
// A floor with no configured ceiling means the rule has no upper bound.
|
||||
if (
|
||||
rule.minMonthlyIncome > 0 ||
|
||||
rule.minAnnualIncome > 0 ||
|
||||
rule.minAnnualTurnover > 0 ||
|
||||
rule.txnThresholdAmount != null
|
||||
) {
|
||||
return 'No upper limit';
|
||||
}
|
||||
return '—';
|
||||
}
|
||||
|
||||
/** Occupation-driven rules carry no amount; show the criterion instead. */
|
||||
getNonNumericCriterion(rule: any): string {
|
||||
return rule.occupationName || rule.occupationCategoryName || '';
|
||||
}
|
||||
|
||||
getRiskCategoryLabel(category: number): string {
|
||||
switch (category) {
|
||||
case 1:
|
||||
@@ -85,39 +246,4 @@ export class AmlRulesComponent implements OnInit {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/** Formats whichever income/turnover/occupation criterion drives this rule's risk mark. */
|
||||
getIncomeLimitLabel(rule: any): string {
|
||||
const inr = (n: number) => '₹' + Number(n).toLocaleString('en-IN');
|
||||
if (rule.minMonthlyIncome != null && rule.minMonthlyIncome > 0) {
|
||||
return rule.maxMonthlyIncome != null && rule.maxMonthlyIncome > 0
|
||||
? `Monthly Income ${inr(rule.minMonthlyIncome)} - ${inr(rule.maxMonthlyIncome)}`
|
||||
: `Monthly Income > ${inr(rule.minMonthlyIncome)}`;
|
||||
}
|
||||
if (rule.minAnnualIncome != null && rule.minAnnualIncome > 0) {
|
||||
return rule.maxAnnualIncome != null && rule.maxAnnualIncome > 0
|
||||
? `Annual Income ${inr(rule.minAnnualIncome)} - ${inr(rule.maxAnnualIncome)}`
|
||||
: `Annual Income > ${inr(rule.minAnnualIncome)}`;
|
||||
}
|
||||
if (rule.minAnnualTurnover != null && rule.minAnnualTurnover > 0) {
|
||||
return rule.maxAnnualTurnover != null && rule.maxAnnualTurnover > 0
|
||||
? `Annual Turnover ${inr(rule.minAnnualTurnover)} - ${inr(rule.maxAnnualTurnover)}`
|
||||
: `Annual Turnover > ${inr(rule.minAnnualTurnover)}`;
|
||||
}
|
||||
if (rule.occupationName) return `Occupation: ${rule.occupationName}`;
|
||||
if (rule.occupationCategoryName) return `Occupation Category: ${rule.occupationCategoryName}`;
|
||||
if (rule.txnThresholdAmountMediumRisk != null || rule.txnThresholdAmountHighRisk != null) {
|
||||
const parts: string[] = [];
|
||||
if (rule.txnThresholdAmountMediumRisk != null) parts.push(`${inr(rule.txnThresholdAmountMediumRisk)} (Medium Risk)`);
|
||||
if (rule.txnThresholdAmountHighRisk != null) parts.push(`${inr(rule.txnThresholdAmountHighRisk)} (High Risk)`);
|
||||
return `Txn Amount ≥ ${parts.join(' / ')}`;
|
||||
}
|
||||
if (rule.txnThresholdAmount != null) {
|
||||
const amt = inr(rule.txnThresholdAmount);
|
||||
if (rule.txnRuleType === 'THRESHOLD') return `Txn Amount ≥ ${amt}`;
|
||||
if (rule.txnWindowDays != null) return `${amt} within ${rule.txnWindowDays} days`;
|
||||
return `Txn Amount ≥ ${amt}`;
|
||||
}
|
||||
return 'Behavioral / Transaction Pattern';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user