feat(cashier): denomination overdraft validation, exchange detail fix, cash exchange in reports

- Savings/Current/FD/RD withdrawal forms: card-style overdraft warning when
  requested denomination count exceeds cashier stock; submit blocked on overdraft
- Cash History detail view: show both RECEIVED and GIVEN denomination breakdowns
  for Cash Exchange (previously only RECEIVED side was displayed)
- Closing Cash Report: add Cash Exchanges section (denomination-wise received/given/net)
- Excess Transaction Report: include cash exchanges >= threshold with Type badge
  (Exchange/Txn) and ID Proof column for RBI/AML compliance
- cashier-shared.scss: etr-badge and closing-exchange-head styles
- Cash Exchange entry: overdraft warning redesigned to cx-overdraft-card BEM layout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jaanu423
2026-06-01 10:10:17 +05:30
co-authored by Claude Sonnet 4.6
parent 51495f8eb8
commit f291e4da5b
24 changed files with 1339 additions and 25 deletions
@@ -133,8 +133,109 @@
</table>
}
@if (loaded && rows.length === 0) {
@if (loaded && rows.length === 0 && exchangeRows.length === 0) {
<div class="pg-empty">No cash denomination data for this date.</div>
}
</div>
<!-- Cash Exchange section — separate from deposits/withdrawals (net monetary = ₹0) -->
@if (exchangeRows.length > 0) {
<div class="pg-card">
<div class="closing-exchange-head">
<mat-icon>swap_horiz</mat-icon>
<div>
<div class="closing-exchange-title">Cash Exchanges</div>
<div class="closing-exchange-sub">Denomination swaps recorded on this date (net cash impact: ₹0.00)</div>
</div>
</div>
@if (exchangeNoteRows.length > 0) {
<div class="pos-section-label">Notes</div>
<table class="pg-table">
<thead>
<tr>
<th>Denomination</th>
<th class="num col-in">Received Pcs</th>
<th class="num col-in">Received Amt</th>
<th class="num col-out">Given Pcs</th>
<th class="num col-out">Given Amt</th>
<th class="num col-net">Net Pcs</th>
<th class="num col-net">Net Amount</th>
</tr>
</thead>
<tbody>
@for (r of exchangeNoteRows; track r.denominationId) {
<tr>
<td>
<span class="pg-chip">₹{{ r.denominationValue }}</span>
</td>
<td class="num col-in">{{ r.receivedCount }}</td>
<td class="num col-in">₹{{ r.receivedAmount | number: '1.2-2' }}</td>
<td class="num col-out">{{ r.givenCount }}</td>
<td class="num col-out">₹{{ r.givenAmount | number: '1.2-2' }}</td>
<td
class="num col-net"
[style.color]="r.netCount > 0 ? '#16a34a' : r.netCount < 0 ? '#dc2626' : '#94a3b8'"
>
{{ r.netCount > 0 ? '+' : '' }}{{ r.netCount }}
</td>
<td
class="num col-net"
[style.color]="r.netCount > 0 ? '#16a34a' : r.netCount < 0 ? '#dc2626' : '#94a3b8'"
>
{{ r.netCount >= 0 ? '' : '−' }}₹{{
(r.netAmount < 0 ? -r.netAmount : r.netAmount) | number: '1.2-2'
}}
</td>
</tr>
}
</tbody>
</table>
}
@if (exchangeCoinRows.length > 0) {
<div class="pos-section-label pos-section-label--coin">Coins</div>
<table class="pg-table">
<thead>
<tr>
<th>Denomination</th>
<th class="num col-in">Received Pcs</th>
<th class="num col-in">Received Amt</th>
<th class="num col-out">Given Pcs</th>
<th class="num col-out">Given Amt</th>
<th class="num col-net">Net Pcs</th>
<th class="num col-net">Net Amount</th>
</tr>
</thead>
<tbody>
@for (r of exchangeCoinRows; track r.denominationId) {
<tr>
<td>
<span class="pg-chip pg-chip--coin">₹{{ r.denominationValue }}</span>
</td>
<td class="num col-in">{{ r.receivedCount }}</td>
<td class="num col-in">₹{{ r.receivedAmount | number: '1.2-2' }}</td>
<td class="num col-out">{{ r.givenCount }}</td>
<td class="num col-out">₹{{ r.givenAmount | number: '1.2-2' }}</td>
<td
class="num col-net"
[style.color]="r.netCount > 0 ? '#16a34a' : r.netCount < 0 ? '#dc2626' : '#94a3b8'"
>
{{ r.netCount > 0 ? '+' : '' }}{{ r.netCount }}
</td>
<td
class="num col-net"
[style.color]="r.netCount > 0 ? '#16a34a' : r.netCount < 0 ? '#dc2626' : '#94a3b8'"
>
{{ r.netCount >= 0 ? '' : '−' }}₹{{
(r.netAmount < 0 ? -r.netAmount : r.netAmount) | number: '1.2-2'
}}
</td>
</tr>
}
</tbody>
</table>
}
</div>
}
</div>