CTR/STR report and Risk Category auto mark on bases of person occupation and anual salary enter

This commit is contained in:
2026-07-29 10:21:02 +05:30
parent 79fedb66e5
commit f682cb17f6
16 changed files with 1808 additions and 29 deletions
@@ -108,6 +108,7 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
* m_code_value (code "PwdCategory") via the client template, same as occupationCategoryOptions.
* Admins can add/reorder/deactivate entries from System -> Manage Codes without a code change. */
pwdCategoryOptions: any[] = [];
riskRules: any[] = [];
/** Set true after a save attempt so the UI can highlight a missing required document */
seniorPwdDocsTouched = false;
@@ -546,6 +547,10 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
ngOnInit() {
this.maxDate = this.settingsService.businessDate;
this.setOptions();
this.clientService.getClientRiskRules().subscribe((rules) => {
this.riskRules = rules || [];
});
// Fetch marital status options from code values
this.clientService.getCodeValuesByName('MaritalStatus').subscribe((options) => {
this.maritalStatusOptions = options || [];
@@ -2120,6 +2125,74 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
return generalDetails;
}
get calculatedRisk(): { category: number; reason: string } {
const legalFormId = this.createClientForm.get('legalFormId')?.value || 1; // 1 = Person, 2 = Entity
const occCatId = this.createClientForm.get('occupationCategoryCvId')?.value;
const occId = this.createClientForm.get('occupationCvId')?.value;
const monthlyIncome = parseFloat(this.createClientForm.get('monthlyIncome')?.value) || 0;
const annualIncome = parseFloat(this.createClientForm.get('annualIncome')?.value) || 0;
const monthlyTurnover = parseFloat(this.createClientForm.get('monthlyTurnover')?.value) || 0;
const annualTurnover = parseFloat(this.createClientForm.get('annualTurnover')?.value) || 0;
const agricultureIncome = parseFloat(this.createClientForm.get('agricultureIncome')?.value) || 0;
const nonAgricultureIncome = parseFloat(this.createClientForm.get('nonAgricultureIncome')?.value) || 0;
const totalAnnualIncome = annualIncome + agricultureIncome + nonAgricultureIncome;
// Evaluate rules from DB (ordered by orderPosition ASC)
if (this.riskRules && this.riskRules.length > 0) {
for (const rule of this.riskRules) {
// Match legal form
if (rule.legalFormId != null && rule.legalFormId !== legalFormId) {
continue;
}
// Match occupation category
if (rule.occupationCategoryCvId != null && rule.occupationCategoryCvId !== occCatId) {
continue;
}
// Match occupation
if (rule.occupationCvId != null && rule.occupationCvId !== occId) {
continue;
}
// Match monthly income ranges
if (rule.minMonthlyIncome != null && monthlyIncome < rule.minMonthlyIncome) {
continue;
}
if (rule.maxMonthlyIncome != null && monthlyIncome > rule.maxMonthlyIncome) {
continue;
}
// Match annual income ranges (evaluated against totalAnnualIncome)
if (rule.minAnnualIncome != null && totalAnnualIncome < rule.minAnnualIncome) {
continue;
}
if (rule.maxAnnualIncome != null && totalAnnualIncome > rule.maxAnnualIncome) {
continue;
}
// Match turnover ranges
if (rule.minAnnualTurnover != null && annualTurnover < rule.minAnnualTurnover) {
continue;
}
if (rule.maxAnnualTurnover != null && annualTurnover > rule.maxAnnualTurnover) {
continue;
}
// All matched!
return { category: rule.riskCategory, reason: rule.reason };
}
}
// Default Fallbacks
if (legalFormId !== LegalFormId.PERSON) {
return { category: 2, reason: 'Non-Individual / Entity profile (Default Medium Risk)' };
}
return { category: 1, reason: 'Default Low Risk profile (Salary / Service / Agriculture / Others)' };
}
}
/**