feat(npa): add Undebited Interest Recovery Report, fix note text width

Adds a 10th NPA report tracking memorandum "undebited interest" per IRAC
norms (accrued vs cash-recovered vs balance), wired into Export to Excel
and the NPA mega-menu. Also fixes a narrow-width text wrap on the report's
description note (new .npa-report-note class overriding pg-sub's 560px cap).
This commit is contained in:
2026-08-02 08:34:03 +05:30
parent 90beea64cb
commit 27cdaf7fc2
5 changed files with 220 additions and 10 deletions
@@ -784,7 +784,97 @@
</div>
}
<!-- ===================== 08 PROBABLE NPA ===================== -->
<!-- ===================== 08 UNDEBITED INTEREST RECOVERY REPORT ===================== -->
@if (activeReport === 'undebited-interest') {
<div class="pg-card">
<div class="pos-section-label">
Undebited Interest Recovery Report — Memorandum Interest Held Outside the Loan Account (IRAC Norms)
</div>
<p class="pg-sub npa-report-note">
Once an account turns NPA, interest is no longer debited to the borrower's loan account or recognised as income
— it is tracked here as memorandum "undebited interest" and recognised only when actually recovered in cash.
Cash recovered is appropriated to this bucket first; any balance beyond it reduces principal.
</p>
<div class="pg-table-scroll">
<table class="pg-table">
<thead>
<tr>
<th>Account No</th>
<th>Customer</th>
<th>Branch</th>
<th>Stage</th>
<th>NPA Since</th>
<th class="num">Days NPA</th>
<th class="num">Rate</th>
<th class="num col-out">Undebited Interest Accrued</th>
<th class="num col-in">Interest Recovered (Cash)</th>
<th class="num">Undebited Interest Balance</th>
</tr>
</thead>
<tbody>
@for (a of paged(npaAccounts); track a.accountNo) {
<tr>
<td>
<span class="pg-chip">{{ a.accountNo }}</span>
</td>
<td>{{ a.customerName }}</td>
<td>{{ a.branchName }}</td>
<td>
<span [class]="badgeClass(stage(a))">{{ stageLabel(stage(a)) }}</span>
</td>
<td>{{ npaSince(a) }}</td>
<td class="num">{{ daysSinceNpaOf(a) }}</td>
<td class="num">{{ a.interestRate }}%</td>
<td class="num col-out">₹{{ interestRev(a) | number: '1.0-0' }}</td>
<td class="num col-in">₹{{ interestRecoveredCashOf(a) | number: '1.0-0' }}</td>
<td class="num">₹{{ undebitedInterestBalanceOf(a) | number: '1.0-0' }}</td>
</tr>
} @empty {
<tr>
<td colspan="10" class="pg-empty">No NPA accounts in this branch.</td>
</tr>
}
</tbody>
<tfoot>
<tr class="cctr-total-row">
<td colspan="7">Total ({{ npaAccounts.length }} accounts)</td>
<td class="num">₹{{ undebitedInterestAccruedTotal | number: '1.0-0' }}</td>
<td class="num">₹{{ interestRecoveredCashTotal | number: '1.0-0' }}</td>
<td class="num">₹{{ undebitedInterestBalanceTotal | number: '1.0-0' }}</td>
</tr>
</tfoot>
</table>
</div>
@if (npaAccounts.length > pageSize) {
<div class="pg-pagination">
<span class="pg-pagination__info"
>Showing {{ rangeStart(npaAccounts) }}–{{ rangeEnd(npaAccounts) }} of {{ npaAccounts.length }}</span
>
<div class="pg-pagination__controls">
<button
type="button"
class="pg-btn pg-btn--ghost"
[disabled]="currentPage === 1"
(click)="goToPage(currentPage - 1, npaAccounts)"
>
‹ Prev
</button>
<span class="pg-pagination__page">Page {{ currentPage }} of {{ pageCount(npaAccounts) }}</span>
<button
type="button"
class="pg-btn pg-btn--ghost"
[disabled]="currentPage === pageCount(npaAccounts)"
(click)="goToPage(currentPage + 1, npaAccounts)"
>
Next ›
</button>
</div>
</div>
}
</div>
}
<!-- ===================== 09 PROBABLE NPA ===================== -->
@if (activeReport === 'probable') {
<div class="pg-card">
<div class="pos-section-label">
@@ -871,7 +961,7 @@
</div>
}
<!-- ===================== 09 SMA REPORT ===================== -->
<!-- ===================== 10 SMA REPORT ===================== -->
@if (activeReport === 'sma') {
<div class="pg-card">
<div class="pos-section-label">Special Mention Accounts — SMA-0 (1–30d) / SMA-1 (31–60d) / SMA-2 (61–90d)</div>