Payment discrepancy report updates

This commit is contained in:
Stephanos A
2026-07-20 22:48:50 +03:00
parent 19fe977f40
commit eabc15eebf
2 changed files with 38 additions and 23 deletions

View File

@@ -10,7 +10,7 @@ import { apiClient } from '@/lib/api-client';
// ── Types ─────────────────────────────────────────────────────────────────────
interface ScheduleOption { id: string; label: string; departureAt: string; }
interface ScheduleOption { id: string; label: string; departureAt: string; isPackage: boolean; }
interface PassengerBreakdown {
passengerName: string;
@@ -22,6 +22,7 @@ interface PassengerBreakdown {
interface DiscrepancyRow {
bookingRef: string;
isPackage: boolean;
seatClass: string;
coachNumber: string | null;
seatNumber: string | null;
@@ -81,10 +82,15 @@ function Pagination({ page, totalPages, setPage, total }: {
// ── Helpers ───────────────────────────────────────────────────────────────────
function fmt(minor: number) {
function fmtMinor(minor: number) {
return `ETB ${(minor / 100).toLocaleString('en-US', { minimumFractionDigits: 2 })}`;
}
// paidMinor from PaymentIntent.amountMinor is a Float stored as full units (not cents)
function fmtPaid(amount: number) {
return `ETB ${amount.toLocaleString('en-US', { minimumFractionDigits: 2 })}`;
}
function downloadCsv(csv: string, filename: string) {
const blob = new Blob([csv], { type: 'text/csv' });
const url = URL.createObjectURL(blob);
@@ -231,18 +237,10 @@ export default function PaymentsReportPage() {
{data && (
<div className="card overflow-x-auto">
<div className="flex items-center justify-between mb-4">
<div className="mb-4">
<h3 className="text-sm font-semibold uppercase tracking-wider text-muted-foreground">
{data.total} discrepanc{data.total !== 1 ? 'ies' : 'y'} found
</h3>
{data.rows.length > 0 && (
<button
onClick={doExport}
className="flex items-center gap-1.5 text-xs font-medium text-muted-foreground hover:text-foreground border border-border rounded-lg px-3 py-1.5 transition-colors"
>
<Download className="w-3.5 h-3.5" /> Export CSV
</button>
)}
</div>
<table className="w-full text-sm">
<thead>
@@ -270,7 +268,14 @@ export default function PaymentsReportPage() {
<td className="py-2 pr-2 text-muted-foreground">
{isExpanded ? <ChevronUp className="w-3.5 h-3.5" /> : <ChevronDown className="w-3.5 h-3.5" />}
</td>
<td className="py-2 pr-4 font-mono text-xs font-semibold">{r.bookingRef}</td>
<td className="py-2 pr-4 font-mono text-xs font-semibold">
{r.bookingRef}
{r.isPackage && (
<span className="ml-1.5 text-[10px] font-semibold bg-purple-100 dark:bg-purple-950/40 text-purple-700 dark:text-purple-300 border border-purple-200 dark:border-purple-800 px-1.5 py-0.5 rounded">
package
</span>
)}
</td>
<td className="py-2 pr-4 text-xs">
<span className="font-medium">{r.seatClass}</span>
{r.coachNumber && <span className="text-muted-foreground"> · {r.coachNumber}</span>}
@@ -279,12 +284,12 @@ export default function PaymentsReportPage() {
<td className="py-2 pr-4 text-xs text-muted-foreground whitespace-nowrap">
{r.origin} {r.destination}
</td>
<td className="py-2 pr-4 text-right tabular-nums text-xs">{fmt(r.actualMinor)}</td>
<td className="py-2 pr-4 text-right tabular-nums text-xs">{fmt(r.paidMinor)}</td>
<td className="py-2 pr-4 text-right tabular-nums text-xs">{fmtMinor(r.actualMinor)}</td>
<td className="py-2 pr-4 text-right tabular-nums text-xs">{fmtPaid(r.paidMinor)}</td>
<td className="py-2 pr-4 text-right">
<span className="inline-flex items-center gap-1 text-xs font-bold px-2 py-0.5 rounded-md bg-red-50 dark:bg-red-950/30 text-red-600 dark:text-red-400 border border-red-200 dark:border-red-800">
<AlertTriangle className="w-3 h-3" />
{fmt(r.varianceMinor)}
{fmtMinor(r.varianceMinor)}
</span>
</td>
<td className="py-2 text-xs text-muted-foreground">{r.phone}</td>
@@ -314,14 +319,14 @@ export default function PaymentsReportPage() {
<td className="py-1.5 pr-4">{b.seatClass}</td>
<td className="py-1.5 pr-4 font-mono">{b.coachNumber ?? '—'}</td>
<td className="py-1.5 pr-4 font-mono">{b.seatNumber ?? '—'}</td>
<td className="py-1.5 text-right tabular-nums font-semibold">{fmt(b.fareMinor)}</td>
<td className="py-1.5 text-right tabular-nums font-semibold">{fmtMinor(b.fareMinor)}</td>
</tr>
))}
<tr className="border-t border-border font-semibold">
<td colSpan={4} className="pt-2 text-muted-foreground">Total actual vs paid</td>
<td className="pt-2 text-right tabular-nums">
{fmt(r.actualMinor)} / {fmt(r.paidMinor)}
<span className="ml-2 text-red-500">(+{fmt(r.varianceMinor)})</span>
{fmtMinor(r.actualMinor)} / {fmtPaid(r.paidMinor)}
<span className="ml-2 text-red-500">(+{fmtMinor(r.varianceMinor)})</span>
</td>
</tr>
</tbody>