@kreiseck/kasseneck-api 0.13.1 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/README.md +127 -21
  3. package/dist/cjs/client/auth.d.ts +4 -4
  4. package/dist/cjs/client/auth.js +3 -3
  5. package/dist/cjs/client/cashregisters.d.ts +1 -1
  6. package/dist/cjs/client/cashregisters.js +1 -1
  7. package/dist/cjs/client/errors.d.ts +1 -1
  8. package/dist/cjs/client/errors.js +2 -2
  9. package/dist/cjs/client/receipts.d.ts +8 -1
  10. package/dist/cjs/client/receipts.js +2 -1
  11. package/dist/cjs/client/transport.d.ts +1 -1
  12. package/dist/cjs/client/transport.js +2 -2
  13. package/dist/cjs/kasse/drucker.d.ts +5 -0
  14. package/dist/cjs/kasse/drucker.js +9 -0
  15. package/dist/cjs/kasse/settings.js +5 -2
  16. package/dist/cjs/models/cashregister.d.ts +2 -2
  17. package/dist/cjs/models/receipt-company.d.ts +1 -1
  18. package/dist/cjs/printing/escpos.d.ts +38 -4
  19. package/dist/cjs/printing/escpos.js +87 -15
  20. package/dist/cjs/printing/index.d.ts +2 -2
  21. package/dist/cjs/printing/index.js +5 -1
  22. package/dist/cjs/printing/qr-groesse.d.ts +26 -21
  23. package/dist/cjs/printing/qr-groesse.js +22 -8
  24. package/dist/cjs/react/index.d.ts +53 -0
  25. package/dist/cjs/react/index.js +81 -0
  26. package/dist/cjs/receipt/bild.d.ts +14 -0
  27. package/dist/cjs/receipt/bild.js +65 -0
  28. package/dist/cjs/receipt/blatt.d.ts +107 -0
  29. package/dist/cjs/receipt/blatt.js +137 -0
  30. package/dist/cjs/receipt/epos.d.ts +19 -8
  31. package/dist/cjs/receipt/epos.js +39 -20
  32. package/dist/cjs/receipt/grid.d.ts +1 -1
  33. package/dist/cjs/receipt/grid.js +9 -1
  34. package/dist/cjs/receipt/index.d.ts +4 -2
  35. package/dist/cjs/receipt/index.js +17 -1
  36. package/dist/cjs/receipt/layout-escpos.d.ts +31 -3
  37. package/dist/cjs/receipt/layout-escpos.js +58 -18
  38. package/dist/cjs/register/index.d.ts +1 -1
  39. package/dist/cjs/register/index.js +1 -1
  40. package/dist/cjs/register/pairing.d.ts +2 -2
  41. package/dist/esm/client/auth.d.ts +4 -4
  42. package/dist/esm/client/auth.js +3 -3
  43. package/dist/esm/client/cashregisters.d.ts +1 -1
  44. package/dist/esm/client/cashregisters.js +1 -1
  45. package/dist/esm/client/errors.d.ts +1 -1
  46. package/dist/esm/client/errors.js +2 -2
  47. package/dist/esm/client/receipts.d.ts +8 -1
  48. package/dist/esm/client/receipts.js +2 -1
  49. package/dist/esm/client/transport.d.ts +1 -1
  50. package/dist/esm/client/transport.js +2 -2
  51. package/dist/esm/kasse/drucker.d.ts +5 -0
  52. package/dist/esm/kasse/drucker.js +9 -0
  53. package/dist/esm/kasse/settings.js +5 -2
  54. package/dist/esm/models/cashregister.d.ts +2 -2
  55. package/dist/esm/models/receipt-company.d.ts +1 -1
  56. package/dist/esm/printing/escpos.d.ts +38 -4
  57. package/dist/esm/printing/escpos.js +84 -15
  58. package/dist/esm/printing/index.d.ts +2 -2
  59. package/dist/esm/printing/index.js +2 -2
  60. package/dist/esm/printing/qr-groesse.d.ts +26 -21
  61. package/dist/esm/printing/qr-groesse.js +21 -8
  62. package/dist/esm/react/index.d.ts +53 -0
  63. package/dist/esm/react/index.js +80 -1
  64. package/dist/esm/receipt/bild.d.ts +14 -0
  65. package/dist/esm/receipt/bild.js +62 -0
  66. package/dist/esm/receipt/blatt.d.ts +107 -0
  67. package/dist/esm/receipt/blatt.js +128 -0
  68. package/dist/esm/receipt/epos.d.ts +19 -8
  69. package/dist/esm/receipt/epos.js +40 -22
  70. package/dist/esm/receipt/grid.d.ts +1 -1
  71. package/dist/esm/receipt/grid.js +9 -1
  72. package/dist/esm/receipt/index.d.ts +4 -2
  73. package/dist/esm/receipt/index.js +4 -2
  74. package/dist/esm/receipt/layout-escpos.d.ts +31 -3
  75. package/dist/esm/receipt/layout-escpos.js +58 -20
  76. package/dist/esm/register/index.d.ts +1 -1
  77. package/dist/esm/register/index.js +1 -1
  78. package/dist/esm/register/pairing.d.ts +2 -2
  79. package/fixtures/erwartet/karte-eigener.blatt32.json +159 -0
  80. package/fixtures/erwartet/karte-eigener.blatt48.json +159 -0
  81. package/fixtures/erwartet/karte-gptom-ios.blatt32.json +231 -0
  82. package/fixtures/erwartet/karte-gptom-ios.blatt48.json +231 -0
  83. package/fixtures/erwartet/karte-gptom.blatt32.json +231 -0
  84. package/fixtures/erwartet/karte-gptom.blatt48.json +231 -0
  85. package/fixtures/erwartet/karte-hobex-cloud.blatt32.json +201 -0
  86. package/fixtures/erwartet/karte-hobex-cloud.blatt48.json +201 -0
  87. package/fixtures/erwartet/karte-hobex-hps.blatt32.json +225 -0
  88. package/fixtures/erwartet/karte-hobex-hps.blatt48.json +225 -0
  89. package/fixtures/erwartet/karte-mypos.blatt32.json +255 -0
  90. package/fixtures/erwartet/karte-mypos.blatt48.json +243 -0
  91. package/fixtures/erwartet/karte-stripe-eps.blatt32.json +195 -0
  92. package/fixtures/erwartet/karte-stripe-eps.blatt48.json +195 -0
  93. package/fixtures/erwartet/karte-stripe.blatt32.json +213 -0
  94. package/fixtures/erwartet/karte-stripe.blatt48.json +213 -0
  95. package/fixtures/erwartet/karte-sumup.blatt32.json +219 -0
  96. package/fixtures/erwartet/karte-sumup.blatt48.json +207 -0
  97. package/fixtures/erwartet/langer-artikelname.blatt32.json +177 -0
  98. package/fixtures/erwartet/langer-artikelname.blatt48.json +171 -0
  99. package/fixtures/erwartet/logo-probe-hoch.raster32.txt +120 -0
  100. package/fixtures/erwartet/logo-probe.raster32.txt +54 -0
  101. package/fixtures/erwartet/null-ausfall.blatt32.json +207 -0
  102. package/fixtures/erwartet/null-ausfall.blatt48.json +189 -0
  103. package/fixtures/erwartet/null-ausfall.grid32.txt +2 -0
  104. package/fixtures/erwartet/null-ausfall.grid48.txt +2 -0
  105. package/fixtures/erwartet/null-jahr.blatt32.json +213 -0
  106. package/fixtures/erwartet/null-jahr.blatt48.json +189 -0
  107. package/fixtures/erwartet/null-jahr.grid32.txt +2 -0
  108. package/fixtures/erwartet/null-jahr.grid48.txt +2 -0
  109. package/fixtures/erwartet/null-monat.blatt32.json +207 -0
  110. package/fixtures/erwartet/null-monat.blatt48.json +189 -0
  111. package/fixtures/erwartet/null-monat.grid32.txt +2 -0
  112. package/fixtures/erwartet/null-monat.grid48.txt +2 -0
  113. package/fixtures/erwartet/null-pruef.blatt32.json +207 -0
  114. package/fixtures/erwartet/null-pruef.blatt48.json +189 -0
  115. package/fixtures/erwartet/null-pruef.grid32.txt +2 -0
  116. package/fixtures/erwartet/null-pruef.grid48.txt +2 -0
  117. package/fixtures/erwartet/null-schluss.blatt32.json +207 -0
  118. package/fixtures/erwartet/null-schluss.blatt48.json +189 -0
  119. package/fixtures/erwartet/null-schluss.grid32.txt +2 -0
  120. package/fixtures/erwartet/null-schluss.grid48.txt +2 -0
  121. package/fixtures/erwartet/null-start.blatt32.json +207 -0
  122. package/fixtures/erwartet/null-start.blatt48.json +189 -0
  123. package/fixtures/erwartet/null-start.grid32.txt +2 -0
  124. package/fixtures/erwartet/null-start.grid48.txt +2 -0
  125. package/fixtures/erwartet/rabatt-chef-trinkgeld.blatt32.json +213 -0
  126. package/fixtures/erwartet/rabatt-chef-trinkgeld.blatt48.json +207 -0
  127. package/fixtures/erwartet/rabatt-einfach.blatt32.json +183 -0
  128. package/fixtures/erwartet/rabatt-einfach.blatt48.json +177 -0
  129. package/fixtures/erwartet/rabatt-trinkgeld.blatt32.json +213 -0
  130. package/fixtures/erwartet/rabatt-trinkgeld.blatt48.json +207 -0
  131. package/fixtures/erwartet/rabatt-wertgutschein.blatt32.json +219 -0
  132. package/fixtures/erwartet/rabatt-wertgutschein.blatt48.json +213 -0
  133. package/fixtures/erwartet/rabattzeilen.blatt32.json +201 -0
  134. package/fixtures/erwartet/rabattzeilen.blatt48.json +195 -0
  135. package/fixtures/erwartet/signaturausfall-verkauf.blatt32.json +195 -0
  136. package/fixtures/erwartet/signaturausfall-verkauf.blatt48.json +183 -0
  137. package/fixtures/erwartet/storno-rabatt.blatt32.json +249 -0
  138. package/fixtures/erwartet/storno-rabatt.blatt48.json +237 -0
  139. package/fixtures/erwartet/storno-rabatt.grid32.txt +2 -0
  140. package/fixtures/erwartet/storno-rabatt.grid48.txt +2 -0
  141. package/fixtures/erwartet/storno-teil.blatt32.json +207 -0
  142. package/fixtures/erwartet/storno-teil.blatt48.json +201 -0
  143. package/fixtures/erwartet/storno-teil.grid32.txt +2 -0
  144. package/fixtures/erwartet/storno-teil.grid48.txt +2 -0
  145. package/fixtures/erwartet/storno-voll.blatt32.json +219 -0
  146. package/fixtures/erwartet/storno-voll.blatt48.json +213 -0
  147. package/fixtures/erwartet/storno-voll.grid32.txt +2 -0
  148. package/fixtures/erwartet/storno-voll.grid48.txt +2 -0
  149. package/fixtures/erwartet/testkasse-verkauf.blatt32.json +225 -0
  150. package/fixtures/erwartet/testkasse-verkauf.blatt48.json +219 -0
  151. package/fixtures/erwartet/testkasse-verkauf.grid32.txt +5 -1
  152. package/fixtures/erwartet/testkasse-verkauf.grid48.txt +5 -1
  153. package/fixtures/erwartet/testsignatur-verkauf.blatt32.json +237 -0
  154. package/fixtures/erwartet/testsignatur-verkauf.blatt48.json +219 -0
  155. package/fixtures/erwartet/testsignatur-verkauf.grid32.txt +5 -1
  156. package/fixtures/erwartet/testsignatur-verkauf.grid48.txt +5 -1
  157. package/fixtures/erwartet/training.blatt32.json +237 -0
  158. package/fixtures/erwartet/training.blatt48.json +219 -0
  159. package/fixtures/erwartet/training.grid32.txt +2 -0
  160. package/fixtures/erwartet/training.grid48.txt +2 -0
  161. package/fixtures/erwartet/verkauf-bar.blatt32.json +177 -0
  162. package/fixtures/erwartet/verkauf-bar.blatt48.json +171 -0
  163. package/fixtures/erwartet/verkauf-karte.blatt32.json +177 -0
  164. package/fixtures/erwartet/verkauf-karte.blatt48.json +171 -0
  165. package/fixtures/erwartet/verkauf-kleinunternehmer.blatt32.json +183 -0
  166. package/fixtures/erwartet/verkauf-kleinunternehmer.blatt48.json +177 -0
  167. package/fixtures/hobex-hps-codes.json +1 -1
  168. package/fixtures/kasse-settings-standard.json +1 -1
  169. package/fixtures/kasse-texte.json +1 -1
  170. package/fixtures/manifest.json +109 -43
  171. package/fixtures/oberflaeche.json +1 -1
  172. package/package.json +20 -5
