feat(loan-origination): guarantor share-account verification, committee resolution gating, legal doc uploads, CIC score-detection fixes, and interest/share rate chart
build-run / Run Lint, Build and Deploy (push) Canceled after 0s
Publish Image in Docker Hub / build (push) Canceled after 0s
Playwright E2E Tests / Run Playwright Tests (push) Canceled after 0s
Tests / testRigor (push) Canceled after 0s

- Guarantor must be a real existing client with a verified active share account, with clickable share-account chips
- Loan Committee Approval now requires Resolution No./Date plus a full application report before approving
- Loan Committee gets its own pre-filtered pipeline view via a menu link and stage query param
- Legal Approval stage gets a multi-file document upload checklist with add-more support
- CIC PDF parser: item-level score detection before line-based fallback, fixing font-size-driven line-merging misdetection
- New Interest & Share Rate Chart tab: per-product interest/tenure bands and per-amount-slab Share Capital linkage requirements
This commit is contained in:
2026-08-14 14:49:22 +05:30
parent 1d1e76497c
commit 2d93f80d50
8 changed files with 773 additions and 38 deletions
@@ -116,6 +116,14 @@
>
Target vs Actual
</button>
<button
type="button"
class="pg-btn pg-btn--ghost"
[class.pg-btn--active]="activeView === 'rates'"
(click)="setView('rates')"
>
Interest &amp; Share Rate Chart
</button>
</div>
<!-- ===================== PIPELINE ===================== -->
@@ -614,6 +622,103 @@
</table>
</div>
}
<!-- ===================== INTEREST & SHARE RATE CHART ===================== -->
@if (activeView === 'rates') {
<div class="pg-card">
<div class="pos-section-label">Product-wise — Interest Rate &amp; Share Capital Required</div>
<p class="pg-sub npa-report-note">
Total Interest is an illustrative simple-interest figure (Amount x Rate x Tenure in years) at the product's own
min/max amount and tenure band — actual repayment is on a reducing balance and depends on the amount and tenure
chosen at sanction. Share Capital Required is the minimum a borrower must hold per bank bye-laws, proportional
to the loan amount.
</p>
<div class="pg-table-scroll">
<table class="pg-table">
<thead>
<tr>
<th>Product</th>
<th>Type</th>
<th class="num">Amount Range</th>
<th class="num">Interest Rate (p.a.)</th>
<th class="num">Tenure Range</th>
<th class="num">Illustrative Total Interest</th>
<th class="num">Share Capital Required</th>
<th class="num">Illustrative Share Amount</th>
</tr>
</thead>
<tbody>
@for (p of products; track p.code) {
<tr>
<td>{{ p.name }}</td>
<td>
<span
class="loan-badge"
[class.loan-badge--progress]="p.secured"
[class.loan-badge--hold]="!p.secured"
>
{{ p.secured ? 'Secured' : 'Unsecured' }}
</span>
</td>
<td class="num">₹{{ p.minAmt | number: '1.0-0' }} – ₹{{ p.maxAmt | number: '1.0-0' }}</td>
<td class="num">{{ p.minRate | number: '1.1-1' }}% – {{ p.maxRate | number: '1.1-1' }}%</td>
<td class="num">{{ p.minTenure }} – {{ p.maxTenure }} months</td>
<td class="num">
₹{{ illustrativeInterest(p.minAmt, p.minRate, p.minTenure) | number: '1.0-0' }} – ₹{{
illustrativeInterest(p.maxAmt, p.maxRate, p.maxTenure) | number: '1.0-0'
}}
</td>
<td class="num">{{ p.shareLinkagePercent | number: '1.1-1' }}%</td>
<td class="num">
₹{{ p.minAmt * (p.shareLinkagePercent / 100) | number: '1.0-0' }} – ₹{{
p.maxAmt * (p.shareLinkagePercent / 100) | number: '1.0-0'
}}
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<div class="pg-card">
<div class="pos-section-label">Amount Slab-wise — Share Capital Required (All Products)</div>
<p class="pg-sub npa-report-note">
A general slab schedule by loan quantum, independent of product — where this differs from the product-wise
minimum above, whichever is higher governs the actual requirement.
</p>
<table class="pg-table">
<thead>
<tr>
<th class="num">Loan Amount Slab</th>
<th class="num">Share Capital Required</th>
<th class="num">Illustrative Share Amount</th>
</tr>
</thead>
<tbody>
@for (row of shareLinkageSlabRows; track row.minAmt) {
<tr>
<td class="num">
@if (row.maxAmt !== null) {
₹{{ row.minAmt | number: '1.0-0' }} – ₹{{ row.maxAmt | number: '1.0-0' }}
} @else {
Above ₹{{ row.minAmt | number: '1.0-0' }}
}
</td>
<td class="num">{{ row.sharePercent | number: '1.1-1' }}%</td>
<td class="num">
@if (row.shareAtMax !== null) {
₹{{ row.shareAtMin | number: '1.0-0' }} – ₹{{ row.shareAtMax | number: '1.0-0' }}
} @else {
From ₹{{ row.shareAtMin | number: '1.0-0' }}
}
</td>
</tr>
}
</tbody>
</table>
</div>
}
</div>
<div class="inv-toast" [class.show]="toastVisible">{{ toastMsg }}</div>