feat: re-model drawer cash as directional vouchers (Mandat Arkëtimi / Pagese)
Replace the single signed-± cash_movement with two distinct financial documents — the direction is the event TYPE, not the sign of an amount: cash_in = Mandat Arkëtimi (receipt / pay-IN, +) voucher AR-NNNN cash_out = Mandat Pagese (disbursement / pay-OUT, −) voucher PA-NNNN Each carries a positive magnitude, voucher number, reason, the operator who raised it and the admin who authorized it, and prints an Albanian slip. Authorization changes from admin-only to operator-RAISED / admin-AUTHORIZED: any shift:create holder raises the voucher, but POST /api/cash-voucher only commits when authorizedBy is a real admin (shift:cash) re-entering their password (verified server-side). Keeps the float control while letting the operator do the booth paperwork. Legacy cash_movement events are kept — they still verify and still fold into the drawer (signed-±); the append-only chain is never rewritten. The drawer fold and the Z-report window now sum all three types. Verified against a copy of the live DB with the real signing modules: cash_in 3000 + cash_out 5000 → drawer −2000, hash-chain verifies OK. Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
This commit is contained in:
@@ -121,7 +121,18 @@ export type LedgerEventType =
|
||||
// Admin loads/removes physical drawer cash (the float). Signed payload:
|
||||
// { amountMinor (signed: + load, − removal), reason, currency, operator }.
|
||||
// Folds into the drawer balance carried across shifts. See wiki/concepts/shift.md.
|
||||
// SUPERSEDED 2026-06-20 by the directional voucher pair below — kept as a type so
|
||||
// historical events on the live chain still verify and still fold into the drawer.
|
||||
| "cash_movement"
|
||||
// Drawer cash vouchers (replace the signed-± cash_movement with two distinct
|
||||
// financial documents — the direction is the TYPE, not the sign of an amount):
|
||||
// cash_in = Mandat Arkëtimi (receipt / pay-IN): cash enters the drawer.
|
||||
// cash_out = Mandat Pagese (disbursement / pay-OUT): cash leaves the drawer.
|
||||
// Payload: { amountMinor (POSITIVE magnitude), reason, currency, operator (raised
|
||||
// by), authorizedBy (admin who signed off), voucherNo }. Operator-raised /
|
||||
// admin-authorized. Folds into the drawer balance. See wiki/concepts/shift.md.
|
||||
| "cash_in"
|
||||
| "cash_out"
|
||||
| "anomaly";
|
||||
|
||||
/** How money was tendered (for payment events + the shift Z-report). */
|
||||
@@ -168,6 +179,12 @@ export interface LedgerPayload {
|
||||
/** vehicle_entry: the vehicle/customer category, frozen at entry so V2 category
|
||||
* pricing reprices identically at exit. Absent on legacy entries (= default). */
|
||||
readonly category?: string;
|
||||
/** cash_in / cash_out voucher: the admin who AUTHORIZED the drawer movement (the
|
||||
* operator in `operator` raised it). Operator-raised / admin-authorized. */
|
||||
readonly authorizedBy?: string;
|
||||
/** cash_in / cash_out voucher: a human-facing voucher number printed on the slip
|
||||
* (Mandat Nr.). Sequential per type; signed for reproducibility. */
|
||||
readonly voucherNo?: string;
|
||||
/** Free-form for forward-compat without a schema change. */
|
||||
readonly [k: string]: unknown;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user