package/CHANGELOG.md CHANGED
@@ -4,6 +4,97 @@ Was vor 0.7.0 geschah, steht in der Commit-Historie (`git log`); ab hier wird
4
4
  es hier geführt. Ein Eintrag nennt die Änderung **und ihren Grund** —
5
5
  nur der Grund überlebt den nächsten Umbau.
6
6
 
7
+ ## 0.14.0
8
+
9
+ ### Das Beleg-Blatt: ein Beleg, der überall gleich aussieht
10
+
11
+ **Anlass:** Derselbe Beleg sah in der App, am Bon, in der Web-Kasse, im Panel
12
+ und im PDF verschieden aus. Das Raster war als einzige Wahrheit gedacht, aber
13
+ jeder Zeichner setzte Rahmen, Logo und QR selbst: das Panel stellte das Logo
14
+ über den Testkassen-Rahmen, das PDF legte es darauf, die App zeigte keins, der
15
+ Bon druckte Warnungen invers und doppelt hoch.
16
+
17
+ - `renderReceiptGrid` gibt Aufdrucke als drei Rasterzeilen aus (`====`, Text,
18
+ `====`). ESC/POS und ePOS drucken sie als normale fette Zeilen — keine doppelte
19
+ Höhe, kein Invertieren mehr. `grid32`/`grid48` der Belege mit Aufdruck ändern
20
+ sich, das Zeilenmodell nicht.
21
+ - Bekannter Unterschied, bleibt so: ESC/POS druckt `EUR` statt `€` (die
22
+ Ein-Byte-Codepage des Bondruckers kennt das Zeichen nicht). Bildschirm, PDF
23
+ und ePOS zeigen `€`; die Zeilen sind dadurch am Bon an diesen Stellen anders
24
+ gefüllt, das Raster bleibt gleich breit.
25
+ - Neu `belegBlatt(layout, { zeichen, logo, marke, qrGroesse })`: Reihenfolge
26
+ (Aufdrucke oben, Leerzeile, Logo, Leerzeile, Beleg, Marke), Logo-Maß je Stufe
27
+ S/M/L/XL (nie hochgerechnet), QR-Anteil wie am Drucker.
28
+ - Ein QR-Inhalt, der in keine QR-Version passt (Korrektur M, mehr als 2331
29
+ Byte), bekommt im Blatt den Anteil 0, statt dass `belegBlatt` wirft. ESC/POS
30
+ und ePOS lassen den QR dann weg und melden es über `qrFehler`; der Beleg steht
31
+ ohne QR. Die Bildschirm-Ansicht ruft `renderQr` weiter mit der Nutzlast, damit
32
+ die Oberfläche den fehlenden QR anzeigen kann (Papierbeleg-Hinweis). **Grund:** Ein Wurf riss jeden Zeichner mit — die Bon-Ansicht der
33
+ Web-Kasse fiel ganz aus, Bon und PDF ebenso. Neu `qrPasstInVersion(nutzlast)`
34
+ (`./printing`); `qrModulAnzahl` wirft weiter.
35
+ - Neu `logoRaster` (RGBA → einfarbiges Rasterbild), `escPosRasterBild`,
36
+ `eposBildXml`; `escPosLayoutBytes` und `eposPrintXml` nehmen `logo` und `marke`.
37
+ - Neu `BelegBlattView` / `BelegBlattZeilen` (`./react`); `ReceiptLayoutView` ist
38
+ `@deprecated`. `BelegBlattView` zeigt ein Logo ueber 4096x4096px (oder 0)
39
+ ebenso wenig wie ein nicht geladenes -- neu `LOGO_PIXEL_MAX`,
40
+ `logoPixelZulaessig` (`./receipt`). **Grund:** Bildschirm und Bon zeigen
41
+ dasselbe Logo; das Druck-Kit lehnt ein zu grosses Logo beim Rastern fuer
42
+ den Bon schon ab (dieselbe Grenze), der Bildschirm bisher nicht -- ein
43
+ 5000x1200px-Logo erschien am Bildschirm und im PDF, aber nie auf dem
44
+ gedruckten Beleg.
45
+ - Neu `ReceiptWithCompany.logoStufe` (aus `logo_skala` der Beleg-Antwort,
46
+ Vorgabe `M`): Panel und App kannten die Logo-Stufe des Betriebs bisher nicht.
47
+ - `createPrintJob` nimmt `logo` und `marke`: der Netzwerk-Drucker (Connect)
48
+ druckt dasselbe Blatt wie USB, Bluetooth und ePOS direkt. Neu
49
+ `rasterZeilenBase64` (gemeinsam für ePOS-`<image>` und den Druckjob).
50
+ - Goldens `erwartet/<name>.blatt32.json`/`.blatt48.json`,
51
+ `erwartet/logo-probe.raster32.txt` (mit Teiltransparenz) und
52
+ `erwartet/logo-probe-hoch.raster32.txt` (höhenbegrenzt) für den Dart-Zwilling.
53
+ - `escPosRasterBild` wirft bei einer Bildhöhe über 65535 Punkten (`GS v 0` trägt
54
+ die Höhe in zwei Bytes).
55
+
56
+ ### Achtung: Brüche
57
+
58
+ - **Aufdrucke im Raster.** `renderReceiptGrid` gibt jeden Aufdruck als drei
59
+ Zeilen `kind:'banner'` aus (`====`, Text, `====`). *Umstellen:* eigene
60
+ Rahmen oder Sonderstile für Aufdrucke entfernen (sie stünden sonst doppelt)
61
+ und nicht annehmen, dass die erste `banner`-Zeile die einzige ist — der Text
62
+ steht in der mittleren.
63
+ - **`ReceiptWithCompany.logoStufe` ist Pflicht.** `getReceiptWithCompany` füllt
64
+ es selbst. *Umstellen:* von Hand gebaute Objekte (Tests, Vorschauen) brauchen
65
+ `logoStufe: 'M'`.
66
+ - **QR-Vorgabe `auto` deckelt bei 6 Punkten je Modul (vorher 4)** — in npm und
67
+ Dart dasselbe. Am ESC/POS-Bon wird der QR ohne ausdrückliche Wahl größer
68
+ (80 mm: rund 55 % statt 37 % der Breite). *Umstellen:* wer die alte Größe
69
+ will, stellt `qrGroesse: 'klein'`.
70
+ - **Nativer ESC/POS-QR mit Fehlerkorrektur M (vorher L)**, wie ePOS, Bildweg
71
+ und Blatt — der Kasten am Bildschirm ist damit genau der gedruckte QR.
72
+ Manche Nutzlasten brauchen eine Version mehr. *Umstellen:* den alten
73
+ Bytestrom liefert `qrCorrection: 'L'` (zusammen mit `qrGroesse: 'klein'`).
74
+ - **ePOS-Vorgabe `qrGroesse` ist `auto`** (vorher `mittel`). Derselbe Wert,
75
+ kein Byte anders; nur wer die Vorgabe ausliest oder dokumentiert, merkt es.
76
+
77
+ ## 0.13.2
78
+
79
+ ### Die Paketseite erklaert, wofuer das Paket da ist
80
+
81
+ **Anlass:** Wer auf npm landet, sah eine Wand aus Technik und nirgends, worum
82
+ es geht. Die Seite traegt jetzt das Kasseneck-Logo, einen englischen Einzeiler
83
+ fuer Besucher von aussen, und eine Tabelle, welche Pflichten einer
84
+ oesterreichischen Registrierkasse wo erledigt werden — mit Verweisen auf die
85
+ Wissensseiten und einem ausdruecklichen Hinweis, dass hier kein Rechtsrat steht
86
+ und die Verantwortung beim Unternehmer bleibt. Kopf und Fuss nennen Kreiseck
87
+ als Absender und verlinken dorthin. Am Code aendert sich nichts.
88
+
89
+ ### Der Vertrag nennt keinen Anmeldedienst mehr beim Namen
90
+
91
+ **Anlass:** Die Doku sprach an 16 Stellen von einem bestimmten Anbieter,
92
+ obwohl das Paket ihn gar nicht kennt: `registerUserAuth` bekommt eine Funktion,
93
+ die ein Token liefert — woher es stammt, geht das Paket nichts an. Ein
94
+ Implementierungsdetail im Vertrag bindet beide Seiten grundlos aneinander;
95
+ jetzt steht dort "ID-Token des Anmeldediensts". Damit verschwindet der Name
96
+ auch aus den ausgelieferten Typdeklarationen.
97
+
7
98
  ## 0.13.1
