Files
cbsnexora/src/app/credit-bureau/cic-dashboard/cic-dashboard.component.ts
T
niteshandClaude Opus 5.5 885b5897af feat(api-management): set up each CIC bureau as an API vendor
CIBIL, Experian, Equifax and CRIF are vendors under API Management (active =
whitelisted) and the Credit Bureau dashboard reads them from there; the
separate CIC whitelist and API mapping screens are removed. Mapping tables show
the value each row finds in the sample payload, and bureau cards link to their
set-up.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 15:50:27 +05:30

131 lines
3.9 KiB
TypeScript

/**
* 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 { CommonModule } from '@angular/common';
import { Component, OnInit, inject } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { ApiManagementService } from 'app/api-management/api-management.service';
import { HasPermissionDirective } from 'app/directives/has-permission/has-permission.directive';
import { CicAlertDetailComponent } from '../cic-alert-detail/cic-alert-detail.component';
import { CicService, cicError, cicStatusTone } from '../cic.service';
/**
* Credit Bureau dashboard: our customers who applied for a loan at another bank / NBFC, as reported by the CICs -
* who, what loan and how much (the CIC does not name the lender) - with the customers applying elsewhere repeatedly,
* the loan types, the trend, and the fetch status of each bureau. Each bureau is set up under API Management → API
* Vendors & Setup.
*/
@Component({
selector: 'mifosx-cic-dashboard',
standalone: true,
imports: [
CommonModule,
FormsModule,
RouterModule,
HasPermissionDirective,
CicAlertDetailComponent
],
templateUrl: './cic-dashboard.component.html',
styleUrls: ['../cic-shared.scss']
})
export class CicDashboardComponent implements OnInit {
private cic = inject(CicService);
private apis = inject(ApiManagementService);
/** Each bureau is set up as a vendor under API Management (connection, whitelist, request / response mapping). */
setupRoute(code: string): any[] {
const v = this.apis.vendorByCode(code);
return v ? [
'/api-management/vendors',
v.id
] : ['/api-management/vendors'];
}
days = 30;
loading = false;
error: string | null = null;
info: string | null = null;
data: any = null;
fetching: number | 'ALL' | null = null;
openAlertId: number | null = null;
readonly statusTone = cicStatusTone;
ngOnInit(): void {
this.load();
}
load(): void {
this.loading = true;
this.error = null;
this.cic.dashboard(this.days).subscribe({
next: (d) => {
this.data = d;
this.loading = false;
},
error: (e) => {
this.error = cicError(e, 'Could not load the credit bureau dashboard.');
this.loading = false;
}
});
}
get whitelisted(): any[] {
return (this.data?.bureaus ?? []).filter((b: any) => b.whitelisted);
}
/** Fetch now from one bureau, or from every whitelisted bureau in turn. */
fetchNow(bureauId: number | 'ALL'): void {
const ids = bureauId === 'ALL' ? this.whitelisted.map((b) => b.id as number) : [bureauId];
if (!ids.length) return;
this.fetching = bureauId;
this.error = null;
this.info = null;
const messages: string[] = [];
const next = (i: number) => {
if (i >= ids.length) {
this.fetching = null;
this.info = messages.join(' · ');
this.load();
return;
}
this.cic.fetch(ids[i]).subscribe({
next: (run) => {
messages.push(
`${run.bureauCode}: ${run.status === 'SUCCESS' ? run.newAlerts + ' new alert(s)' : 'failed - ' + run.message}`
);
next(i + 1);
},
error: (e) => {
messages.push(cicError(e, 'Fetch failed.'));
next(i + 1);
}
});
};
next(0);
}
max(list: any[] | undefined, key: string): number {
return Math.max(1, ...(list ?? []).map((x) => Number(x[key] ?? 0)));
}
pct(value: any, list: any[] | undefined, key: string): number {
return Math.round((Number(value ?? 0) / this.max(list, key)) * 100);
}
onChanged(): void {
this.load();
}
fetchTone(status?: string): string {
return status === 'SUCCESS' ? 'good' : status === 'FAILED' ? 'bad' : '';
}
}