177 lines
5.8 KiB
HTML
177 lines
5.8 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">
|
|
<div class="wri-action-bar">
|
|
<div class="wri-action-bar__left">
|
|
<mat-icon class="wri-action-bar__icon">savings</mat-icon>
|
|
<div>
|
|
<div class="wri-action-bar__title">DDS Approvals</div>
|
|
<div class="wri-action-bar__sub">
|
|
Review, approve or reject DDS entries - transfers, payouts, early closures, receipts applied and postings.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<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>
|
|
|
|
@if (loading) {
|
|
<div class="empty-state">
|
|
<p class="empty-title">Loading…</p>
|
|
</div>
|
|
} @else if (loaded && entries.length === 0) {
|
|
<div class="empty-state">
|
|
<i class="fas fa-inbox empty-icon"></i>
|
|
<p class="empty-title">No DDS entries</p>
|
|
<p class="empty-text">
|
|
@if (filterStatus === 'PENDING') {
|
|
There are no DDS entries waiting for approval.
|
|
} @else {
|
|
No {{ filterStatus | lowercase }} DDS entries 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>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 (e of pagedEntries; track e.id) {
|
|
<tr class="wri-row" (click)="review(e)">
|
|
<td class="cell-mono wri-voucher">
|
|
{{ e.voucherNo || '—' }}
|
|
@if (e.voucherCancelled) {
|
|
<span class="wri-gl-name">(cancelled)</span>
|
|
}
|
|
</td>
|
|
<td>
|
|
<span class="wri-credit-badge" [style.background]="typeColor(e)">{{ e.type }}</span>
|
|
</td>
|
|
<td>
|
|
<span class="wri-gl-name">{{ e.details || '—' }}</span>
|
|
</td>
|
|
<td class="num wri-amount">
|
|
{{ e.amount !== null && e.amount !== undefined ? '₹' + (e.amount | number: '1.2-2') : '—' }}
|
|
</td>
|
|
<td class="wri-credit-count">
|
|
@if (e.entries) {
|
|
<span class="wri-credit-badge">{{ e.entries }} account{{ e.entries !== 1 ? 's' : '' }}</span>
|
|
} @else {
|
|
—
|
|
}
|
|
</td>
|
|
<td>
|
|
{{ e.makerName || e.maker || '—' }}
|
|
@if (isMine(e) && e.status === 'PENDING') {
|
|
<span class="wri-gl-name">(you)</span>
|
|
}
|
|
</td>
|
|
<td>{{ e.status === 'PENDING' ? '—' : e.checkerName || e.checker || '—' }}</td>
|
|
<td class="wri-dt">{{ formatDateTime(e.madeOn) }}</td>
|
|
<td>
|
|
<span class="wri-status" [ngClass]="statusClass(e.status)">{{ e.status | titlecase }}</span>
|
|
</td>
|
|
<td class="wri-action-cell" (click)="$event.stopPropagation()">
|
|
<button type="button" class="wri-btn wri-btn--review" (click)="review(e)">
|
|
<mat-icon>rate_review</mat-icon>
|
|
Review
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<mat-paginator
|
|
[length]="entries.length"
|
|
[pageSize]="pageSize"
|
|
[pageSizeOptions]="pageSizeOptions"
|
|
[pageIndex]="pageIndex"
|
|
showFirstLastButtons
|
|
(page)="onPageChange($event)"
|
|
></mat-paginator>
|
|
}
|
|
</div>
|