Files
cbsnexora/src/app/loan-eligibility/loan-eligibility.service.ts
T
2026-10-19 15:19:16 +05:30

155 lines
4.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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 } from '@angular/core';
import { Observable, delay, of, throwError } from 'rxjs';
import { demoBorrower, demoBorrowers, demoSummary } from './loan-eligibility.mock';
export type BorrowerCategory = 'GOOD' | 'WATCH' | 'BAD';
export interface LoanStageRow {
stage: string;
label: string;
dpdRange: string;
group: 'PERFORMING' | 'NPA' | 'CLOSED';
loans: number;
outstanding: number;
overdue: number;
}
export interface LoanProductRow {
productId: number;
productName: string;
activeLoans: number;
performingLoans: number;
npaLoans: number;
outstanding: number;
npaOutstanding: number;
}
/** Loan book health as on the business date (RBI asset classes, products, borrowers). */
export interface LoanEligibilitySummary {
asOnDate: string;
activeLoans: number;
activeOutstanding: number;
performingLoans: number;
performingOutstanding: number;
npaLoans: number;
npaOutstanding: number;
grossNpaPct: number;
closedLoans: number;
writtenOffLoans: number;
writtenOffAmount: number;
/** Share linking to borrowing across members with running loans. */
shareRequired: number;
shareHeld: number;
shareShortMembers: number;
shareShortfall: number;
goodBorrowers: number;
watchBorrowers: number;
badBorrowers: number;
stages: LoanStageRow[];
products: LoanProductRow[];
notes: string[];
}
export interface BorrowerLoan {
loanId: number;
accountNo: string;
productName: string;
status: string;
stage: string;
dpd: number;
emisPaid: number;
emisLate: number;
disbursed: number;
outstanding: number;
overdue: number;
sharePct: number;
shareRequired: number;
}
export interface AccountMonth {
month: string;
credits: number;
debits: number;
avgBalance: number;
returns: number;
}
/** Savings / current account statement, month by month. */
export interface BorrowerAccount {
type: 'Savings' | 'Current';
accountNo: string;
months: AccountMonth[];
}
export interface ProductEligibility {
productId: number;
productName: string;
eligible: boolean;
eligibleAmount?: number;
sharePct: number;
/** Shares to be taken with this loan (incl. any existing shortfall). */
shareToBuy?: number;
netInHand?: number;
minAmount?: number;
maxAmount?: number;
passed: string[];
failed: string[];
notes: string[];
}
export interface Borrower {
clientId: number;
clientName: string;
clientAccountNo: string;
category: BorrowerCategory;
activeLoans: number;
closedLoans: number;
writtenOffLoans: number;
outstanding: number;
maxDpd: number;
worstStage?: string;
monthlyIncome?: number;
age?: number;
depositBalance: number;
currentEmi: number;
eligibleProducts: number;
/** Repayment record over all loans: EMIs fallen due and how many were paid late. */
emisPaid: number;
emisLate: number;
shareHeld: number;
shareRequired: number;
/** Six-month averages of the operative account. */
accountType: 'Savings' | 'Current';
avgCredits: number;
avgDebits: number;
returns: number;
accounts?: BorrowerAccount[];
loans?: BorrowerLoan[];
eligibility?: ProductEligibility[];
}
/** Loan Eligibility (AI / Intelligence – Lending & Risk): demo data, worked out on the eligibility rules. */
@Injectable({ providedIn: 'root' })
export class LoanEligibilityService {
getSummary(): Observable<LoanEligibilitySummary> {
return of(demoSummary()).pipe(delay(2800));
}
getBorrowers(category: BorrowerCategory | '', search: string): Observable<Borrower[]> {
return of(demoBorrowers(category, search)).pipe(delay(700));
}
getBorrower(clientId: number): Observable<Borrower> {
const b = demoBorrower(clientId);
return b ? of(b).pipe(delay(900)) : throwError(() => new Error('Borrower not found'));
}
}