server+web: shifts — open/close + signed Z-report (manned mode)
A shift is two signed ledger events, no mutable table: new shift_open event type + existing shift_z_report. The operator is the logged-in user (carried in event identity); a shift is open iff their latest shift event is a shift_open. ShiftService: close sums payment events in [start,end] by tender (cash/card, by payment time), appends the signed shift_z_report (totals/counts/window), and prints via a new generic PrinterDevice.printReport(title, lines) (Rongta ESC/POS text) to a booth-receipt printer. Print is best-effort — a failed print does not undo the signed close. Routes (cashier/operator/admin): GET /api/shift/current, POST /api/shift/open (409 if open), POST /api/shift/close (409 if none). Web ShiftControl in the shell (non-readonly): Start/End + Z-report totals. Verified: open -> double-open 409 -> payments (cash+card; one outside the window excluded) -> close totals correct + signed + printed -> close-again 409 -> re-open ok; readonly 403; verifyChain ok.
This commit is contained in:
@@ -277,3 +277,30 @@ export function revokePermit(id: string): Promise<Permit> {
|
||||
export function deletePermit(id: string): Promise<void> {
|
||||
return apiFetch(`/api/permits/${id}`, { method: "DELETE" });
|
||||
}
|
||||
|
||||
// --- Shifts ---------------------------------------------------------------
|
||||
|
||||
export interface ShiftStatus {
|
||||
operator: string;
|
||||
open: { startedAt: string } | null;
|
||||
}
|
||||
export interface ShiftReport {
|
||||
operator: string;
|
||||
startedAt: string;
|
||||
endedAt: string;
|
||||
cashTotalMinor: number;
|
||||
cardTotalMinor: number;
|
||||
currency: string | null;
|
||||
paymentCount: number;
|
||||
printed: boolean;
|
||||
}
|
||||
|
||||
export function fetchShift(): Promise<ShiftStatus> {
|
||||
return apiFetch("/api/shift/current");
|
||||
}
|
||||
export function openShift(): Promise<{ startedAt: string }> {
|
||||
return apiFetch("/api/shift/open", { method: "POST" });
|
||||
}
|
||||
export function closeShift(): Promise<ShiftReport> {
|
||||
return apiFetch("/api/shift/close", { method: "POST" });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user