Files
cbsnexora/src/app/clerk/my-disbursement-requests/my-disbursement-requests.component.html
T
Jaanu423andClaude Sonnet 4.6 6cccb58c04 feat(clerk): add collection flow — multi-DR savings to CR GL with maker-checker
- Transaction entry: detect collection mode (N DR savings → 1 CR GL) and disbursement mode (1 DR GL → N CR savings); build dbCr-tagged payload for backend
- Disbursement review: show 'GL Credit (Target)' / 'Debit Entries' labels for collection; fix double-count by summing only DR entries for collection totals; dynamic approve button text
- My disbursement requests: add DR/CR badge column in expanded credit-entries preview
- My requests / withdrawal-requests: minor consistency updates

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 15:28:27 +05:30

207 lines
7.3 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="mdr-page">
<!-- ── HEADER ── -->
<div class="mdr-header">
<div class="mdr-header__left">
<mat-icon class="mdr-header__icon">swap_horiz</mat-icon>
<div>
<div class="mdr-header__title">My Disbursement Requests</div>
<div class="mdr-header__sub">Track your submitted GL disbursement requests.</div>
</div>
</div>
<button type="button" class="mdr-btn mdr-btn--new" (click)="newDisbursement()">
<mat-icon>add</mat-icon>
New Disbursement
</button>
</div>
<!-- ── FILTER BAR ── -->
<div class="mdr-filter-bar">
<select class="mdr-filter-select" [(ngModel)]="filterStatus" (change)="onFilterChange()">
@for (opt of statusOptions; track opt.value) {
<option [value]="opt.value">{{ opt.label }}</option>
}
</select>
<span class="mdr-fb-sep"></span>
<div class="mdr-presets">
@for (p of datePresets; track p.key) {
<button
type="button"
class="mdr-preset-chip"
[class.mdr-preset-chip--active]="activePreset === p.key"
(click)="applyPreset(p.key)"
>
{{ p.label }}
</button>
}
</div>
<span class="mdr-fb-sep"></span>
<div class="mdr-date-range">
<div class="mdr-date-box">
<span class="mdr-date-box__lbl">From</span>
<input
class="mdr-date-box__input"
[matDatepicker]="fromPicker"
[(ngModel)]="fromDate"
[max]="maxDate"
(dateChange)="onFromDateChange()"
readonly
/>
<button type="button" class="mdr-date-box__btn" (click)="fromPicker.open()">
<mat-icon>event</mat-icon>
</button>
<mat-datepicker #fromPicker></mat-datepicker>
</div>
<span class="mdr-date-range__sep">—</span>
<div class="mdr-date-box">
<span class="mdr-date-box__lbl">To</span>
<input
class="mdr-date-box__input"
[matDatepicker]="toPicker"
[(ngModel)]="toDate"
[min]="fromDate"
[max]="maxDate"
(dateChange)="onToDateChange()"
readonly
/>
<button type="button" class="mdr-date-box__btn" (click)="toPicker.open()">
<mat-icon>event</mat-icon>
</button>
<mat-datepicker #toPicker></mat-datepicker>
</div>
</div>
<button type="button" class="mdr-btn mdr-btn--refresh" (click)="load()" [disabled]="loading">
<mat-icon>refresh</mat-icon>
</button>
</div>
<!-- ── TABLE ── -->
@if (loading) {
<div class="mdr-empty">
<p class="mdr-empty__title">Loading…</p>
</div>
} @else if (loaded && requests.length === 0) {
<div class="mdr-empty">
<i class="fas fa-inbox mdr-empty__icon"></i>
<p class="mdr-empty__title">No disbursement requests found</p>
<p class="mdr-empty__text">You have not submitted any disbursement requests yet.</p>
<button type="button" class="mdr-btn mdr-btn--new" style="margin-top: 12px" (click)="newDisbursement()">
<mat-icon>add</mat-icon>
New Disbursement
</button>
</div>
} @else {
<div class="mdr-table-wrap">
<table class="mdr-table">
<thead>
<tr>
<th>Voucher No</th>
<th>GL Account</th>
<th class="num">DR Amount</th>
<th>Credit Entries</th>
<th>Payment Mode</th>
<th>Reviewed By</th>
<th>Submitted At</th>
<th>Status</th>
</tr>
</thead>
<tbody>
@for (r of requests; track r.id) {
<tr class="mdr-row">
<td class="cell-mono mdr-voucher">{{ r.voucher_no || '—' }}</td>
<td>
<span class="cell-mono">{{ r.gl_account_no }}</span>
<span class="mdr-gl-name">{{ r.gl_account_name }}</span>
</td>
<td class="num mdr-amount">₹{{ r.dr_amount | number: '1.2-2' }}</td>
<td>
<button type="button" class="mdr-credit-badge mdr-credit-badge--btn" (click)="toggleExpand(r.id)">
{{ creditCount(r) }} account{{ creditCount(r) !== 1 ? 's' : '' }}
<mat-icon class="mdr-credit-chevron" [class.mdr-credit-chevron--open]="expandedIds.has(r.id)">
expand_more
</mat-icon>
</button>
</td>
<td>{{ r.payment_type_name || 'Transfer' }}</td>
<td>{{ r.manager_name || r.manager_username || '—' }}</td>
<td class="mdr-dt">{{ formatDateTime(r.submitted_at) }}</td>
<td>
<span class="mdr-status" [ngClass]="statusClass(r.status)">{{ statusLabel(r.status) }}</span>
</td>
</tr>
@if (expandedIds.has(r.id)) {
<tr class="mdr-expand-row">
<td colspan="8" class="mdr-expand-cell">
<div class="mdr-credit-preview">
<table class="mdr-credit-table">
<thead>
<tr>
<th>DR/CR</th>
<th>Account No</th>
<th>Account Name</th>
<th>Type</th>
<th class="num">Amount (₹)</th>
</tr>
</thead>
<tbody>
@for (ce of getCreditEntries(r); track ce.accountNo) {
<tr>
<td>
<span
class="mdr-actype"
[style.background]="ce.dbCr === 'Dr' ? '#fee2e2' : '#dcfce7'"
[style.color]="ce.dbCr === 'Dr' ? '#991b1b' : '#166534'"
>
{{ ce.dbCr || 'CR' }}
</span>
</td>
<td class="cell-mono">{{ ce.accountNo || '—' }}</td>
<td>{{ ce.accountName || '—' }}</td>
<td>
<span class="mdr-actype">{{ ce.accountType || '—' }}</span>
</td>
<td class="num mdr-ce-amount">{{ ce.amount | number: '1.2-2' }}</td>
</tr>
}
</tbody>
</table>
</div>
</td>
</tr>
}
@if (r.status === 'REJECTED' && r.rejection_reason) {
<tr class="mdr-reason-row">
<td colspan="8" class="mdr-reason-cell">
<mat-icon class="mdr-reason-icon">info</mat-icon>
{{ r.rejection_reason }}
</td>
</tr>
}
}
</tbody>
</table>
</div>
<mat-paginator
[length]="totalRecords"
[pageSize]="pageSize"
[pageSizeOptions]="pageSizeOptions"
[pageIndex]="pageIndex"
showFirstLastButtons
(page)="onPageChange($event)"
></mat-paginator>
}
</div>