import { KasseneckApiError } from '../client/errors.js'; import type { Receipt } from './receipt.js'; import type { ReceiptPaymentInput } from './receipt-payment.js'; /** * Storno-Metadaten — Zwilling von `functions/storno-core.js`. * * Ein Storno ist ein eigener, signierter Beleg vom Typ `cancellation` mit * negativen Betraegen. Was NICHT signiert ist und hier als Metadaten laeuft: * der Bezug zum Original (`cancellationOf`, `cancellationReason` am * Storno-Beleg) und die Liste der Stornos am Original (`cancellations`), aus * der sich die Restmengen ergeben. */ /** * Grund-Katalog: Codes wie unter `/v3` (Katalog `STORNO_GRUND` des * Backends), Anzeigetext fuer Bon und Bedienung. Der Anzeigetext bleibt * deutsch, er steht so am Beleg. */ export declare const CANCELLATION_REASONS: Readonly<{ readonly input_error: "Fehleingabe"; readonly customer_cancelled: "Kunde hat storniert"; readonly wrong_payment_method: "Falsche Zahlart"; readonly duplicate: "Doppelt erfasst"; readonly other: "Sonstiges"; }>; export type CancellationReason = keyof typeof CANCELLATION_REASONS; export declare function isCancellationReason(value: unknown): value is CancellationReason; /** * Rueckgabe-Wahl beim Storno und bei der Gutschrift (Lager-Kern Stufe 2, * Katalog `RUECKGABE` des Backends): `restock` zurueck ins Lager (Vorgabe des * Servers), `defective` als defekt ins Lager, `disposed` entsorgt. Wirkt nur * an Positionen mit `articleId`; alle anderen bucht der Server nie und meldet * dafuer auch keinen Fehler. */ export declare const RETURN_DISPOSITIONS: readonly ["restock", "defective", "disposed"]; export type ReturnDisposition = (typeof RETURN_DISPOSITIONS)[number]; export declare function isReturnDisposition(value: unknown): value is ReturnDisposition; /** * Stabile Fehlercodes von `cancelReceipt` unter `/v3` (Vokabular * `errorCodes.cancellation`, gleiche Reihenfolge). Das Backend legt sie bei * jedem fachlichen Fehler als `code` neben die Meldung; das Paket reicht sie * als [KasseneckApiError.code] durch. **Entscheide am Code, nie am Text:** * die deutsche Meldung darf sich aendern, der Code nicht. * * Formfehler an `payments` selbst melden die Codes aus * [PAYMENT_ERROR_CODES]. `cancellation_outcome_unknown` heisst: der Storno * ist moeglicherweise gebucht (`outcome: 'unknown'`). Nie wiederholen, * sondern das Original nachlesen (`getReceipt`, `cancellations[]`). * * Dahinter (ab 1.0) die Codes, die Anmeldung und Rand auf diesem Endpunkt * erzeugen koennen: `errorCodes.auth` ohne die sieben des Partner-Zugangs und * `errorCodes.edge` (`not_found`, `dialect_mismatch`, `response_translation_failed` * ...), zuletzt die Codes des Pakets (`route_missing`, `response_unreadable`). * Die Zahlungscodes (`payment_method_not_supported` ...) stehen in * [PAYMENT_ERROR_CODES]. Ein Code ausserhalb bleibt ueber * `KasseneckApiError.code` lesbar. */ export declare const CANCELLATION_ERROR_CODES: readonly ["receipt_not_found", "receipt_type_not_cancellable", "training_receipt", "already_cancelled", "invalid_line", "quantity_exceeds_remaining", "unknown_reason", "note_too_long", "invalid_items", "cashregister_not_assigned", "not_permitted", "own_receipts_only", "cashregister_incomplete", "cancellation_failed", "cancellation_payments_required", "cancellation_refund_exceeds_payment", "cancellation_refund_reference_required", "cancellation_refund_reference_unknown", "cancellation_outcome_unknown", "invalid_return_disposition", "tip_refund_conflict", "invalid_tip_refund_source", "tip_refund_source_requires_cash", "tip_keep_not_possible_with_voucher", "account_not_found", "action_confirmation_required", "admin_required", "api_not_approved", "app_check_invalid", "app_check_missing", "cashregister_not_found", "cashregister_token_invalid", "cashregister_token_missing", "dialect_mismatch", "internal_translation_error", "live_not_enabled", "method_not_allowed", "mfa_required", "not_found", "password_change_required", "register_user_no_business", "register_user_not_allowed", "register_user_not_found", "response_translation_failed", "second_factor_required", "session_expired", "session_other_cashregister", "unauthorized", "user_disabled", "user_verification_failed", "validation", "route_missing", "response_unreadable"]; export type CancellationErrorCode = (typeof CANCELLATION_ERROR_CODES)[number]; export declare function isCancellationErrorCode(value: unknown): value is CancellationErrorCode; /** Der Code eines geworfenen Fehlers, wenn er in [CANCELLATION_ERROR_CODES] steht; sonst `undefined`. */ export declare function cancellationErrorCode(error: unknown): CancellationErrorCode | undefined; /** * Kurzform fuer `catch (e) { if (isCancellationError(e, 'already_cancelled')) … }`. * Ohne `code`: traegt der Fehler ueberhaupt einen Code aus [CANCELLATION_ERROR_CODES]? */ export declare function isCancellationError(error: unknown, code?: CancellationErrorCode): error is KasseneckApiError; /** Stornostand eines Belegs in der Belegliste (Katalog `STORNO_STAND`). */ export declare const CANCELLATION_STATUSES: readonly ["none", "partial", "full"]; export type CancellationStatus = (typeof CANCELLATION_STATUSES)[number]; /** Bezug eines Storno-Belegs auf sein Original. */ export interface CancellationOf { receiptId: string; fullReceiptId: string | null; /** * Zeitstempel des Originals (Server-Format, Wiener Wanduhr) — das Layout * nennt ihn im Kopfblock des Storno-Bons („vom 11.08.2026, 09:02 Uhr"). * Fehlt bei Altbelegen; dann bleibt die Zeile weg. */ timeStamp?: string; } /** Eine stornierte Position: Index im Original und Menge, an Artikelzeilen die Rueckgabe-Wahl. */ export interface CancellationItem { index: number; quantity: number; /** Wohin die Ware dieser Position geht; fehlt = Vorgabe des Aufrufs bzw. `restock`. */ returnDisposition?: ReturnDisposition; } /** * Eintrag in `cancellations[]` am Original. `pending` = Reservierung, die * das Backend vor der Buchung setzt und danach ersetzt; sie zaehlt fuer die * Restmengen nur, solange sie frisch ist (siehe [remainingQuantities]). */ export interface Cancellation { receiptId?: string; pending?: boolean; at: number; by: string | null; note: string | null; items: CancellationItem[]; /** * Rabattgutschein-Ausgleich, den DIESER Storno gewaehrt hat — Cent je * Steuertopf des Backends (`amountRateStandard`, `amountRateReduced1`, …). * Ein Rabattgutschein ist am Original schon in den Umsatz eingerechnet; * jeder Storno nimmt ihn anteilig der stornierten Menge zurueck (bei 3 Stueck * a 10 EUR mit 6 EUR Rabatt: 2,00 je Stueck). Fehlt das Feld, hat der Eintrag * nichts gewaehrt (Altbestand vor dieser Regel) — der naechste Storno holt nach. */ promoAdjustmentCents?: Record; /** * Rueckzahlung je Zahlung, die DIESER Storno-Eintrag auf eine Zahlung des * Originals verbucht hat (`refundOf`) -- Zahlungs-ID auf positive Cent, * Zwilling von `functions/gemeinsam/storno-core.js` `refundedByPayment`. * Ueber alle Eintraege darf je Zahlung nie mehr zurueck, als bezahlt wurde * (siehe dort `restJeZahlung`). Ein Eintrag ohne das Feld (vor dieser Regel * oder ohne Zahlungsmodell gebucht) zaehlt dabei 0 je Zahlung. Auch am * `pending`-Eintrag vorhanden, sobald reserviert wird. */ refundedByPayment?: Record; } /** Ab wann eine liegengebliebene Reservierung nicht mehr zaehlt (wie im Backend). */ export declare const CANCELLATION_RESERVATION_MS = 120000; /** * Restmenge je Position eines Belegs — Belegmenge minus alles, was storniert * oder frisch reserviert ist; nie unter null. Fuer den Storno-Dialog der Kasse * (Reste anzeigen, bevor der Server gefragt wird). Die Wahrheit hat der Server. */ export declare function remainingQuantities(receipt: Receipt, nowMs?: number): number[]; /** Ein Feldfehler aus `data.errors[]` einer `validation`-Antwort von `cancelReceipt`. */ export interface CancellationFieldError { field: string; message: string; } /** Die Feldfehler einer `validation`-Antwort; leer, wenn es keine sind. */ export declare function cancellationFieldErrors(error: unknown): CancellationFieldError[]; /** * Woher das Trinkgeld beim Storno zurueckkommt: `drawer` – die Lade zahlt es aus („offen“ sinkt, * kann negativ werden); `employee` – die Mitarbeiterin gibt es selbst („verdient“ und „schon * genommen“ sinken, die Lade bleibt unberuehrt). Nur bei Barrueckgabe. */ export declare const TIP_REFUND_SOURCES: readonly ["drawer", "employee"]; export type TipRefundSource = (typeof TIP_REFUND_SOURCES)[number]; export declare function isTipRefundSource(value: unknown): value is TipRefundSource; /** * Noch nicht storniertes Mitarbeiter-Trinkgeld in Cent. Groesser 0 heisst: das Storno fragt * „Trinkgeld auch zurueckgeben?“ (auch beim Teilstorno). Inhaber-Trinkgeld ist Umsatz und folgt * der Ware -- dafuer gibt es keine Frage. */ export declare function openStaffTipCents(receipt: Receipt, nowMs?: number): number; /** * Fragt das Storno „Trinkgeld auch zurueckgeben?“ – nur bei noch offenem Mitarbeiter-Trinkgeld und * ohne Wertgutschein am Beleg. Einen Wertgutschein spiegelt nur ein Storno, der alles nimmt; darum * geht das Trinkgeld dort immer mit (der Server weist `refundTip: false` mit * `tip_keep_not_possible_with_voucher` ab), die Kasse zeigt stattdessen * `cancellation.tip_refunded_with_voucher` und sendet `refundTip: true`. Die Frage nach der Quelle * bleibt ([asksTipRefundSource]). */ export declare function asksRefundTip(receipt: Receipt, nowMs?: number): boolean; /** * Die Positionen, die nach der Antwort auf „Trinkgeld auch zurueckgeben?“ hinausgehen -- dieselbe * Regel wie im Backend. `items` fehlt = ganzer Beleg. * - Ja: zum Teilstorno kommt das offene Trinkgeld dazu; der ganze Beleg bleibt `undefined`. * - Nein: ohne das Mitarbeiter-Trinkgeld; der ganze Beleg wird zur Liste aller Restmengen ausser dem * Trinkgeld (leer = nichts mehr zu stornieren). Ist kein Mitarbeiter-Trinkgeld mehr offen (keines * oder schon storniert), bleibt der Wunsch, wie er ist – „Nein“ wirkt dann wie keine Wahl. */ export declare function cancellationItemsForTip(receipt: Receipt, items: readonly CancellationItem[] | undefined, refundTip: boolean, nowMs?: number): CancellationItem[] | undefined; /** * Was dieses Storno bar zurueckgibt (positiv, Cent): mit Rueckzahlungen deren Barteil; ohne * (der Server spiegelt die eine Zahlung des Originals) alles, wenn das Original bar bezahlt war. * Bei mehr als einer Zahlung ohne Angabe 0: welcher Teil bar zurueckgeht, ist dann offen (ein * Teilstorno verlangt ohnehin `payments`). Beide Kassen schicken bei mehr als einer Zahlung darum * immer die Rueckzahlungen mit und rechnen hier mit ihnen. */ export declare function cancellationCashRefundCents(receipt: Receipt, payments: readonly ReceiptPaymentInput[] | undefined, dueCents: number): number; /** * Fragt das Storno nach „Ja“ auch „Woher kommt das Trinkgeld zurueck?“ – nur, wenn das Bargeld des * Stornos (`cashRefundCents`, siehe [cancellationCashRefundCents]) das offene Mitarbeiter-Trinkgeld * deckt und die Mitarbeiterin wenigstens eines davon schon hatte. Bei Kartenrueckgabe geht es auf * die Karte zurueck; ueber Lohn behaltenes Trinkgeld kommt immer aus der Lade. */ export declare function asksTipRefundSource(receipt: Receipt, cashRefundCents: number, nowMs?: number): boolean;