feat(investment,npa): RBI-grounded targets, GL-tracked interest posting, date/search pickers
- Correct Investment portfolio allocation and Loan Origination product-mix targets against RBI's UCB SLR/Non-SLR framework and PSL circulars, with a Target Basis column distinguishing RBI-mandated vs board-policy rows (Excel export included). - Expand Investment holdings dataset with more near-term maturities so the Due-Date Diary reflects a realistic spread across FD/Govt Security/Non-SLR/Bond. - Add From/To period-based Interest Calculation & Post (with GL selection for both posting and receiving) across the Investment Interest module, FD Entry and Bond Entry screens; fix a bug where a posted period kept re-appearing as due since accrual wasn't tracked per-holding. - Add a reusable DD-MM-YYYY date-picker component and roll it out across all Investment date fields. - NPA Summary Report: drop SMA-0/1/2 from the stage-wise table (kept in Day-wise Overdue only). - NPA Recovery Report: add Account Type / NPA Category / Target-vs-Actual columns, a shared Account Type filter driving both the account picker and the register, and a searchable (fixed-position, not clipped by card overflow) account select for long lists. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1470,16 +1470,30 @@ export function branchTargetAmount(branchCode: string): number {
|
||||
return BRANCH_DISBURSEMENT_TARGET[branchCode] || 0;
|
||||
}
|
||||
|
||||
/** Target product mix (% of total disbursement) — weighted towards secured Housing/Vehicle
|
||||
* lending plus the priority-sector KCC/Cash Credit book, adding up to 100%. */
|
||||
/**
|
||||
* Target product mix (% of total disbursement). Two of these are genuinely RBI-mandated
|
||||
* Priority Sector Lending sub-targets (RBI Master Direction — Priority Sector Lending: Targets
|
||||
* and Classification, FIDD.CO.Plan.BC.13/04.09.01/2020-21, as extended to UCBs) —
|
||||
* • Agriculture: 18% of Adjusted Net Bank Credit (ANBC) — mapped here to Kisan Credit Card.
|
||||
* • Micro Enterprises: 7.5% of ANBC — mapped here to Cash Credit (MSME).
|
||||
* RBI sets these as a % of the BANK'S WHOLE loan book (ANBC), not of any one product line's own
|
||||
* disbursement — shown here against this module's own mix as the closest available proxy, since
|
||||
* this demo has no bank-wide ANBC figure to check against. The remaining five products (Housing,
|
||||
* Vehicle, Gold, Personal, Education) have no RBI-mandated minimum share of their own — Housing
|
||||
* and Education are Priority-Sector-*eligible* within RBI's loan-amount ceilings but aren't
|
||||
* separately targeted, and Vehicle/Gold/Personal aren't Priority Sector categories at all — so
|
||||
* their split below is an internal business-plan assumption, not a regulatory requirement.
|
||||
* (RBI's other PSL sub-targets — Weaker Sections 12%, overall PSL 40% — cut across products by
|
||||
* borrower category rather than by loan type, so they aren't represented as their own row here.)
|
||||
*/
|
||||
export const PRODUCT_TARGET_PCT: Record<string, number> = {
|
||||
PL: 12,
|
||||
HL: 28,
|
||||
HL: 30,
|
||||
VL: 15,
|
||||
GL: 10,
|
||||
CC: 15,
|
||||
KCC: 12,
|
||||
EL: 8
|
||||
GL: 12,
|
||||
CC: 7.5, // RBI Micro Enterprises PSL sub-target
|
||||
KCC: 18, // RBI Agriculture PSL sub-target
|
||||
EL: 5.5
|
||||
};
|
||||
|
||||
/** Target channel mix (% of disbursement) — the bank's push towards BC/Digital origination and
|
||||
|
||||
@@ -483,10 +483,17 @@
|
||||
|
||||
<div class="pg-card">
|
||||
<div class="pos-section-label">Product Mix — Target % vs Actual % (of Disbursed Amount)</div>
|
||||
<p class="pg-sub npa-report-note">
|
||||
KCC and Cash Credit (MSME) targets are RBI's actual Priority Sector Lending sub-targets — Agriculture 18% and
|
||||
Micro Enterprises 7.5% of Adjusted Net Bank Credit (shown here against this module's own mix, since RBI sets
|
||||
them against the bank's whole loan book, not one product line). The rest are internal business-plan targets, not
|
||||
RBI-mandated.
|
||||
</p>
|
||||
<table class="pg-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Product</th>
|
||||
<th>Target Basis</th>
|
||||
<th class="num">Target %</th>
|
||||
<th class="num col-in">Actual %</th>
|
||||
<th class="num">Variance</th>
|
||||
@@ -497,7 +504,12 @@
|
||||
@for (row of productTargetRows; track row.code) {
|
||||
<tr>
|
||||
<td>{{ row.label }}</td>
|
||||
<td class="num">{{ row.targetPct | number: '1.0-0' }}%</td>
|
||||
<td>
|
||||
<span class="loan-badge" [class.loan-badge--progress]="row.isRbiMandated">
|
||||
{{ row.isRbiMandated ? 'RBI PSL Sub-Target' : 'Internal Target' }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="num">{{ row.targetPct | number: '1.0-1' }}%</td>
|
||||
<td class="num col-in">{{ row.actualPct | number: '1.1-1' }}%</td>
|
||||
<td class="num" [class.col-out]="row.variancePct < 0" [class.col-in]="row.variancePct > 0">
|
||||
{{ row.variancePct > 0 ? '+' : '' }}{{ row.variancePct | number: '1.1-1' }} pp
|
||||
@@ -533,7 +545,7 @@
|
||||
@for (row of channelTargetRows; track row.code) {
|
||||
<tr>
|
||||
<td>{{ row.label }}</td>
|
||||
<td class="num">{{ row.targetPct | number: '1.0-0' }}%</td>
|
||||
<td class="num">{{ row.targetPct | number: '1.0-1' }}%</td>
|
||||
<td class="num col-in">{{ row.actualPct | number: '1.1-1' }}%</td>
|
||||
<td class="num" [class.col-out]="row.variancePct < 0" [class.col-in]="row.variancePct > 0">
|
||||
{{ row.variancePct > 0 ? '+' : '' }}{{ row.variancePct | number: '1.1-1' }} pp
|
||||
|
||||
@@ -71,6 +71,9 @@ interface MixTargetRow {
|
||||
actualPct: number;
|
||||
variancePct: number;
|
||||
status: TargetStatus;
|
||||
/** True only for the two rows whose target is an actual RBI PSL sub-target (Agriculture 18% /
|
||||
* Micro Enterprises 7.5% of ANBC) rather than an internal business-plan assumption. */
|
||||
isRbiMandated: boolean;
|
||||
}
|
||||
|
||||
type ViewId = 'pipeline' | 'new' | 'channel' | 'bc' | 'share' | 'target';
|
||||
@@ -389,7 +392,8 @@ export class LoanPipelineComponent implements OnInit {
|
||||
targetPct,
|
||||
actualPct,
|
||||
variancePct: actualPct - targetPct,
|
||||
status: targetStatus(actualPct, targetPct, 3)
|
||||
status: targetStatus(actualPct, targetPct, 3),
|
||||
isRbiMandated: p.code === 'KCC' || p.code === 'CC'
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -413,7 +417,8 @@ export class LoanPipelineComponent implements OnInit {
|
||||
targetPct,
|
||||
actualPct,
|
||||
variancePct: actualPct - targetPct,
|
||||
status: targetStatus(actualPct, targetPct, 3)
|
||||
status: targetStatus(actualPct, targetPct, 3),
|
||||
isRbiMandated: false
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -626,6 +631,7 @@ export class LoanPipelineComponent implements OnInit {
|
||||
subtitle,
|
||||
headers: [
|
||||
'Mix',
|
||||
'Target Basis',
|
||||
'Target %',
|
||||
'Actual %',
|
||||
'Variance (pp)',
|
||||
@@ -633,6 +639,7 @@ export class LoanPipelineComponent implements OnInit {
|
||||
],
|
||||
widths: [
|
||||
26,
|
||||
18,
|
||||
12,
|
||||
12,
|
||||
14,
|
||||
@@ -641,6 +648,7 @@ export class LoanPipelineComponent implements OnInit {
|
||||
rows: [
|
||||
...this.productTargetRows.map((r) => [
|
||||
`Product — ${r.label}`,
|
||||
r.isRbiMandated ? 'RBI PSL Sub-Target' : 'Internal Target',
|
||||
r.targetPct,
|
||||
Number(r.actualPct.toFixed(1)),
|
||||
Number(r.variancePct.toFixed(1)),
|
||||
@@ -648,6 +656,7 @@ export class LoanPipelineComponent implements OnInit {
|
||||
]),
|
||||
...this.channelTargetRows.map((r) => [
|
||||
`Channel — ${r.label}`,
|
||||
'Internal Target',
|
||||
r.targetPct,
|
||||
Number(r.actualPct.toFixed(1)),
|
||||
Number(r.variancePct.toFixed(1)),
|
||||
|
||||
Reference in New Issue
Block a user