kyc risk and AML & Compliance Checks automate on client creation

This commit is contained in:
2026-07-31 10:58:58 +05:30
parent 29f1cdc646
commit 1daa12a117
17 changed files with 1113 additions and 1347 deletions
+126 -2
View File
@@ -6,10 +6,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
import { Component } from '@angular/core';
import { Component, OnInit, inject } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { AmlService } from 'app/aml/aml.service';
import { AuthenticationService } from 'app/core/authentication/authentication.service';
import {
CtrTransaction,
CTR_TXNS,
@@ -33,7 +35,9 @@ import {
FormsModule
]
})
export class FiuComponent {
export class FiuComponent implements OnInit {
private amlService = inject(AmlService);
private authenticationService = inject(AuthenticationService);
/** Active tab */
activeTab: 'dashboard' | 'ctr' | 'str' | 'customers' | 'files' = 'dashboard';
@@ -57,6 +61,126 @@ export class FiuComponent {
toastVisible = false;
private toastTimer: any;
// -------------------- Live AML monitoring (real backend, replaces mock CTR/STR tables) --------------------
amlAlerts: any[] = [];
amlAlertStatusFilter = '';
amlReviewNotes: Record<number, string> = {};
amlCtrReports: any[] = [];
ctrGenerateMonth = '';
amlStrCases: any[] = [];
selectedStrCase: any = null;
concludeConclusion: 'NOT_SUSPICIOUS' | 'SUSPICIOUS' = 'NOT_SUSPICIOUS';
concludeInvestigationNotes = '';
concludeSourceOfFundsNotes = '';
fileReferenceNo = '';
get isPrincipalOfficer(): boolean {
return this.authenticationService.isPrincipalOfficerUser();
}
get isAmlOfficer(): boolean {
return this.authenticationService.isAmlOfficerUser();
}
ngOnInit(): void {
this.loadAmlAlerts();
this.loadAmlCtrReports();
this.loadAmlStrCases();
}
loadAmlAlerts(): void {
this.amlService
.getAlerts(this.amlAlertStatusFilter || undefined)
.subscribe((data) => (this.amlAlerts = data || []));
}
loadAmlCtrReports(): void {
this.amlService.getCtrReports().subscribe((data) => (this.amlCtrReports = data || []));
}
loadAmlStrCases(): void {
this.amlService.getStrCases().subscribe((data) => (this.amlStrCases = data || []));
}
whitelistAlert(alert: any): void {
this.amlService.reviewAlert(alert.id, 'WHITELIST', this.amlReviewNotes[alert.id] || '').subscribe(() => {
this.toast(`Alert #${alert.id} whitelisted`);
this.loadAmlAlerts();
});
}
escalateAlert(alert: any): void {
this.amlService.reviewAlert(alert.id, 'ESCALATE', this.amlReviewNotes[alert.id] || '').subscribe(() => {
this.toast(`Alert #${alert.id} escalated to Principal Officer`);
this.loadAmlAlerts();
this.loadAmlStrCases();
});
}
generateCtrReport(): void {
if (!this.ctrGenerateMonth) {
return;
}
this.amlService.generateCtrReport(this.ctrGenerateMonth).subscribe({
next: () => {
this.toast(`CTR report generated for ${this.ctrGenerateMonth}`);
this.loadAmlCtrReports();
},
error: (err) => this.toast(err?.error?.defaultUserMessage || 'CTR report generation failed')
});
}
selectStrCase(strCase: any): void {
this.selectedStrCase = strCase;
this.concludeConclusion = 'NOT_SUSPICIOUS';
this.concludeInvestigationNotes = strCase.investigationNotes || '';
this.concludeSourceOfFundsNotes = strCase.sourceOfFundsNotes || '';
this.fileReferenceNo = '';
}
closeStrCaseDetail(): void {
this.selectedStrCase = null;
}
concludeStrCase(): void {
if (!this.selectedStrCase) {
return;
}
this.amlService
.concludeStrCase(
this.selectedStrCase.id,
this.concludeConclusion,
this.concludeInvestigationNotes,
this.concludeSourceOfFundsNotes
)
.subscribe((updated) => {
this.toast(
this.concludeConclusion === 'SUSPICIOUS'
? `STR case #${updated.id} concluded suspicious — FIU due date ${updated.fiuDueDate}`
: `STR case #${updated.id} concluded not suspicious`
);
this.selectedStrCase = updated;
this.loadAmlStrCases();
});
}
fileStrCase(): void {
if (!this.selectedStrCase || !this.fileReferenceNo) {
return;
}
this.amlService.fileStr(this.selectedStrCase.id, this.fileReferenceNo).subscribe((updated) => {
this.toast(`STR case #${updated.id} recorded as filed (ref ${updated.strReferenceNo})`);
this.selectedStrCase = updated;
this.loadAmlStrCases();
});
}
amlStatusClass(status: string): string {
return 'status-pill status-' + (status || '').toLowerCase().replace(/_/g, '-');
}
showTab(tab: 'dashboard' | 'ctr' | 'str' | 'customers' | 'files'): void {
this.activeTab = tab;
}