feat(cashier): integrate expected balance, settlement verification, and reconciliation checks

This commit is contained in:
Jaanu423
2026-05-28 22:30:08 +05:30
parent 7ccaffa7f1
commit 6433ae068d
10 changed files with 1362 additions and 201 deletions
@@ -83,7 +83,7 @@
<td>{{ r.fromParty }}</td>
<td>{{ r.toParty }}</td>
<td class="num">₹{{ r.amount | number: '1.2-2' }}</td>
<td>{{ r.note || '—' }}</td>
<td class="td-note">{{ r.note || '—' }}</td>
<td>{{ r.performedByUsername || '—' }}</td>
<td style="text-align: center">
<span class="badge" [class.badge-active]="!r.isReversed" [class.badge-reversed]="r.isReversed">
@@ -91,11 +91,21 @@
</span>
</td>
<td style="text-align: center">
@if (!r.isReversed) {
<button type="button" class="pg-btn pg-btn--ghost btn-sm" (click)="startReverse(r)">
<mat-icon>undo</mat-icon>
<div class="action-btns">
<button
type="button"
class="pg-btn pg-btn--ghost btn-sm btn-view"
title="View details"
(click)="viewDetail(r)"
>
<mat-icon>visibility</mat-icon>
</button>
}
@if (!r.isReversed) {
<button type="button" class="pg-btn pg-btn--ghost btn-sm" title="Reverse" (click)="startReverse(r)">
<mat-icon>undo</mat-icon>
</button>
}
</div>
</td>
</tr>
}
@@ -104,3 +114,126 @@
</div>
}
</ng-template>
<!-- ── Detail Overlay ── -->
@if (detail) {
<div class="detail-overlay" (click)="closeDetail()">
<div class="detail-panel" (click)="$event.stopPropagation()">
<!-- Header -->
<div class="detail-panel__head">
<div class="detail-panel__title">
<mat-icon>{{ detail.row.type === 'settlement' ? 'account_balance_wallet' : 'swap_horiz' }}</mat-icon>
<div>
<span class="detail-panel__type">{{ typeLabel(detail.row.type) }}</span>
<span class="detail-panel__id">#{{ detail.row.id }}</span>
</div>
</div>
<button type="button" class="detail-panel__close" (click)="closeDetail()">
<mat-icon>close</mat-icon>
</button>
</div>
<!-- Meta grid -->
<div class="detail-meta">
<div class="detail-meta__item">
<span class="detail-meta__label">From</span>
<span class="detail-meta__val">{{ detail.row.fromParty || '—' }}</span>
</div>
<div class="detail-meta__item">
<span class="detail-meta__label">To</span>
<span class="detail-meta__val">{{ detail.row.toParty || '—' }}</span>
</div>
<div class="detail-meta__item">
<span class="detail-meta__label">Date</span>
<span class="detail-meta__val">{{ detail.row.date }}</span>
</div>
<div class="detail-meta__item">
<span class="detail-meta__label">Total Amount</span>
<span class="detail-meta__val detail-meta__val--amount">₹{{ detail.row.amount | number: '1.2-2' }}</span>
</div>
<div class="detail-meta__item">
<span class="detail-meta__label">Performed By</span>
<span class="detail-meta__val">{{ detail.row.performedByUsername || '—' }}</span>
</div>
<div class="detail-meta__item">
<span class="detail-meta__label">Created At</span>
<span class="detail-meta__val">{{ detail.row.createdAt || '—' }}</span>
</div>
<div class="detail-meta__item detail-meta__item--full">
<span class="detail-meta__label">Note</span>
<span class="detail-meta__val">{{ detail.row.note || '—' }}</span>
</div>
<div class="detail-meta__item">
<span class="detail-meta__label">Status</span>
<span
class="badge"
[class.badge-active]="!detail.row.isReversed"
[class.badge-reversed]="detail.row.isReversed"
>
{{ detail.row.isReversed ? 'Reversed' : 'Active' }}
</span>
</div>
</div>
<!-- Reversal info (if reversed) -->
@if (detail.row.isReversed) {
<div class="detail-reversal">
<mat-icon>undo</mat-icon>
<div>
<strong>Reversed</strong>
@if (detail.row.reversedAt) {
<span> on {{ detail.row.reversedAt }}</span>
}
@if (detail.row.reverseReason) {
<span class="detail-reversal__reason"> — {{ detail.row.reverseReason }}</span>
}
</div>
</div>
}
<!-- Denomination breakdown -->
<div class="detail-denom-head">
<mat-icon>payments</mat-icon>
Denomination Breakdown
</div>
@if (detail.loading) {
<div class="pg-empty" style="padding: 20px 0">Loading denomination details…</div>
} @else if (detail.denominations.length === 0) {
<div class="pg-empty" style="padding: 20px 0">No denomination data recorded.</div>
} @else {
<table class="pg-table detail-denom-table">
<thead>
<tr>
<th>Denomination</th>
<th style="text-align: center">Count</th>
<th class="num">Total</th>
</tr>
</thead>
<tbody>
@for (d of detail.denominations; track d.denominationValue) {
<tr>
<td>
<span class="pg-chip">₹{{ d.denominationValue }}</span>
</td>
<td style="text-align: center; font-weight: 600">{{ d.count }}</td>
<td class="num">₹{{ d.totalAmount | number: '1.2-2' }}</td>
</tr>
}
</tbody>
<tfoot>
<tr class="detail-denom-total">
<td><strong>Total</strong></td>
<td style="text-align: center">
<strong>{{ totalCount(detail.denominations) }}</strong>
</td>
<td class="num">
<strong>₹{{ detail.row.amount | number: '1.2-2' }}</strong>
</td>
</tr>
</tfoot>
</table>
}
</div>
</div>
}