Adds sponsor-dd and sponsor-dd-reconciliation feature modules, a shared customer search dialog, and wires them into routing/shell/ organization screens alongside cashier and deposit-request updates.
269 lines
10 KiB
HTML
269 lines
10 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="pg">
|
|
<!-- ── HEADER ── -->
|
|
<header class="pg-head">
|
|
<div>
|
|
<div class="pg-eyebrow">CASHIER · DEPOSIT REQUESTS</div>
|
|
<h1 class="pg-title">My Deposit Requests</h1>
|
|
<p class="pg-sub">Track the status of your submitted deposit requests awaiting manager approval.</p>
|
|
</div>
|
|
<button type="button" class="pg-btn pg-btn--primary" (click)="newDeposit()">
|
|
<mat-icon>add</mat-icon> New Deposit
|
|
</button>
|
|
</header>
|
|
|
|
<!-- ── FILTER ROW ── -->
|
|
<div class="pg-filter-row">
|
|
<select class="mdr-select" [(ngModel)]="filterStatus" (change)="onFilterChange()">
|
|
@for (opt of statusOptions; track opt.value) {
|
|
<option [value]="opt.value">{{ opt.label }}</option>
|
|
}
|
|
</select>
|
|
|
|
<span class="pg-fb-sep"></span>
|
|
|
|
<div class="pg-presets">
|
|
@for (p of datePresets; track p.key) {
|
|
<button
|
|
type="button"
|
|
class="pg-preset-chip"
|
|
[class.pg-preset-chip--active]="activePreset === p.key"
|
|
(click)="applyPreset(p.key)"
|
|
>
|
|
{{ p.label }}
|
|
</button>
|
|
}
|
|
</div>
|
|
|
|
<span class="pg-fb-sep"></span>
|
|
|
|
<div class="pg-date-range">
|
|
<div class="pg-date-box">
|
|
<span class="pg-date-box__lbl">From</span>
|
|
<input
|
|
class="pg-date-box__input"
|
|
[matDatepicker]="fromPicker"
|
|
[(ngModel)]="fromDate"
|
|
[max]="maxDate"
|
|
(dateChange)="onFromDateChange()"
|
|
readonly
|
|
/>
|
|
<button type="button" class="pg-date-box__btn" (click)="fromPicker.open()">
|
|
<mat-icon>event</mat-icon>
|
|
</button>
|
|
<mat-datepicker #fromPicker></mat-datepicker>
|
|
</div>
|
|
<span class="pg-date-range__sep">—</span>
|
|
<div class="pg-date-box">
|
|
<span class="pg-date-box__lbl">To</span>
|
|
<input
|
|
class="pg-date-box__input"
|
|
[matDatepicker]="toPicker"
|
|
[(ngModel)]="toDate"
|
|
[min]="fromDate"
|
|
[max]="maxDate"
|
|
(dateChange)="onToDateChange()"
|
|
readonly
|
|
/>
|
|
<button type="button" class="pg-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-refresh" (click)="load()" [disabled]="loading">
|
|
<mat-icon>refresh</mat-icon>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- ── TABLE CARD ── -->
|
|
<div class="pg-card">
|
|
@if (loading) {
|
|
<div class="pg-empty">Loading requests…</div>
|
|
} @else if (loaded && requests.length === 0) {
|
|
<div class="pg-empty">
|
|
<mat-icon style="font-size: 36px; color: #cbd5e1; display: block; text-align: center">inbox</mat-icon>
|
|
<p style="margin-top: 8px; color: #94a3b8">No deposit requests found.</p>
|
|
<button type="button" class="pg-btn pg-btn--primary" (click)="newDeposit()" style="margin-top: 12px">
|
|
<mat-icon>add</mat-icon> New Deposit
|
|
</button>
|
|
</div>
|
|
} @else {
|
|
<table class="pg-table mdr-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Voucher No</th>
|
|
<th>Account</th>
|
|
<th>Client</th>
|
|
<th class="num">Amount</th>
|
|
<th>Payment Mode</th>
|
|
<th>Status</th>
|
|
<th>Submitted</th>
|
|
<th>Reviewed By</th>
|
|
<th>Rejection Reason</th>
|
|
<th class="mdr-th-action">Action</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (r of requests; track r.id) {
|
|
<tr
|
|
class="mdr-row"
|
|
[class.mdr-row--pending]="r.status === 'PENDING'"
|
|
[class.mdr-row--approved]="r.status === 'APPROVED'"
|
|
[class.mdr-row--rejected]="r.status === 'REJECTED'"
|
|
>
|
|
<td class="cell-mono mdr-voucher">{{ r.voucher_no || '—' }}</td>
|
|
<td class="cell-mono">{{ r.account_no }}</td>
|
|
<td>{{ r.client_name }}</td>
|
|
<td class="num">₹{{ r.amount | number: '1.2-2' }}</td>
|
|
<td>{{ r.payment_type_name || 'Cash' }}</td>
|
|
<td>
|
|
<span class="mdr-status" [ngClass]="statusClass(r.status)">
|
|
{{ statusLabel(r.status) }}
|
|
</span>
|
|
</td>
|
|
<td>{{ formatDateTime(r.submitted_at) }}</td>
|
|
<td>{{ r.manager_name || r.manager_username || '—' }}</td>
|
|
<td class="mdr-rejection">
|
|
@if (r.status === 'REJECTED' && r.rejection_reason) {
|
|
<span class="mdr-rejection-text" [title]="r.rejection_reason">
|
|
{{ r.rejection_reason | slice: 0 : 60 }}{{ r.rejection_reason?.length > 60 ? '…' : '' }}
|
|
</span>
|
|
} @else {
|
|
<span class="mdr-none">—</span>
|
|
}
|
|
</td>
|
|
<td class="mdr-actions-cell">
|
|
<button type="button" class="pg-btn mdr-btn-view" (click)="view(r)">
|
|
<mat-icon>visibility</mat-icon> View
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
|
|
<mat-paginator
|
|
[length]="totalRecords"
|
|
[pageSize]="pageSize"
|
|
[pageSizeOptions]="pageSizeOptions"
|
|
[pageIndex]="pageIndex"
|
|
showFirstLastButtons
|
|
(page)="onPageChange($event)"
|
|
></mat-paginator>
|
|
}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ── VIEW MODAL ── -->
|
|
@if (viewRequest) {
|
|
<div class="mdr-modal-overlay" (click)="closeView()">
|
|
<div class="mdr-modal" (click)="$event.stopPropagation()">
|
|
<div class="mdr-modal__header">
|
|
<div>
|
|
<div class="mdr-modal__eyebrow">DEPOSIT REQUEST · VOUCHER {{ viewRequest.voucher_no || '—' }}</div>
|
|
<div class="mdr-modal__title">
|
|
₹{{ viewRequest.amount | number: '1.2-2' }} — {{ viewRequest.client_name }}
|
|
</div>
|
|
</div>
|
|
<button type="button" class="mdr-modal__close" (click)="closeView()">
|
|
<mat-icon>close</mat-icon>
|
|
</button>
|
|
</div>
|
|
<div class="mdr-modal__body">
|
|
<div class="mdr-detail-grid">
|
|
<div class="mdr-detail">
|
|
<span class="mdr-detail__lbl">Account No</span>
|
|
<span class="mdr-detail__val cell-mono">{{ viewRequest.account_no }}</span>
|
|
</div>
|
|
<div class="mdr-detail">
|
|
<span class="mdr-detail__lbl">Payment Mode</span>
|
|
<span class="mdr-detail__val">{{ viewRequest.payment_type_name || 'Cash' }}</span>
|
|
</div>
|
|
<div class="mdr-detail">
|
|
<span class="mdr-detail__lbl">Status</span>
|
|
<span class="mdr-detail__val">
|
|
<span class="mdr-status" [ngClass]="statusClass(viewRequest.status)">
|
|
{{ statusLabel(viewRequest.status) }}
|
|
</span>
|
|
</span>
|
|
</div>
|
|
<div class="mdr-detail">
|
|
<span class="mdr-detail__lbl">Submitted</span>
|
|
<span class="mdr-detail__val">{{ formatDateTime(viewRequest.submitted_at) }}</span>
|
|
</div>
|
|
@if (viewRequest.manager_name || viewRequest.manager_username) {
|
|
<div class="mdr-detail">
|
|
<span class="mdr-detail__lbl">Reviewed By</span>
|
|
<span class="mdr-detail__val">{{ viewRequest.manager_name || viewRequest.manager_username }}</span>
|
|
</div>
|
|
}
|
|
@if (viewRequest.actioned_at) {
|
|
<div class="mdr-detail">
|
|
<span class="mdr-detail__lbl">Actioned At</span>
|
|
<span class="mdr-detail__val">{{ formatDateTime(viewRequest.actioned_at) }}</span>
|
|
</div>
|
|
}
|
|
@if (viewRequest.txn_id) {
|
|
<div class="mdr-detail">
|
|
<span class="mdr-detail__lbl">Transaction Ref</span>
|
|
<span class="mdr-detail__val cell-mono">{{ viewRequest.txn_id }}</span>
|
|
</div>
|
|
}
|
|
@if (viewRequest.dd_face_value != null) {
|
|
<div class="mdr-detail">
|
|
<span class="mdr-detail__lbl">DD Face Value</span>
|
|
<span class="mdr-detail__val">₹{{ viewRequest.dd_face_value | number: '1.2-2' }}</span>
|
|
</div>
|
|
<div class="mdr-detail">
|
|
<span class="mdr-detail__lbl">Charges</span>
|
|
<span class="mdr-detail__val">₹{{ viewRequest.dd_charges | number: '1.2-2' }}</span>
|
|
</div>
|
|
<div class="mdr-detail">
|
|
<span class="mdr-detail__lbl">GST ({{ viewRequest.dd_gst_percentage }}%)</span>
|
|
<span class="mdr-detail__val">₹{{ viewRequest.dd_gst_amount | number: '1.2-2' }}</span>
|
|
</div>
|
|
<div class="mdr-detail">
|
|
<span class="mdr-detail__lbl">Total Collected</span>
|
|
<span class="mdr-detail__val"
|
|
><strong>₹{{ viewRequest.amount | number: '1.2-2' }}</strong></span
|
|
>
|
|
</div>
|
|
}
|
|
@if (viewRequest.description) {
|
|
<div class="mdr-detail mdr-detail--wide">
|
|
<span class="mdr-detail__lbl">Description</span>
|
|
<span class="mdr-detail__val">{{ viewRequest.description }}</span>
|
|
</div>
|
|
}
|
|
@if (viewRequest.status === 'REJECTED' && viewRequest.rejection_reason) {
|
|
<div class="mdr-detail mdr-detail--wide">
|
|
<span class="mdr-detail__lbl">Rejection Reason</span>
|
|
<span class="mdr-detail__val mdr-detail__val--reject">{{ viewRequest.rejection_reason }}</span>
|
|
</div>
|
|
}
|
|
</div>
|
|
@if (viewRequest.status === 'REJECTED') {
|
|
<div class="mdr-hint">This request was rejected. Enter a fresh deposit at Transaction Entry to resubmit.</div>
|
|
}
|
|
</div>
|
|
<div class="mdr-modal__actions">
|
|
<button type="button" class="pg-btn" (click)="closeView()">Close</button>
|
|
@if (viewRequest.status === 'REJECTED') {
|
|
<button type="button" class="pg-btn pg-btn--primary" (click)="newDeposit()">
|
|
<mat-icon>add</mat-icon> New Deposit
|
|
</button>
|
|
}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|