184 lines
6.2 KiB
HTML
184 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="pg">
|
|
<header class="pg-head vr-no-print">
|
|
<div>
|
|
<div class="pg-eyebrow">CASHIER · REPORT</div>
|
|
<h1 class="pg-title">Voucher Report</h1>
|
|
<p class="pg-sub">
|
|
Every voucher raised over a day or a month — the number, what was debited, what was credited, and who raised it.
|
|
</p>
|
|
</div>
|
|
<div class="pg-toolbar">
|
|
<label class="pg-field">
|
|
<span>Period</span>
|
|
<select [(ngModel)]="period" (change)="load()">
|
|
<option value="DAY">Day</option>
|
|
<option value="MONTH">Month</option>
|
|
</select>
|
|
</label>
|
|
<label class="pg-field">
|
|
<span>{{ period === 'DAY' ? 'Date' : 'Month of' }}</span>
|
|
<input type="date" [(ngModel)]="anchor" (change)="load()" />
|
|
</label>
|
|
@if (report?.canSeeAllUsers) {
|
|
<label class="pg-field">
|
|
<span>User</span>
|
|
<input
|
|
type="text"
|
|
[(ngModel)]="usernameFilter"
|
|
(keyup.enter)="load()"
|
|
placeholder="All users"
|
|
autocomplete="off"
|
|
/>
|
|
</label>
|
|
}
|
|
<button type="button" class="pg-btn pg-btn--primary" (click)="load()" [disabled]="loading">
|
|
<mat-icon>refresh</mat-icon> Run
|
|
</button>
|
|
@if (report && report.count > 0) {
|
|
<button type="button" class="pg-btn" (click)="print()">
|
|
<mat-icon>print</mat-icon> Print
|
|
</button>
|
|
}
|
|
</div>
|
|
</header>
|
|
|
|
@if (error) {
|
|
<div class="pg-alert pg-alert--error vr-no-print">{{ error }}</div>
|
|
}
|
|
|
|
@if (loading) {
|
|
<div class="pg-empty vr-no-print">Loading…</div>
|
|
}
|
|
|
|
@if (report && !loading) {
|
|
<div class="vr-period">
|
|
{{ report.from | date: 'dd MMM yyyy' }}
|
|
@if (report.from !== report.to) {
|
|
— {{ report.to | date: 'dd MMM yyyy' }}
|
|
}
|
|
· {{ report.count }} voucher{{ report.count === 1 ? '' : 's' }}
|
|
· ₹{{ report.totalAmount | number: '1.2-2' }}
|
|
@if (report.username) {
|
|
· {{ report.username }}
|
|
}
|
|
<!-- Said plainly rather than left to be inferred from a missing filter: a cashier should know
|
|
this is their own work and not the branch's. -->
|
|
@if (!report.canSeeAllUsers) {
|
|
<span class="vr-scope-note">Your own vouchers</span>
|
|
}
|
|
</div>
|
|
|
|
@if (report.count === 0) {
|
|
<div class="pg-empty">No vouchers were raised in this period.</div>
|
|
} @else {
|
|
<div class="vr-summaries">
|
|
<div class="pg-card">
|
|
<div class="pos-section-label">By type</div>
|
|
<table class="pg-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Type</th>
|
|
<th class="num">Count</th>
|
|
<th class="num">Amount</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (row of byType; track row.type) {
|
|
<tr>
|
|
<td>{{ row.type }}</td>
|
|
<td class="num">{{ row.count }}</td>
|
|
<td class="num">{{ row.total | number: '1.2-2' }}</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Only worth showing to someone who can see more than one person's work. -->
|
|
@if (report.canSeeAllUsers) {
|
|
<div class="pg-card">
|
|
<div class="pos-section-label">By user</div>
|
|
<table class="pg-table">
|
|
<thead>
|
|
<tr>
|
|
<th>User</th>
|
|
<th class="num">Count</th>
|
|
<th class="num">Amount</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (row of byUser; track row.username) {
|
|
<tr>
|
|
<td>{{ row.username }}</td>
|
|
<td class="num">{{ row.count }}</td>
|
|
<td class="num">{{ row.total | number: '1.2-2' }}</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
}
|
|
</div>
|
|
|
|
<div class="pg-card">
|
|
<div class="pos-section-label">Vouchers</div>
|
|
<table class="pg-table vr-rows">
|
|
<thead>
|
|
<tr>
|
|
<th>Voucher No</th>
|
|
<th>Type</th>
|
|
<th>Debit</th>
|
|
<th>Credit</th>
|
|
<th class="num">Amount</th>
|
|
<th>User</th>
|
|
<th>Time</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@for (row of report.vouchers; track row.voucherNo) {
|
|
<tr>
|
|
<td>
|
|
<a class="vr-link" [routerLink]="['/cashier/voucher']" [queryParams]="{ voucherNo: row.voucherNo }">
|
|
{{ row.voucherNo }}
|
|
</a>
|
|
@if (row.verificationStatus === 'EXCEPTION') {
|
|
<mat-icon class="vr-flag" title="An exception was raised against this voucher">error_outline</mat-icon>
|
|
}
|
|
</td>
|
|
<td>{{ row.voucherType || '—' }}</td>
|
|
<td>
|
|
<div class="vr-party">{{ row.debitParty || '—' }}</div>
|
|
@if (row.debitAccount) {
|
|
<div class="vr-acct">{{ row.debitAccount }}</div>
|
|
}
|
|
</td>
|
|
<td>
|
|
<div class="vr-party">{{ row.creditParty || '—' }}</div>
|
|
@if (row.creditAccount) {
|
|
<div class="vr-acct">{{ row.creditAccount }}</div>
|
|
}
|
|
<!-- A DD with charges, or a compound journal, has sides this row does not show. -->
|
|
@if (row.extraLines > 0) {
|
|
<div class="vr-more">+{{ row.extraLines }} more on voucher</div>
|
|
}
|
|
</td>
|
|
<td class="num">{{ row.amount | number: '1.2-2' }}</td>
|
|
<td>{{ row.username || '—' }}</td>
|
|
<td>{{ row.createdAt | date: 'dd MMM, HH:mm' }}</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
}
|
|
}
|
|
</div>
|