Files
cbsnexora/src/app/tasks/checker-inbox-and-tasks-tabs/disbursement-requests/disbursement-requests.component.html
T
Jaanu423andClaude Sonnet 4.6 cbb2bd7c58 feat(bank-transfer): convert bank transfer to maker-checker approval flow
- submitBankTransfer() now calls submit() with requestType='BANK_TRANSFER'
  instead of the immediate-execution /banktransfer endpoint
- Confirm dialog updated: 'Submit for Approval' instead of 'Execute Transfer'
- disbursement-review: isBankTransferMode getter, separate DR/CR entry tables,
  'Approve Bank Transfer' button label, correct isCollectionMode guard
- Disbursement Requests checker inbox: Type badge (Bank Transfer/Collection/
  Disbursement) column, GL column shows 'Intra-bank transfer' for BT requests
- Checker inbox tab renamed to 'Disbursement & Transfers'

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 14:46:26 +05:30

188 lines
6.2 KiB
HTML

<!--
Copyright since 2025 Mifos Initiative
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
-->
<div class="cv-tab-content wri-tab">
<!-- ── TITLE BAR ── -->
<div class="wri-action-bar">
<div class="wri-action-bar__left">
<mat-icon class="wri-action-bar__icon">swap_horiz</mat-icon>
<div>
<div class="wri-action-bar__title">Disbursement &amp; Transfer Requests</div>
<div class="wri-action-bar__sub">
Review, approve or reject clerk disbursement, collection, and bank transfer requests.
</div>
</div>
</div>
</div>
<!-- ── FILTER BAR ── -->
<div class="wri-filter-bar">
<select class="wri-filter-select" [(ngModel)]="filterStatus" (change)="onFilterChange()">
@for (opt of statusOptions; track opt.value) {
<option [value]="opt.value">{{ opt.label }}</option>
}
</select>
<span class="wri-fb-sep"></span>
<div class="wri-presets">
@for (p of datePresets; track p.key) {
<button
type="button"
class="wri-preset-chip"
[class.wri-preset-chip--active]="activePreset === p.key"
(click)="applyPreset(p.key)"
>
{{ p.label }}
</button>
}
</div>
<span class="wri-fb-sep"></span>
<div class="wri-date-range">
<div class="wri-date-box">
<span class="wri-date-box__lbl">From</span>
<input
class="wri-date-box__input"
[matDatepicker]="fromPicker"
[(ngModel)]="fromDate"
[max]="maxDate"
(dateChange)="onFromDateChange()"
readonly
/>
<button type="button" class="wri-date-box__btn" (click)="fromPicker.open()">
<mat-icon>event</mat-icon>
</button>
<mat-datepicker #fromPicker></mat-datepicker>
</div>
<span class="wri-date-range__sep">—</span>
<div class="wri-date-box">
<span class="wri-date-box__lbl">To</span>
<input
class="wri-date-box__input"
[matDatepicker]="toPicker"
[(ngModel)]="toDate"
[min]="fromDate"
[max]="maxDate"
(dateChange)="onToDateChange()"
readonly
/>
<button type="button" class="wri-date-box__btn" (click)="toPicker.open()">
<mat-icon>event</mat-icon>
</button>
<mat-datepicker #toPicker></mat-datepicker>
</div>
</div>
<button type="button" class="wri-btn wri-btn--refresh" (click)="load()" [disabled]="loading">
<mat-icon>refresh</mat-icon>
</button>
</div>
<!-- ── TABLE ── -->
@if (loading) {
<div class="empty-state">
<p class="empty-title">Loading…</p>
</div>
} @else if (loaded && requests.length === 0) {
<div class="empty-state">
<i class="fas fa-inbox empty-icon"></i>
<p class="empty-title">No disbursement requests</p>
<p class="empty-text">
@if (filterStatus === 'PENDING') {
There are no pending disbursement requests waiting for review.
} @else {
No {{ filterStatus | lowercase }} disbursement requests found.
}
</p>
</div>
} @else {
<div class="wri-table-wrap">
<table class="wri-table">
<thead>
<tr>
<th class="wri-th-id">Voucher No</th>
<th>Type</th>
<th>GL Account / Details</th>
<th class="num">Amount</th>
<th>Entries</th>
<th>Clerk</th>
<th>Reviewed By</th>
<th>Submitted At</th>
<th>Status</th>
<th class="wri-th-action">Action</th>
</tr>
</thead>
<tbody>
@for (r of requests; track r.id) {
<tr class="wri-row" (click)="review(r)">
<td class="cell-mono wri-voucher">{{ r.voucher_no || '—' }}</td>
<td>
<span
class="wri-credit-badge"
[style.background]="
r.request_type === 'BANK_TRANSFER'
? '#e3f2fd'
: r.request_type === 'COLLECTION'
? '#fce4ec'
: '#e8f5e9'
"
>
{{
r.request_type === 'BANK_TRANSFER'
? 'Bank Transfer'
: r.request_type === 'COLLECTION'
? 'Collection'
: 'Disbursement'
}}
</span>
</td>
<td>
@if (r.request_type === 'BANK_TRANSFER') {
<span class="wri-gl-name">Intra-bank transfer</span>
} @else {
<span class="cell-mono">{{ r.gl_account_no }}</span>
<span class="wri-gl-name">{{ r.gl_account_name }}</span>
}
</td>
<td class="num wri-amount">₹{{ r.dr_amount | number: '1.2-2' }}</td>
<td class="wri-credit-count">
<span class="wri-credit-badge">{{ creditCount(r) }} account{{ creditCount(r) !== 1 ? 's' : '' }}</span>
</td>
<td>{{ r.clerk_name }}</td>
<td>{{ r.manager_name || r.manager_username || '—' }}</td>
<td class="wri-dt">{{ formatDateTime(r.submitted_at) }}</td>
<td>
<span class="wri-status" [ngClass]="statusClass(r.status)">
{{ statusLabel(r.status) }}
</span>
</td>
<td class="wri-action-cell" (click)="$event.stopPropagation()">
<button type="button" class="wri-btn wri-btn--review" (click)="review(r)">
<mat-icon>rate_review</mat-icon>
Review
</button>
</td>
</tr>
}
</tbody>
</table>
</div>
<mat-paginator
[length]="totalRecords"
[pageSize]="pageSize"
[pageSizeOptions]="pageSizeOptions"
[pageIndex]="pageIndex"
showFirstLastButtons
(page)="onPageChange($event)"
></mat-paginator>
}
</div>