8
99
 
9
100
  ### Der 404 beim Abbruch wird benannt, nicht als Abriss gefuehrt
package/README.md CHANGED
@@ -1,15 +1,87 @@
1
- # @kreiseck/kasseneck-api
2
-
3
- JavaScript-/TypeScript-Client für das Kasseneck-Backend — der Zwilling des
4
- Flutter-Pakets `kasseneck_api`. Er spricht dieselben Endpunkte, führt dieselben
5
- Modelle und dieselben Enum-Werte; ein eingecheckter Abzug der Dart-Enums wird
6
- im Test gegengeprüft, damit die beiden Pakete nicht auseinanderdriften.
7
-
8
- Das Paket deckt ab: Belege ausstellen und stornieren, Belege und Kassen
9
- auflisten, Berichte herunterladen, Status bei FinanzOnline abfragen,
10
- Stripe-Zahllinks und Hobex-Cloud-Zahlungen, das Beleg-Layout und die
11
- ESC/POS-Erzeugung für den Bondrucker — und unter `./partner` die
12
- **Partner-API**: Betriebe anlegen und bis zur laufenden Kasse begleiten.
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/kreiseck-at/kasseneck-api/main/doc/kasseneck.gif" alt="Kasseneck — RKSV-Registrierkasse aus Österreich" width="420">
3
+ </p>
4
+
5
+ <h1 align="center">@kreiseck/kasseneck-api</h1>
6
+
7
+ <p align="center">
8
+ <b>Austrian fiscal cash register (RKSV) for JavaScript and TypeScript — signed receipts, card payments, receipt printing.</b>
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://www.npmjs.com/package/@kreiseck/kasseneck-api"><img src="https://img.shields.io/npm/v/%40kreiseck%2Fkasseneck-api?color=136B6B&label=npm" alt="npm"></a>
13
+ <img src="https://img.shields.io/badge/RKSV-%C2%A7%20131b%20BAO-136B6B" alt="RKSV">
14
+ <img src="https://img.shields.io/badge/Lizenz-Apache--2.0-136B6B" alt="Apache-2.0">
15
+ <a href="https://kasseneck.at"><img src="https://img.shields.io/badge/Kasseneck-kasseneck.at-132A2A" alt="kasseneck.at"></a>
16
+ <a href="https://kreiseck.com"><img src="https://img.shields.io/badge/von-Kreiseck-132A2A" alt="Kreiseck Software Solutions"></a>
17
+ </p>
18
+
19
+ **Kasseneck** ist eine österreichische Registrierkasse nach RKSV. Dieses Paket ist
20
+ der JavaScript-/TypeScript-Client dafür: Ihr Code stellt Belege aus, storniert sie,
21
+ nimmt Kartenzahlungen entgegen und druckt Bons. Es ist der Zwilling des
22
+ Flutter-Pakets [`kasseneck_api`](https://pub.dev/packages/kasseneck_api):
23
+ dieselben Endpunkte, dieselben Modelle, dieselben Enum-Werte, im Test
24
+ gegeneinander geprüft.
25
+
26
+ ## Was eine Registrierkasse in Österreich können muss
27
+
28
+ Die Registrierkassen- und Belegerteilungspflicht steht in § 131b der
29
+ Bundesabgabenordnung, die technischen Anforderungen an die Sicherheitseinrichtung
30
+ in der Registrierkassensicherheitsverordnung (RKSV). Daraus ergibt sich eine
31
+ ganze Kette von Aufgaben — die Tabelle zeigt, welche davon **diese Software**
32
+ übernimmt und welche beim Betrieb selbst bleiben:
33
+
34
+ | Aufgabe | Wo sie erledigt wird |
35
+ | --- | --- |
36
+ | [Signaturerstellungseinheit](https://kasseneck.at/wissen/signaturerstellungseinheit) — jede Barzahlung wird signiert | Kasseneck, nichts zu installieren |
37
+ | [Verkettung und DEP](https://kasseneck.at/wissen/dep) — jeder Beleg trägt den vorigen, das Protokoll ist exportierbar | Kasseneck-Backend |
38
+ | [Startbeleg, Monatsbeleg, Jahresbeleg](https://kasseneck.at/wissen/startbeleg-monatsbeleg-jahresbeleg) | Kasseneck, automatisch |
39
+ | [Meldungen an FinanzOnline](https://kasseneck.at/wissen/finanzonline) — Anmeldung, Ausfall, Außerbetriebnahme | Kasseneck-Backend |
40
+ | [Belegerteilungspflicht](https://kasseneck.at/wissen/belegerteilungspflicht) — jeder Kunde bekommt einen Beleg | **dieses Paket** — Bon, PDF, Bildschirm oder Link |
41
+ | [Ausfall der Signatureinheit](https://kasseneck.at/wissen/ausfall) — Sammelbeleg, Meldung, Nachsignatur | Kasseneck, automatisch |
42
+ | [Kassennachschau](https://kasseneck.at/wissen/kassennachschau) — der Prüfer verlangt das DEP | Kasseneck, Export auf Knopfdruck |
43
+ | Anmeldung der Kasse, Aufbewahrung, steuerliche Würdigung | **beim Unternehmer** |
44
+
45
+ Kurz: Sie bauen die Kassenoberfläche, nicht die Sicherheitseinrichtung. Ein Aufruf
46
+ von `createReceipt(...)` erzeugt einen signierten, verketteten und im DEP
47
+ abgelegten Beleg. Die Signaturkette wird gegen das offizielle Prüfwerkzeug des
48
+ BMF getestet.
49
+
50
+ > **Kein Rechts- oder Steuerrat.** Dieser Abschnitt beschreibt, was die Software
51
+ > tut. Er ersetzt keine Beratung und begründet keine Zusicherung, dass ein
52
+ > bestimmter Betrieb damit alle Pflichten erfüllt. Verbindlich sind die
53
+ > Bundesabgabenordnung, die RKSV und die Erlässe des BMF; die Verantwortung für
54
+ > Anmeldung, Betrieb und Aufbewahrung bleibt beim Unternehmer. Ausführlicher und
55
+ > mit Quellen: [kasseneck.at/wissen](https://kasseneck.at/wissen).
56
+ > Stand: September 2026.
57
+
58
+ ## Erst ausprobieren
59
+
60
+ Es gibt eine Test-Umgebung mit eigenem Schlüssel und Test-Signaturen, getrennt
61
+ vom Echtbetrieb — die aktuellen Konditionen stehen auf
62
+ [kasseneck.at/preise](https://kasseneck.at/preise), die Schnittstelle ist unter
63
+ [kasseneck.at/api-doku](https://kasseneck.at/api-doku) beschrieben.
64
+
65
+ ## Lieber eine fertige Kasse?
66
+
67
+ Dieses Paket ist für alle, die eine eigene Anwendung bauen. Wer einfach kassieren
68
+ will, muss nichts davon programmieren:
69
+
70
+ - **[Kasseneck — die fertige Registrierkasse](https://kasseneck.at)** für Telefon,
71
+ Tablet und Browser, inklusive Signaturerstellungseinheit und
72
+ FinanzOnline-Anmeldung.
73
+ - **[Lösungen nach Branche](https://kasseneck.at/branchen)** — vom Lokal bis zum Taxi.
74
+ - **[Preise](https://kasseneck.at/preise)**
75
+ - **[Kontakt](https://kasseneck.at/kontakt)** — auch für Kassenwechsel,
76
+ Partnerschaften und eigene Integrationen.
77
+
78
+ ## Was drin ist
79
+
80
+ Belege ausstellen und stornieren, Belege und Kassen auflisten, Berichte
81
+ herunterladen, Status bei FinanzOnline abfragen, Stripe-Zahllinks und
82
+ Hobex-Cloud-Zahlungen, das Beleg-Layout und die ESC/POS-Erzeugung für den
83
+ Bondrucker — und unter `./partner` die **Partner-API**: Betriebe anlegen und bis
84
+ zur laufenden Kasse begleiten.
13
85
 
14
86
  **Es läuft im Browser und in Node.** ESM ist das Hauptformat, CommonJS liegt
15
87
  daneben; beides mit eigenen Typdeklarationen. Node ab 20.18 (`fetch` muss
@@ -33,7 +105,7 @@ bevorzugte:
33
105
  | Weg | Wer | Wie |
34
106
  |-----|-----|-----|
35
107
  | `apiKeyAuth` | Geräte, POS-Apps, Dritte | `api_key` als Bearer + `cashregister-token`-Kopfzeile |
36
- | `registerUserAuth` | Browser-Kasse | Firebase-ID-Token als Bearer + `register-session`-Kopfzeile, Kasse als Parameter |
108
+ | `registerUserAuth` | Browser-Kasse | ID-Token des Anmeldediensts als Bearer + `register-session`-Kopfzeile, Kasse als Parameter |
37
109
 
38
110
  ```ts
39
111
  import { apiKeyAuth, registerUserAuth } from '@kreiseck/kasseneck-api';
@@ -41,7 +113,7 @@ import { apiKeyAuth, registerUserAuth } from '@kreiseck/kasseneck-api';
41
113
  // Gerät/POS: der api_key gehört auf ein Gerät, nie in einen Browser.
42
114
  const geraet = apiKeyAuth({ apiKey: 'kr_live_…', cashregisterToken: 'cb_live_…' });
43
115
 
44
- // Browser-Kasse: das Paket kennt Firebase nicht — es bekommt Funktionen, die
116
+ // Browser-Kasse: das Paket kennt den Anmeldedienst nicht — es bekommt Funktionen, die
45
117
  // ein gültiges Token bzw. die laufende Sitzung liefern. Beide werden bei JEDEM
46
118
  // Aufruf befragt (ID-Tokens laufen nach einer Stunde ab, die Kassen-Sitzung
47
119
  // nach 90 Sekunden).
@@ -66,7 +138,7 @@ const geraet = await pairRegisterDevice({ code: 'K7NPQR34', label: 'Schank' });
66
138
  const sitzung = await registerUserLogin({ ...geraet, userId: 'ru-1', pin: '1234' });
67
139
  ```
68
140
 
69
- Mit `sitzung.customToken` meldet sich der Verbraucher bei Firebase an; das
141
+ Mit `sitzung.customToken` meldet sich der Verbraucher beim Anmeldedienst an; das
70
142
  daraus entstehende ID-Token und `sitzung.sessionId` ergeben `registerUserAuth`.
71
143
 
72
144
  Eine anmeldungsfreie Anmeldung gibt es dafür **nicht** — sie wäre ein
@@ -388,8 +460,9 @@ const mass = qrGroesseFuer({ nutzlast: beleg.qr, papierbreitePunkte: QR_DRUCK_PU
388
460
 
389
461
  Am Belegweg passiert das von selbst. `qrGroesse` ist ein **Deckel**, keine
390
462
  Vorgabe: gedruckt wird die größte Größe, die noch passt, höchstens aber der
391
- Deckel. `auto` (Vorgabe) deckelt beim Bestandswert 4 — ohne ausdrückliche Wahl
392
- ändert sich also kein Byte.
463
+ Deckel. `auto` (Vorgabe) deckelt bei 6 Punkten je Modul — wie im Dart-Zwilling
464
+ und am Epson-Weg; `klein` deckelt bei 4. Alle Druckwege setzen den QR mit
465
+ Fehlerkorrektur M.
393
466
 
394
467
  ```ts
395
468
  import { escPosLayoutErgebnis } from '@kreiseck/kasseneck-api/receipt';
@@ -402,8 +475,8 @@ const { bytes, qrFehler, qrAusweich } = escPosLayoutErgebnis(layout, {
402
475
  ```
403
476
 
404
477
  Der Epson-Weg (`eposPrintXml` / `eposDirectPrint`) rechnet genauso;
405
- `eposPrintXmlErgebnis` gibt dort `{ xml, qrFehler, qrAusweich }`. Sein
406
- Bestandswert ist 6, deshalb ist die Vorgabe dort der Deckel `mittel`.
478
+ `eposPrintXmlErgebnis` gibt dort `{ xml, qrFehler, qrAusweich }`. Die Vorgabe
479
+ ist auch dort `auto`.
407
480
 
408
481
  `qrFehler` heißt „Beleg ohne QR" — das gehört dem Kunden gesagt. `qrAusweich`
409
482
  heißt „gedruckt, aber der eingestellte Weg taugt für dieses Gerät nicht" — das
@@ -411,6 +484,30 @@ gehört dem Chef gesagt. Den Bildweg fährt das Paket nur mit einem `qrMatrix`,
411
484
  das die Nutzlast in ein fertiges Raster übersetzt: hier wird bewusst weder ein
412
485
  QR gerechnet noch ein Bild verarbeitet.
413
486
 
487
+ ## Das Beleg-Blatt: überall derselbe Beleg
488
+
489
+ Bildschirm, Bon, ePOS und PDF setzen dasselbe **Blatt**: Rasterzeilen, Firmenlogo,
490
+ QR und die Marke „erstellt mit Kasseneck", mit Größen als Anteil der Blattbreite
491
+ und in Zeilen (eine Zeile = zwei Zeichenbreiten).
492
+
493
+ ```tsx
494
+ import { BelegBlattView } from '@kreiseck/kasseneck-api/react';
495
+
496
+ <BelegBlattView layout={layout} logo={{ url: company.logoUrl, stufe: 'M' }} marke={company.showKreiseckLogo} renderQr={(d) => <QrSvg data={d} />} />
497
+ ```
498
+
499
+ ```ts
500
+ import { escPosLayoutBytes, logoMass, logoRaster } from '@kreiseck/kasseneck-api/receipt';
501
+
502
+ const mass = logoMass({ stufe: 'M', pxBreite: bild.width, pxHoehe: bild.height }, 48);
503
+ const raster = logoRaster(imageData.data, bild.width, bild.height, mass, 48);
504
+ escPosLayoutBytes(layout, { paperSize: 'mm80', logo: { stufe: 'M', pxBreite: bild.width, pxHoehe: bild.height, raster }, marke: true });
505
+ ```
506
+
507
+ Logo-Stufen: S 42 % × 5 Zeilen, M 62 % × 8, L 80 % × 12, XL 94 % × 16 — eingepasst,
508
+ nie hochgerechnet. Der Aufdruck (TESTKASSE, STORNOBELEG …) ist ein Rahmen aus
509
+ `=`-Zeilen, auf jedem Weg gleich.
510
+
414
511
  ## Hobex HPS über Kasseneck Connect
415
512
 
416
513
  Ein Browser hat weiterhin keine rohen TCP-Sockets — ein **direkter**
@@ -444,7 +541,8 @@ Android-SDKs ohne Entsprechung hier.
444
541
  ## Was hier grundsätzlich nicht dazugehört
445
542
 
446
543
  Die Druckeransteuerung selbst (dieses Paket erzeugt die Bytes, es verschickt
447
- sie nicht), Firmenlogos und Rasterbilder, und die PDF-Erzeugung.
544
+ sie nicht) und die PDF-Erzeugung. Bilder dekodieren (PNG/JPEG): das Paket
545
+ rastert fertige RGBA-Pixel, das Laden des Bilds bleibt bei der Anwendung.
448
546
 
449
547
  ## Entwicklung
450
548
 
@@ -476,7 +574,7 @@ steht. Deshalb prüft das Skript auf ein `status`-Feld und nicht auf Erfolg.
476
574
  Bewusst außerhalb von `npm test`: Sie braucht Netz. Ist keines da, sagt sie es
477
575
  und endet mit 0. Aufrufe, die unter `/v1` absichtlich keine Weiterleitung
478
576
  haben — der Kassen-Weg über `kasse.kasseneck.at/api`, die Aufrufe mit
479
- Firebase-ID-Token — stehen mit Grund in `scripts/erreichbarkeit-ausnahmen.json`.
577
+ ID-Token — stehen mit Grund in `scripts/erreichbarkeit-ausnahmen.json`.
480
578
  Wird eine Ausnahme erreichbar, schlägt die Prüfung an: Sonst sänke die Zahl nie.
481
579
 
482
580
  ## Vertragsdateien für die Zwillinge
@@ -520,3 +618,11 @@ ankommt.
520
618
  ## Lizenz
521
619
 
522
620
  Apache-2.0 — siehe `LICENSE` und `NOTICE`.
621
+
622
+ ---
623
+
624
+ **Kasseneck** ist ein Produkt von
625
+ [Kreiseck Software Solutions](https://kreiseck.com) aus Salzburg — Apps,
626
+ Kassensysteme und Automatisierungen. Fragen zur Schnittstelle, zu eigenen
627
+ Integrationen oder zu einer Partnerschaft:
628
+ [kasseneck.at/kontakt](https://kasseneck.at/kontakt).
@@ -6,7 +6,7 @@
6
6
  * Bearer plus die Kopfzeile `cashregister-token` (wie im Flutter-Zwilling
7
7
  * `kasseneck_api`).
8
8
  * - `registerUserAuth` — der Weg der Browser-Kasse: ein Kassen-Benutzer, per
9
- * PIN an einem gekoppelten Geraet angemeldet. Firebase-ID-Token als Bearer,
9
+ * PIN an einem gekoppelten Geraet angemeldet. ID-Token als Bearer,
10
10
  * die laufende Sitzung als Kopfzeile `register-session`, die Kasse als
11
11
  * Parameter `cashregisterId` in der Nutzlast.
12
12
  *
@@ -14,9 +14,9 @@
14
14
  * fuehrt keine eigenen HTTP-Aufrufe, kennt den Transport nicht und haelt keinen
15
15
  * Zustand — genau deshalb ist sie austauschbar und einzeln testbar.
16
16
  *
17
- * Das Paket weiss **nichts** von Firebase: `registerUserAuth` bekommt eine
17
+ * Das Paket weiss **nichts** vom Anmeldedienst: `registerUserAuth` bekommt eine
18
18
  * Funktion, die ein gueltiges ID-Token liefert (darf `async` sein). Sie wird
19
- * bei **jedem** Aufruf befragt — Firebase-ID-Tokens laufen nach einer Stunde
19
+ * bei **jedem** Aufruf befragt — ID-Tokens laufen nach einer Stunde
20
20
  * ab, die Sitzung der Browser-Kasse lebt sogar nur 90 Sekunden und wird alle
21
21
  * 30 Sekunden erneuert; ein einmal gemerkter Wert waere also bald tot.
22
22
  */
@@ -39,7 +39,7 @@ export interface ApiKeyAuthOptions {
39
39
  cashregisterToken: string;
40
40
  }
41
41
  export interface RegisterUserAuthOptions {
42
- /** Liefert ein gueltiges Firebase-ID-Token; wird pro Anfrage befragt. */
42
+ /** Liefert ein gueltiges ID-Token des Anmeldediensts; wird pro Anfrage befragt. */
43
43
  getIdToken: () => string | Promise<string>;
44
44
  /** Liefert die laufende Kassen-Sitzung; wird pro Anfrage befragt. */
45
45
  getSessionId: () => string | Promise<string>;
@@ -7,7 +7,7 @@
7
7
  * Bearer plus die Kopfzeile `cashregister-token` (wie im Flutter-Zwilling
8
8
  * `kasseneck_api`).
9
9
  * - `registerUserAuth` — der Weg der Browser-Kasse: ein Kassen-Benutzer, per
10
- * PIN an einem gekoppelten Geraet angemeldet. Firebase-ID-Token als Bearer,
10
+ * PIN an einem gekoppelten Geraet angemeldet. ID-Token als Bearer,
11
11
  * die laufende Sitzung als Kopfzeile `register-session`, die Kasse als
12
12
  * Parameter `cashregisterId` in der Nutzlast.
13
13
  *
@@ -15,9 +15,9 @@
15
15
  * fuehrt keine eigenen HTTP-Aufrufe, kennt den Transport nicht und haelt keinen
16
16
  * Zustand — genau deshalb ist sie austauschbar und einzeln testbar.
17
17
  *
18
- * Das Paket weiss **nichts** von Firebase: `registerUserAuth` bekommt eine
18
+ * Das Paket weiss **nichts** vom Anmeldedienst: `registerUserAuth` bekommt eine
19
19
  * Funktion, die ein gueltiges ID-Token liefert (darf `async` sein). Sie wird
20
- * bei **jedem** Aufruf befragt — Firebase-ID-Tokens laufen nach einer Stunde
20
+ * bei **jedem** Aufruf befragt — ID-Tokens laufen nach einer Stunde
21
21
  * ab, die Sitzung der Browser-Kasse lebt sogar nur 90 Sekunden und wird alle
22
22
  * 30 Sekunden erneuert; ein einmal gemerkter Wert waere also bald tot.
23
23
  */
@@ -5,7 +5,7 @@ import type { InternerTransport } from './aufrufe.js';
5
5
  *
6
6
  * **Anmeldeweg:** `listMyCashregisters` laeuft im Backend unter
7
7
  * `checkRequest(req, 'customer', …, {allowRegisterUser: true})` — der Bearer
8
- * muss also ein Firebase-ID-Token sein. Mit `apiKeyAuth` (api_key als Bearer)
8
+ * muss also ein ID-Token des Anmeldediensts sein. Mit `apiKeyAuth` (api_key als Bearer)
9
9
  * ist dieser Endpunkt **nicht** erreichbar; fuer die Browser-Kasse ist
10
10
  * `registerUserAuth` der Weg. Dieses Paket bildet das nicht nach — wer darf,
11
11
  * entscheidet allein das Backend. Der Hinweis steht hier, damit ein Leser
@@ -8,7 +8,7 @@ const errors_js_1 = require("./errors.js");
8
8
  *
9
9
  * **Anmeldeweg:** `listMyCashregisters` laeuft im Backend unter
10
10
  * `checkRequest(req, 'customer', …, {allowRegisterUser: true})` — der Bearer
11
- * muss also ein Firebase-ID-Token sein. Mit `apiKeyAuth` (api_key als Bearer)
11
+ * muss also ein ID-Token des Anmeldediensts sein. Mit `apiKeyAuth` (api_key als Bearer)
12
12
  * ist dieser Endpunkt **nicht** erreichbar; fuer die Browser-Kasse ist
13
13
  * `registerUserAuth` der Weg. Dieses Paket bildet das nicht nach — wer darf,
14
14
  * entscheidet allein das Backend. Der Hinweis steht hier, damit ein Leser
@@ -30,7 +30,7 @@
30
30
  * Sonderfall.
31
31
  *
32
32
  * **Geheimnisse gehoeren in keinen dieser Fehler.** Fehlermeldungen landen in
33
- * Protokollen und Fehlerdiensten; weder `api_key`, Kassen-Token, Firebase-
33
+ * Protokollen und Fehlerdiensten; weder `api_key`, Kassen-Token, ID-
34
34
  * ID-Token noch Sitzungsbezeichner duerfen dorthin. Deshalb tragen die Fehler
35
35
  * ausschliesslich Funktionsname, HTTP-Status/Inhaltstyp, den vom Paket
36
36
  * formulierten Grund und die vom Backend formulierte Meldung — nie Kopfzeilen,
@@ -31,7 +31,7 @@
31
31
  * Sonderfall.
32
32
  *
33
33
  * **Geheimnisse gehoeren in keinen dieser Fehler.** Fehlermeldungen landen in
34
- * Protokollen und Fehlerdiensten; weder `api_key`, Kassen-Token, Firebase-
34
+ * Protokollen und Fehlerdiensten; weder `api_key`, Kassen-Token, ID-
35
35
  * ID-Token noch Sitzungsbezeichner duerfen dorthin. Deshalb tragen die Fehler
36
36
  * ausschliesslich Funktionsname, HTTP-Status/Inhaltstyp, den vom Paket
37
37
  * formulierten Grund und die vom Backend formulierte Meldung — nie Kopfzeilen,
@@ -66,7 +66,7 @@ exports.isKasseneckAuthError = isKasseneckAuthError;
66
66
  exports.isKasseneckValidationError = isKasseneckValidationError;
67
67
  // Bezeichner-artig: Buchstabe vorn, danach nur Bezeichnerzeichen, hoechstens
68
68
  // 64 Zeichen. Das laesst `TypeError`, `ECONNREFUSED` und `auth/internal-error`
69
- // durch, aber keinen Freitext und kein Firebase-ID-Token (~900 Zeichen).
69
+ // durch, aber keinen Freitext und kein ID-Token (~900 Zeichen).
70
70
  const BEZEICHNER = /^[A-Za-z][A-Za-z0-9_./-]{0,63}$/;
71
71
  /**
72
72
  * Reduziert eine fremde Ursache auf Name und Code — und verwirft beides, wenn
@@ -2,6 +2,7 @@ import { ReceiptType, type ReceiptTypeKey, KeckPaymentMethod, type KeckPaymentMe
2
2
  import { type Receipt, type ReceiptCompany, type ReceiptItem, type Voucher, type ReceiptSummary, type ReportMonth, type CancellationItem, type CancellationOf, type CancellationReason } from '../models/index.js';
3
3
  import type { InternerTransport } from './aufrufe.js';
4
4
  import type { Pruefangaben, ReceiptLayout } from '../receipt/layout.js';
5
+ import type { LogoStufe } from '../receipt/blatt.js';
5
6
  /**
6
7
  * Beleg-Endpunkte — Zwilling der Beleg-Aufrufe in
7
8
  * kasseneck_api/lib/kasseneck_api.dart.
@@ -168,6 +169,12 @@ export interface ReceiptWithCompany {
168
169
  * fuer Clients, die das Layout selbst bauen; null bei altem Backend.
169
170
  */
170
171
  pruefangaben: Pruefangaben | null;
172
+ /**
173
+ * Groesse des Firmenlogos am Beleg (Kasse-Einstellung `logoSkala` des
174
+ * Betriebs). Bildschirm, Bon und PDF setzen das Logo in genau dieser Stufe;
175
+ * liefert das Backend sie nicht (alt), gilt `M` -- der Bestandswert.
176
+ */
177
+ logoStufe: LogoStufe;
171
178
  }
172
179
  /**
173
180
  * Gemeinsame Umsetzung aller Belegarten (Zwilling von `_createReceipt`).
@@ -256,7 +263,7 @@ export interface ListMyReceiptsOptions {
256
263
  *
257
264
  * **Anmeldeweg:** Der Endpunkt laeuft im Backend unter
258
265
  * `checkRequest(req, 'customer', …, {allowRegisterUser: true})`, der Bearer
259
- * muss also ein Firebase-ID-Token sein — mit `apiKeyAuth` ist er nicht
266
+ * muss also ein ID-Token des Anmeldediensts sein — mit `apiKeyAuth` ist er nicht
260
267
  * erreichbar. Ausserdem prueft das Backend die Kassenzuweisung hier im Rumpf
261
268
  * (der Endpunkt laeuft mit `checkCashRegister: false`), ein Kassen-Benutzer
262
269
  * bekommt also nur die ihm zugewiesenen Kassen.
@@ -217,7 +217,7 @@ function zeroReceipt(rufen) {
217
217
  *
218
218
  * **Anmeldeweg:** Der Endpunkt laeuft im Backend unter
219
219
  * `checkRequest(req, 'customer', …, {allowRegisterUser: true})`, der Bearer
220
- * muss also ein Firebase-ID-Token sein — mit `apiKeyAuth` ist er nicht
220
+ * muss also ein ID-Token des Anmeldediensts sein — mit `apiKeyAuth` ist er nicht
221
221
  * erreichbar. Ausserdem prueft das Backend die Kassenzuweisung hier im Rumpf
222
222
  * (der Endpunkt laeuft mit `checkCashRegister: false`), ein Kassen-Benutzer
223
223
  * bekommt also nur die ihm zugewiesenen Kassen.
@@ -582,5 +582,6 @@ function belegMitFirmaAusHuelle(daten, functionName) {
582
582
  kopfId: typeof d.kopfId === 'string' ? d.kopfId : null,
583
583
  layout,
584
584
  pruefangaben: pa ? { karteRegistriertAm: text(pa.karteRegistriertAm), kasseRegistriertAm: text(pa.kasseRegistriertAm) } : null,
585
+ logoStufe: d.logo_skala === 'S' || d.logo_skala === 'M' || d.logo_skala === 'L' || d.logo_skala === 'XL' ? d.logo_skala : 'M',
585
586
  };
586
587
  }
@@ -7,7 +7,7 @@ import type { KasseneckAuth } from './auth.js';
7
7
  * Der Transport macht drei Dinge und sonst nichts: Anfrage bauen (Kopfzeilen
8
8
  * von der Anmeldung, Nutzlast aus Auth-Parametern und Aufruferparametern),
9
9
  * Zeitlimit ueberwachen, und die Antworthuelle aufloesen. Er kennt keine
10
- * einzelne Backend-Funktion und keine Firebase-Details.
10
+ * einzelne Backend-Funktion und keine Details der Infrastruktur.
11
11
  *
12
12
  * Es gibt **zwei Einstiegspunkte** auf demselben Kern: [createTransport] fuer
13
13
  * die JSON-Aufrufe und [createBinaryTransport] fuer die beiden Bericht-
@@ -12,7 +12,7 @@ const errors_js_1 = require("./errors.js");
12
12
  * Der Transport macht drei Dinge und sonst nichts: Anfrage bauen (Kopfzeilen
13
13
  * von der Anmeldung, Nutzlast aus Auth-Parametern und Aufruferparametern),
14
14
  * Zeitlimit ueberwachen, und die Antworthuelle aufloesen. Er kennt keine
15
- * einzelne Backend-Funktion und keine Firebase-Details.
15
+ * einzelne Backend-Funktion und keine Details der Infrastruktur.
16
16
  *
17
17
  * Es gibt **zwei Einstiegspunkte** auf demselben Kern: [createTransport] fuer
18
18
  * die JSON-Aufrufe und [createBinaryTransport] fuer die beiden Bericht-
@@ -81,7 +81,7 @@ function createCore(options) {
81
81
  throw new errors_js_1.KasseneckNetworkError(fehlerName, true, zeitlimitMs);
82
82
  }
83
83
  // Eigene Pruefungen tragen ihren geheimnisfreien Grund weiter; von einer
84
- // fremden Ursache (Firebase & Co.) bleibt nichts uebrig — weder Meldung
84
+ // fremden Ursache bleibt nichts uebrig — weder Meldung
85
85
  // noch Verdichtung, siehe Klassenkommentar zu KasseneckAuthError.
86
86
  const grund = ursache instanceof errors_js_1.KasseneckAuthError ? ursache.reason : 'Anmeldung fehlgeschlagen';
87
87
  throw new errors_js_1.KasseneckAuthError(grund, { functionName: fehlerName });
@@ -1,5 +1,6 @@
1
1
  import type { InternerTransport } from '../client/aufrufe.js';
2
2
  import type { ReceiptLayout } from '../receipt/layout.js';
3
+ import type { DruckLogo } from '../receipt/layout-escpos.js';
3
4
  /**
4
5
  * Netzwerk-Bondrucker ueber Epson "Server Direct Print": das Backend fuehrt
5
6
  * je Konto Drucker mit einer geheimen Abhol-URL; die Kasse legt Druckjobs
@@ -46,6 +47,10 @@ export interface CreatePrintJobOptions {
46
47
  receiptId?: string;
47
48
  titel?: string;
48
49
  quelle?: string;
50
+ /** Firmenlogo als fertiges Rasterbild (`logoRaster`); der Server dekodiert keine Bilder. */
51
+ logo?: DruckLogo | null;
52
+ /** "erstellt mit Kasseneck" am Ende (Konto-Flag `kreiseck_logo`). */
53
+ marke?: boolean;
49
54
  }
50
55
  export declare function createPrintJob(rufen: InternerTransport, o: CreatePrintJobOptions): Promise<DruckJob>;
51
56
  export declare function getPrintJob(rufen: InternerTransport, o: {
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.listMyPrinters = listMyPrinters;
4
4
  exports.createPrintJob = createPrintJob;
5
5
  exports.getPrintJob = getPrintJob;
6
+ const index_js_1 = require("../printing/index.js");
6
7
  const text = (v) => (typeof v === 'string' && v ? v : null);
7
8
  const zahl = (v) => (typeof v === 'number' && Number.isFinite(v) ? v : null);
8
9
  async function listMyPrinters(rufen) {
@@ -27,6 +28,14 @@ async function createPrintJob(rufen, o) {
27
28
  params.titel = o.titel;
28
29
  if (o.quelle)
29
30
  params.quelle = o.quelle;
31
+ if (o.logo) {
32
+ params.logo = {
33
+ stufe: o.logo.stufe, pxBreite: o.logo.pxBreite, pxHoehe: o.logo.pxHoehe,
34
+ breite: o.logo.raster.breite, hoehe: o.logo.raster.hoehe, zeilen: (0, index_js_1.rasterZeilenBase64)(o.logo.raster),
35
+ };
36
+ }
37
+ if (o.marke === true)
38
+ params.marke = true;
30
39
  const daten = await rufen('createPrintJob', params);
31
40
  return { jobId: String(daten?.jobId ?? ''), status: text(daten?.status) ?? 'offen', ergebnis: null };
32
41
  }
@@ -116,8 +116,11 @@ exports.KASSE_TASTEN_STANDARD = Object.freeze({
116
116
  korbLeeren: ['Mod+C'],
117
117
  });
118
118
  exports.KASSE_BETRIEB_STANDARD = Object.freeze({
119
- // Petrol aus der Markenpalette ("Ecke, Aktion") — nicht das alte Blau.
120
- logoText: 'K', logoAn: true, logoGroesse: 'M', wasserzeichen: 'anmeldung', farbe: '#116B6B',
119
+ // Das Petrol der Marke: die Aktionsfarbe des Design-Systems (Rolle `brand`).
120
+ // Stand bis September 2026 auf dem Wert des alten Markenhandbuchs,
121
+ // der um 0,07 in OKLab danebenlag. Unsichtbar, aber es war die letzte Stelle
122
+ // im Haus, an der eine zweite Zahl fuer dieselbe Farbe stand.
123
+ logoText: 'K', logoAn: true, logoGroesse: 'M', wasserzeichen: 'anmeldung', farbe: '#136B6B',
121
124
  stil: 'klar', schrift: 'M', schriftEinst: 'S', kachelstil: 'streifen', uhr: true,
122
125
  sperrbild: true, foto: true, autoAbMin: 0, abNachVerkauf: false, schnellLogin: true,
123
126
  preisAnzeigen: true, ustAnzeigen: false, emoji: true, katFarben: true, freiErlaubt: true,
@@ -2,7 +2,7 @@
2
2
  * Kasse — die Antwortform von `listMyCashregisters` (functions/index.js).
3
3
  *
4
4
  * Das Dart-Vorbild (`Cashregister` in kasseneck_api/lib/models/cashregister.dart)
5
- * liest das **Firestore-Dokument** direkt ueber das `cloud_firestore`-SDK und
5
+ * liest das **Datenbankdokument** direkt ueber das SDK der Echtzeit-Datenbank und
6
6
  * kommt deshalb an `token` und `aes_key`. Dieses Paket spricht das Backend
7
7
  * ausschliesslich ueber die HTTPS-Endpunkte, und die geben beides nicht her:
8
8
  *
@@ -20,7 +20,7 @@
20
20
  * fehlendes.
21
21
  *
22
22
  * Aus demselben Grund fehlt `userId`: das Dart-Vorbild traegt es, weil es den
23
- * Firestore-**Pfad** kennt (`users/{uid}/cashregisters/{id}`). In dieser
23
+ * **Pfad** in der Datenbank kennt (`users/{uid}/cashregisters/{id}`). In dieser
24
24
  * Antwort steht es nicht, und ein Kassen-Benutzer erfaehrt die Kennung seines
25
25
  * Betriebs bewusst nie — sie steckt allein im Token.
26
26
  */
@@ -36,7 +36,7 @@ export interface ReceiptCompany {
36
36
  logoUrl?: string;
37
37
  /** Dankestext am Belegende, je Zeile ein Eintrag. */
38
38
  thanksMessage: string[];
39
- /** Kreiseck-Branding am Belegende (Firestore-Flag `branding.kreiseck_logo`). */
39
+ /** Kreiseck-Branding am Belegende (Konto-Flag `branding.kreiseck_logo`). */
40
40
  showKreiseckLogo: boolean;
41
41
  }
42
42
  /**
@@ -24,8 +24,9 @@
24
24
  * CP437-Plaetze umkodiert (ä = 0x84, ü = 0x81, ß = 0xE1, ...). Zeichen ohne
25
25
  * CP437-Platz werden zu `?` — weiterhin ein Byte je Zeichen.
26
26
  *
27
- * Nicht enthalten (bewusst): Rasterbilder/Logos, Capability-Profile einzelner
28
- * Druckermodelle, Kassenlade, 1D-Barcodes.
27
+ * Nicht enthalten (bewusst): Bilddekodierung (PNG/JPEG liest die Huelle),
28
+ * Capability-Profile einzelner Druckermodelle, Kassenlade, 1D-Barcodes.
29
+ * Fertige einfarbige Rasterbilder (Logo) gehen ueber [escPosRasterBild].
29
30
  */
30
31
  import { type QrModulGroesse } from './qr-groesse.js';
31
32
  /** Papierbreite der Bonrolle. */
@@ -103,6 +104,7 @@ export interface EscPosQrOptions {
103
104
  * die Regel in `qr-groesse.ts`.
104
105
  */
105
106
  size?: QrSize;
107
+ /** Fehlerkorrektur; Vorgabe `M` wie auf allen Druckwegen (siehe `qrCodeBytes`). */
106
108
  correction?: QrCorrection;
107
109
  /** Deckel fuer die gerechnete Modulgroesse; wirkungslos neben `size`. */
108
110
  groesse?: QrModulGroesse;
@@ -255,6 +257,12 @@ export declare function escPosRow(doc: EscPosDocument, columns: readonly PosColu
255
257
  * es wird kein Bild uebertragen.
256
258
  *
257
259
  * Bei Kasseneck-Belegen steht hier der maschinenlesbare RKSV-Code.
260
+ *
261
+ * Fehlerkorrektur ohne Angabe: **M** (bis 0.13: L). Die Groessenrechnung
262
+ * (`qrModulAnzahl`), das Blatt (Anteil am Bildschirm und im PDF), der
263
+ * ePOS-Weg (`level_m`) und der Bildweg rechnen alle mit M — druckte der
264
+ * native Befehl mit L, kaeme fuer manche Nutzlasten ein kleineres Symbol
265
+ * heraus als der Bildschirm zeigt.
258
266
  */
259
267
  export declare function qrCodeBytes(text: string, options?: {
260
268
  size?: QrSize;
@@ -266,8 +274,8 @@ export declare function qrCodeBytes(text: string, options?: {
266
274
  * **gerechneter** Modulgroesse, sofern `options.size` sie nicht festlegt.
267
275
  *
268
276
  * Ohne `size` entscheidet die Regel aus `qr-groesse.ts`: so gross wie
269
- * moeglich, gedeckelt durch `options.groesse` (Vorgabe `auto` = der
270
- * Bestandswert 4 dieses Pakets). Passt das Symbol auch mit der
277
+ * moeglich, gedeckelt durch `options.groesse` (Vorgabe `auto` = hoechstens 6
278
+ * Punkte je Modul, wie im Flutter-Zwilling). Passt das Symbol auch mit der
271
279
  * Ausnahmegroesse nicht aufs Papier, geht **kein** QR-Befehl hinaus und
272
280
  * `doc.qrFehler` sagt warum: der Drucker schneidet ein zu breites Symbol
273
281
  * nicht ab, er laesst es weg — ein Befehl, von dem man weiss, dass er nichts
@@ -300,4 +308,30 @@ export declare function qrRasterPunkte(paperSize: PosPaperSize, moduleAnzahl: nu
300
308
  groesse?: QrModulGroesse;
301
309
  ruhezoneModule?: number;
302
310
  }): number;
311
+ /**
312
+ * Einfarbiges Rasterbild in Druckpunkten, zeilenweise: `punkte[y * breite + x]`,
313
+ * 1 = schwarz. Entsteht fuer das Firmenlogo in `logoRaster` (receipt/bild.ts).
314
+ */
315
+ export interface RasterBild {
316
+ readonly breite: number;
317
+ readonly hoehe: number;
318
+ readonly punkte: Uint8Array;
319
+ }
320
+ /** Die Rasterzeilen als Bytes: MSB zuerst, jede Zeile auf volle Bytes aufgefuellt. */
321
+ export declare function rasterZeilenBytes(bild: RasterBild): Uint8Array;
322
+ /**
323
+ * Die Rasterzeilen als Base64 -- ohne Buffer, laeuft im Browser und in Node.
324
+ * Eine Stelle fuer ePOS-`<image>` und den Druckjob an den Server.
325
+ */
326
+ export declare function rasterZeilenBase64(bild: RasterBild): string;
327
+ /**
328
+ * Ein Rasterbild (`GS v 0`) -- das Firmenlogo am Bon.
329
+ *
330
+ * Anders als `escPosQrRaster` folgt KEIN Zeilenvorschub: `GS v 0` schiebt das
331
+ * Papier um die Bildhoehe, ein LF danach waere eine zusaetzliche Leerzeile,
332
+ * die Bildschirm und PDF nicht haben. Die Luft um das Logo kommt aus dem Blatt.
333
+ */
334
+ export declare function escPosRasterBild(doc: EscPosDocument, bild: RasterBild, options?: {
335
+ align?: PosAlign;
336
+ }): void;
303
337
  export {};