import { type Receipt, type ReceiptCompany, type RegistrationInfo } from '../models/index.js'; import type { PosPaperSize } from '../printing/escpos.js'; /** * Beleg-Layout — der Bauplan eines Kasseneck-Belegs als reines Datenmodell. * * Aufbau und Reihenfolge stammen aus dem Flutter-Vorbild * `kasseneck_api/lib/models/print_paper.dart` (`setKeckReceipt`). Der * Unterschied: dort entstehen unmittelbar Druckerbytes, hier entsteht **eine * Folge von Zeilen**. Wer sie zeichnet, entscheidet der Aufrufer — der * React-Adapter (`@kreiseck/kasseneck-api/react`) fuer den Bildschirm, * [escPosLayoutBytes] (`./layout-escpos.js`) fuer den Bondrucker, ein * PDF-Erzeuger im Backend. Damit steht die Reihenfolge der Belegangaben genau * einmal da und nicht je Ausgabeweg erneut. * * Kein Framework, keine Druckerabhaengigkeit, keine Bildverarbeitung: das * Modell laeuft unveraendert im Browser und in Node. * * **Der Text im Modell ist echter Text.** Ein Euro-Zeichen ist hier ein „€", * kein „EUR". Bondrucker koennen es nicht darstellen; die Ersetzung sitzt * deshalb an genau einer Stelle in der ESC/POS-Bruecke und nicht hier — sonst * stuende auch auf dem Bildschirm „EUR". * * Bewusst **nicht** enthalten: Firmenlogo und Rasterbilder (brauchen * Bildverarbeitung, die im Browser anders aussieht als in Node), PDF-Erzeugung * und Druckeransteuerung. * * Die anbieterspezifischen Kartenzahlungsbloecke sind dagegen **alle** * enthalten (Hobex, GP Tom, SumUp, myPOS, Stripe). Bis 0.8.0 trug das Modell * nur den Hobex-Block, weil die Browser-Kasse nur das HPS-Terminal selbst * bedient und die uebrigen Anbieter „in ihren eigenen Apps drucken". Das * Argument gilt fuer die Frage, wer das TERMINAL bedient — nicht dafuer, was * auf dem BELEGDOKUMENT steht. Aus der einen Regel wurde die andere, und * derselbe Beleg trug im PDF weniger als auf dem Bon. */ /** Ausrichtung einer Zeile bzw. einer Spalte. */ export type LayoutAlign = 'left' | 'center' | 'right'; /** Eine Spalte einer Spaltenzeile; `width` ist ein Zwoelftel-Anteil (1..12). */ export interface LayoutColumn { text: string; width: number; align: LayoutAlign; } /** Eine Textzeile ueber die volle Breite. */ export interface LayoutTextLine { kind: 'text'; text: string; align: LayoutAlign; bold: boolean; } /** Eine Zeile aus mehreren Spalten; die Breiten ergeben zusammen 12. */ export interface LayoutColumnsLine { kind: 'columns'; columns: LayoutColumn[]; /** * Die ganze Zeile fett (z. B. „Bleibt in der Kassenlade“ auf dem Z-Bon). * Fehlt es, ist die Zeile normal; im Bauplan steht es nur, wenn `true`. */ bold?: boolean; } /** Eine durchgehende Trennlinie aus [char]. */ export interface LayoutRuleLine { kind: 'rule'; char: string; } /** Leerraum von [lines] Zeilen. */ export interface LayoutSpaceLine { kind: 'space'; lines: number; } /** Der maschinenlesbare RKSV-Code. [data] ist die Nutzlast, unveraendert. */ export interface LayoutQrLine { kind: 'qr'; data: string; } /** * Hervorgehobene Zeile (Belegart, Testhinweise): fett, zentriert, vom * Zeichner sichtbar abgesetzt (Rahmen, invers oder Groesse). Der Text ist * bereits fertig (RKSV § 11 Abs. 3: Trainings- und Stornobuchungen sind * ausdruecklich als solche zu bezeichnen). */ export interface LayoutBannerLine { kind: 'banner'; text: string; /** * `warning` fuer Testkasse/Testsignatur (kein gueltiger Beleg), sonst * `receipt_type` (Belegart). Werte wie am `/v3`-Draht (Katalog `LAYOUT_TON`). */ tone: LayoutBannerTone; } /** Ton einer hervorgehobenen Zeile, wie am `/v3`-Draht. */ export type LayoutBannerTone = 'receipt_type' | 'warning'; export type LayoutLine = LayoutTextLine | LayoutColumnsLine | LayoutRuleLine | LayoutSpaceLine | LayoutQrLine | LayoutBannerLine; /** * Version des Layout-Regelwerks. Alte Belege werden mit ihrer gespeicherten * Version gesetzt. * - 1: Nullbeleg reduziert mit Summenzeile „Betrag: 0,00 €“. * - 2: Nullbeleg als Pruefbeleg mit Block „Prüfangaben“ (Barumsatz, Signatur, * Signaturkarte, Zertifizierungsdienst, Registrierdaten); reduziert nur, * wenn alle Betraege wirklich 0 sind. Vollbelege unveraendert. */ export type LayoutRuleset = 1 | 2; export declare const CURRENT_LAYOUT_RULESET: LayoutRuleset; /** Der fertige Bauplan eines Belegs. */ export interface ReceiptLayout { lines: LayoutLine[]; /** Papierbreite, nach der die Spaltenbreiten gewaehlt wurden. */ paperSize: PosPaperSize; /** Regelwerk, nach dem gesetzt wurde. */ ruleset: LayoutRuleset; } export interface BuildReceiptLayoutOptions { /** * Papierbreite; sie bestimmt — wie im Vorbild — allein die Spaltenbreiten * der USt-Tabelle. Vorgabe `mm58`. */ paperSize?: PosPaperSize; /** Layout-Regelwerk (Vorgabe: aktuelles). Unbekannt -> Fehler, nie stumm anders setzen. */ ruleset?: LayoutRuleset; /** * Beleg einer Testumgebung: Rahmen „TESTKASSE — kein gültiger Beleg“ oben * und unten. Aus einer Antwort: `ReceiptWithCompany.testCashregister`. */ testCashregister?: boolean; /** * Produktionskonto hat mit einer Test-Signatureinheit signiert: Rahmen * „TESTSIGNATUR — kein gültiger Beleg“. Der Aufrufer entscheidet (er kennt * das Konto); [receiptSignatureIsTest] sagt nur, OB die Signatur eine * Testsignatur ist. Aus einer Antwort: `ReceiptWithCompany.testSignature`. */ testSignature?: boolean; /** * Registrierdaten fuer den Block „Prüfangaben“ (nur Nullbelege, Regelwerk 2). * Kennt sie nur das Backend (FinanzOnline-Registrierung der Signaturkarte * und der Kasse); fehlen sie, entfallen die Zeilen. Datum als „YYYY-MM-DD“ * oder ISO-Zeitstempel (Wiener Kalendertag). Aus einer Antwort: * `ReceiptWithCompany.registrationInfo`. */ registrationInfo?: RegistrationInfo | null; } /** * Cent-Betrag als Anzeigetext: `1234` -> `"12,34"`. Die **einzige** Stelle, an * der aus Cent eine Zeichenkette wird. Erwartet ganze Cent (Geld wird in * diesem Paket ausnahmslos ganzzahlig gerechnet). */ export declare function formatCents(cents: number): string; /** Zwilling von `stripeReceiptLines` (print_paper.dart). */ export declare function stripeReceiptLines(daten: Record, cardPaymentId: string | null): string[]; /** * Hinweis auf die Steuerbefreiung, den ein Kleinunternehmerbeleg tragen muss — * ohne ihn stuende in der USt-Tabelle „D 0 %" ohne jede Begruendung, und ab * 400 € greift § 11 UStG voll. * * Wortlaut **woertlich** aus dem Backend (`INVOICE_TAX_NOTE.smallBusiness` in * functions/index.js), damit auf Beleg und Rechnung derselbe Satz steht. Er * traegt einen Gedankenstrich (U+2013), kein Bindestrich; der Bondrucker * bekommt ihn ueber die Ersetzung der ESC/POS-Bruecke. * * Weder `print_paper.dart` noch das Beleg-PDF des Backends drucken den Hinweis * heute — hier liegt das Kennzeichen vor, also steht er hier. * * Der **Name** ist englisch wie die uebrige Oberflaeche (`DEFAULT_BASE_URL`, * `formatCents`, `buildReceiptLayout`); der **Wortlaut** ist selbstverstaendlich * deutsch — er steht so auf oesterreichischen Belegen. */ export declare const SMALL_BUSINESS_NOTICE = "Umsatzsteuerbefreit \u2013 Kleinunternehmer gem\u00E4\u00DF \u00A7 6 Abs. 1 Z 27 UStG."; /** Wurde der Beleg ohne funktionierende Signatureinheit ausgestellt? */ export declare function receiptSignatureFailed(receipt: Receipt): boolean; /** * Traegt der Beleg eine **Test**-Signatur? Erkannt am ZDA-Kennzeichen `AT100` * im maschinenlesbaren Code (`_R1-AT100_...`) — der Testpfad der Testumgebungen. * Ob das ein Problem ist, weiss nur der Aufrufer (Testkonto: normal; * Produktionskonto: „TESTSIGNATUR“-Warnung). */ export declare function receiptSignatureIsTest(receipt: Pick): boolean; /** Ist das ein Nullbeleg (Start-, Monats-, Jahres-, Schluss-, Pruefbeleg)? */ export declare function receiptIsZero(receipt: Receipt): boolean; /** * Sind alle Betraege des Belegs wirklich 0? (Keine Positionen mit Wert, keine * Gutscheine.) Ein Nullbeleg, der das nicht erfuellt, ist ein Datenfehler -- * Regelwerk 2 setzt ihn dann als normalen Beleg. */ export declare function receiptAmountsAreZero(receipt: Receipt): boolean; /** * Zertifizierungsdienst aus der QR-Kennung `_R1-_` (RKSV-Detailspezifikation: * AT0 geschlossenes System, AT1 A-Trust, AT2 GlobalTrust, AT3 PrimeSign, * AT100 Testsignatur). Unbekannte Kennung: nur die Kennung. */ export declare function receiptZdaText(qr: string): string | null; /** * Kleinunternehmer (§ 6 Abs. 1 Z 27 UStG, unechte Befreiung): auf dem Beleg * darf keine USt stehen -- jede Position 0 %. Sagt, ob der Beleg dazu passt; * das Backend weist Widersprueche beim Ausstellen ab, hier ist es die Probe. */ export declare function receiptIsSmallBusinessConsistent(receipt: Receipt): boolean; /** * Baut das Layout eines Belegs. Reihenfolge und Spaltenbreiten folgen * `print_paper.dart` (`setKeckReceipt`). */ export declare function buildReceiptLayout(receipt: Receipt, company: ReceiptCompany, options?: BuildReceiptLayoutOptions): ReceiptLayout;