/** * Copyright since 2025 Mifos Initiative * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import { Injectable, inject } from '@angular/core'; import { HttpClient, HttpParams } from '@angular/common/http'; import { Observable } from 'rxjs'; /** * AML transaction-monitoring API: live alerts raised by the rule engine, the * two-tier AML Officer / Principal Officer review workflow, STR cases (with * their 7-working-day FIU filing deadline), monthly CTR reports, and a * client's risk-category change history. */ @Injectable({ providedIn: 'root' }) export class AmlService { private http = inject(HttpClient); // ═══ Alerts (AML Officer) ═══ getAlerts(status?: string): Observable { const params = status ? new HttpParams().set('status', status) : undefined; return this.http.get('/aml/alerts', { params }); } /** disposition: 'WHITELIST' | 'ESCALATE' */ reviewAlert(alertId: number, disposition: 'WHITELIST' | 'ESCALATE', notes: string): Observable { return this.http.post(`/aml/alerts/${alertId}/review`, { disposition, notes }); } // ═══ STR cases (Principal Officer) ═══ getStrCases(): Observable { return this.http.get('/aml/str-cases'); } getStrCase(strCaseId: number): Observable { return this.http.get(`/aml/str-cases/${strCaseId}`); } getWeeklyDigest(): Observable { return this.http.get('/aml/str-cases/weekly-digest'); } assignPrincipalOfficer(strCaseId: number, principalOfficerUserId: number): Observable { return this.http.post(`/aml/str-cases/${strCaseId}/assign`, { principalOfficerUserId }); } /** conclusion: 'NOT_SUSPICIOUS' | 'SUSPICIOUS' */ concludeStrCase( strCaseId: number, conclusion: 'NOT_SUSPICIOUS' | 'SUSPICIOUS', investigationNotes: string, sourceOfFundsNotes: string ): Observable { return this.http.post(`/aml/str-cases/${strCaseId}/conclude`, { conclusion, investigationNotes, sourceOfFundsNotes }); } fileStr(strCaseId: number, referenceNo: string): Observable { return this.http.post(`/aml/str-cases/${strCaseId}/file`, { referenceNo }); } // ═══ CTR reports (mechanical, threshold-based) ═══ getCtrReports(): Observable { return this.http.get('/aml/ctr-reports'); } /** month format: yyyy-MM */ generateCtrReport(month: string): Observable { return this.http.post('/aml/ctr-reports/generate', { month }); } // ═══ Client risk-category history ═══ getRiskCategoryHistory(clientId: number): Observable { return this.http.get(`/clients/${clientId}/risk-category-history`); } }