@kreiseck/kasseneck-api 0.31.0 → 1.0.0-rc.1

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 (712) hide show
  1. package/CHANGELOG.md +302 -0
  2. package/README.de.md +11 -7
  3. package/README.md +486 -126
  4. package/dist/cjs/client/api.d.ts +7 -6
  5. package/dist/cjs/client/api.js +2 -2
  6. package/dist/cjs/client/aufrufe.d.ts +29 -5
  7. package/dist/cjs/client/aufrufe.js +114 -2
  8. package/dist/cjs/client/auth.d.ts +2 -0
  9. package/dist/cjs/client/auth.js +17 -1
  10. package/dist/cjs/client/cashregisters.d.ts +1 -1
  11. package/dist/cjs/client/cashregisters.js +2 -2
  12. package/dist/cjs/client/errors.d.ts +78 -19
  13. package/dist/cjs/client/errors.js +107 -28
  14. package/dist/cjs/client/fehlercodes.d.ts +9 -0
  15. package/dist/cjs/client/fehlercodes.js +36 -0
  16. package/dist/cjs/client/index.d.ts +5 -5
  17. package/dist/cjs/client/index.js +11 -3
  18. package/dist/cjs/client/receipts.d.ts +131 -124
  19. package/dist/cjs/client/receipts.js +214 -137
  20. package/dist/cjs/client/reports.d.ts +26 -4
  21. package/dist/cjs/client/reports.js +37 -4
  22. package/dist/cjs/client/status.d.ts +3 -3
  23. package/dist/cjs/client/status.js +7 -7
  24. package/dist/cjs/client/transport.d.ts +56 -4
  25. package/dist/cjs/client/transport.js +222 -25
  26. package/dist/cjs/enums/vat-rate.d.ts +2 -2
  27. package/dist/cjs/enums/vat-rate.js +1 -1
  28. package/dist/cjs/index.d.ts +4 -3
  29. package/dist/cjs/index.js +42 -13
  30. package/dist/{esm/rechnung → cjs/invoice}/api.d.ts +18 -17
  31. package/dist/cjs/{rechnung → invoice}/api.js +6 -6
  32. package/dist/{esm/rechnung → cjs/invoice}/auth.d.ts +2 -2
  33. package/dist/cjs/{rechnung → invoice}/auth.js +5 -5
  34. package/dist/{esm/rechnung/rechnen.d.ts → cjs/invoice/calc.d.ts} +27 -27
  35. package/dist/cjs/{rechnung/rechnen.js → invoice/calc.js} +54 -54
  36. package/dist/{esm/rechnung → cjs/invoice}/endpunkte.d.ts +23 -21
  37. package/dist/cjs/{rechnung → invoice}/endpunkte.js +52 -42
  38. package/dist/cjs/invoice/fehler.d.ts +31 -0
  39. package/dist/cjs/invoice/fehler.js +39 -0
  40. package/dist/cjs/invoice/index.d.ts +21 -0
  41. package/dist/cjs/invoice/index.js +86 -0
  42. package/dist/cjs/{rechnung → invoice}/summen.d.ts +12 -12
  43. package/dist/cjs/{rechnung → invoice}/summen.js +14 -14
  44. package/dist/cjs/invoice/texte.d.ts +224 -0
  45. package/dist/cjs/invoice/texte.js +425 -0
  46. package/dist/{esm/rechnung → cjs/invoice}/typen.d.ts +32 -11
  47. package/dist/cjs/{rechnung → invoice}/vertrag.d.ts +97 -71
  48. package/dist/cjs/{rechnung → invoice}/vertrag.js +144 -82
  49. package/dist/cjs/models/cancellation.d.ts +43 -24
  50. package/dist/cjs/models/cancellation.js +94 -46
  51. package/dist/cjs/models/hobex-receipt.d.ts +3 -3
  52. package/dist/cjs/models/hobex-receipt.js +35 -35
  53. package/dist/cjs/models/index.d.ts +6 -5
  54. package/dist/cjs/models/index.js +22 -2
  55. package/dist/cjs/models/payment-errors.d.ts +32 -15
  56. package/dist/cjs/models/payment-errors.js +80 -32
  57. package/dist/cjs/models/receipt-company.d.ts +6 -5
  58. package/dist/cjs/models/receipt-company.js +4 -4
  59. package/dist/cjs/models/receipt-email.d.ts +32 -18
  60. package/dist/cjs/models/receipt-email.js +69 -24
  61. package/dist/cjs/models/receipt-errors.d.ts +39 -0
  62. package/dist/cjs/models/receipt-errors.js +94 -0
  63. package/dist/cjs/models/receipt-item.d.ts +9 -1
  64. package/dist/cjs/models/receipt-item.js +3 -0
  65. package/dist/cjs/models/receipt-summary.d.ts +10 -4
  66. package/dist/cjs/models/receipt-summary.js +10 -4
  67. package/dist/cjs/models/receipt.d.ts +31 -2
  68. package/dist/cjs/models/receipt.js +12 -1
  69. package/dist/cjs/models/voucher.d.ts +7 -6
  70. package/dist/cjs/models/voucher.js +2 -7
  71. package/dist/cjs/partner/ablauf.d.ts +10 -10
  72. package/dist/cjs/partner/ablauf.js +29 -29
  73. package/dist/cjs/partner/api.d.ts +26 -23
  74. package/dist/cjs/partner/api.js +11 -13
  75. package/dist/cjs/partner/auth.d.ts +1 -1
  76. package/dist/cjs/partner/auth.js +2 -2
  77. package/dist/cjs/partner/betrieb.d.ts +7 -7
  78. package/dist/cjs/partner/betrieb.js +10 -10
  79. package/dist/cjs/partner/endpunkte.d.ts +27 -14
  80. package/dist/cjs/partner/endpunkte.js +80 -39
  81. package/dist/cjs/partner/fehler.d.ts +60 -30
  82. package/dist/cjs/partner/fehler.js +99 -43
  83. package/dist/cjs/partner/index.d.ts +13 -12
  84. package/dist/cjs/partner/index.js +35 -22
  85. package/dist/cjs/partner/secret.d.ts +3 -3
  86. package/dist/cjs/partner/secret.js +6 -6
  87. package/dist/cjs/partner/typen.d.ts +129 -71
  88. package/dist/cjs/partner/typen.js +76 -3
  89. package/dist/cjs/partner/webhook-signatur.d.ts +2 -2
  90. package/dist/cjs/partner/webhook-signatur.js +12 -12
  91. package/dist/cjs/partner/webhooks.d.ts +60 -32
  92. package/dist/cjs/partner/webhooks.js +40 -34
  93. package/dist/cjs/payments/hobex.d.ts +2 -2
  94. package/dist/cjs/payments/hobex.js +4 -4
  95. package/dist/cjs/payments/stripe.d.ts +2 -2
  96. package/dist/cjs/payments/stripe.js +4 -4
  97. package/dist/cjs/pos/artikel.d.ts +90 -0
  98. package/dist/cjs/pos/artikel.js +89 -0
  99. package/dist/cjs/pos/client.d.ts +27 -0
  100. package/dist/cjs/pos/client.js +144 -0
  101. package/dist/cjs/pos/drucker.d.ts +86 -0
  102. package/dist/cjs/pos/drucker.js +78 -0
  103. package/dist/cjs/pos/errors.d.ts +36 -0
  104. package/dist/cjs/pos/errors.js +95 -0
  105. package/dist/cjs/pos/index.d.ts +15 -0
  106. package/dist/cjs/pos/index.js +102 -0
  107. package/dist/cjs/pos/settings.d.ts +313 -0
  108. package/dist/cjs/pos/settings.js +376 -0
  109. package/dist/cjs/pos/texte.d.ts +883 -0
  110. package/dist/cjs/pos/texte.js +489 -0
  111. package/dist/cjs/{kasse → pos}/trinkgeld.d.ts +1 -1
  112. package/dist/cjs/{kasse → pos}/trinkgeld.js +2 -2
  113. package/dist/cjs/printing/escpos.d.ts +29 -29
  114. package/dist/cjs/printing/escpos.js +61 -61
  115. package/dist/cjs/printing/index.d.ts +2 -2
  116. package/dist/cjs/printing/index.js +17 -17
  117. package/dist/cjs/printing/qr-groesse.d.ts +38 -38
  118. package/dist/cjs/printing/qr-groesse.js +47 -47
  119. package/dist/cjs/printing/webusb.d.ts +2 -2
  120. package/dist/cjs/printing/webusb.js +4 -4
  121. package/dist/cjs/react/index.d.ts +21 -21
  122. package/dist/cjs/react/index.js +40 -30
  123. package/dist/cjs/receipt/bild.d.ts +4 -4
  124. package/dist/cjs/receipt/bild.js +11 -11
  125. package/dist/cjs/receipt/blatt.d.ts +46 -46
  126. package/dist/cjs/receipt/blatt.js +59 -59
  127. package/dist/cjs/receipt/discount.d.ts +1 -1
  128. package/dist/cjs/receipt/discount.js +8 -8
  129. package/dist/cjs/receipt/due.d.ts +86 -0
  130. package/dist/cjs/receipt/due.js +261 -0
  131. package/dist/cjs/receipt/epos.d.ts +22 -22
  132. package/dist/cjs/receipt/epos.js +45 -45
  133. package/dist/cjs/receipt/grid.d.ts +10 -10
  134. package/dist/cjs/receipt/grid.js +20 -20
  135. package/dist/cjs/receipt/index.d.ts +9 -8
  136. package/dist/cjs/receipt/index.js +26 -23
  137. package/dist/cjs/receipt/layout-escpos.d.ts +24 -24
  138. package/dist/cjs/receipt/layout-escpos.js +49 -49
  139. package/dist/cjs/receipt/layout.d.ts +28 -23
  140. package/dist/cjs/receipt/layout.js +45 -21
  141. package/dist/cjs/receipt/marke-daten.d.ts +8 -8
  142. package/dist/cjs/receipt/marke-daten.js +8 -8
  143. package/dist/cjs/receipt/marke.d.ts +7 -7
  144. package/dist/cjs/receipt/marke.js +10 -10
  145. package/dist/cjs/register/errors.d.ts +61 -0
  146. package/dist/cjs/register/errors.js +112 -0
  147. package/dist/cjs/register/index.d.ts +14 -1
  148. package/dist/cjs/register/index.js +20 -1
  149. package/dist/cjs/register/pairing.d.ts +55 -36
  150. package/dist/cjs/register/pairing.js +33 -29
  151. package/dist/cjs/register/session.d.ts +5 -5
  152. package/dist/cjs/register/session.js +7 -7
  153. package/dist/cjs/stored/draht.d.ts +45 -0
  154. package/dist/cjs/stored/draht.js +220 -0
  155. package/dist/cjs/stored/einstellungen.d.ts +23 -0
  156. package/dist/cjs/stored/einstellungen.js +200 -0
  157. package/dist/cjs/stored/index.d.ts +109 -0
  158. package/dist/cjs/stored/index.js +225 -0
  159. package/dist/cjs/stored/vokabular.d.ts +18 -0
  160. package/dist/cjs/stored/vokabular.js +389 -0
  161. package/dist/cjs/version.d.ts +7 -0
  162. package/dist/cjs/version.js +10 -0
  163. package/dist/cjs/vienna-time.d.ts +1 -1
  164. package/dist/cjs/vienna-time.js +2 -2
  165. package/dist/esm/client/api.d.ts +7 -6
  166. package/dist/esm/client/api.js +4 -4
  167. package/dist/esm/client/aufrufe.d.ts +29 -5
  168. package/dist/esm/client/aufrufe.js +111 -1
  169. package/dist/esm/client/auth.d.ts +2 -0
  170. package/dist/esm/client/auth.js +16 -1
  171. package/dist/esm/client/cashregisters.d.ts +1 -1
  172. package/dist/esm/client/cashregisters.js +2 -2
  173. package/dist/esm/client/errors.d.ts +78 -19
  174. package/dist/esm/client/errors.js +105 -27
  175. package/dist/esm/client/fehlercodes.d.ts +9 -0
  176. package/dist/esm/client/fehlercodes.js +32 -0
  177. package/dist/esm/client/index.d.ts +5 -5
  178. package/dist/esm/client/index.js +5 -5
  179. package/dist/esm/client/receipts.d.ts +131 -124
  180. package/dist/esm/client/receipts.js +213 -140
  181. package/dist/esm/client/reports.d.ts +26 -4
  182. package/dist/esm/client/reports.js +36 -4
  183. package/dist/esm/client/status.d.ts +3 -3
  184. package/dist/esm/client/status.js +7 -7
  185. package/dist/esm/client/transport.d.ts +56 -4
  186. package/dist/esm/client/transport.js +221 -24
  187. package/dist/esm/enums/vat-rate.d.ts +2 -2
  188. package/dist/esm/enums/vat-rate.js +1 -1
  189. package/dist/esm/index.d.ts +4 -3
  190. package/dist/esm/index.js +4 -3
  191. package/dist/{cjs/rechnung → esm/invoice}/api.d.ts +18 -17
  192. package/dist/esm/{rechnung → invoice}/api.js +6 -6
  193. package/dist/{cjs/rechnung → esm/invoice}/auth.d.ts +2 -2
  194. package/dist/esm/{rechnung → invoice}/auth.js +4 -4
  195. package/dist/{cjs/rechnung/rechnen.d.ts → esm/invoice/calc.d.ts} +27 -27
  196. package/dist/esm/{rechnung/rechnen.js → invoice/calc.js} +45 -45
  197. package/dist/{cjs/rechnung → esm/invoice}/endpunkte.d.ts +23 -21
  198. package/dist/esm/{rechnung → invoice}/endpunkte.js +52 -42
  199. package/dist/esm/invoice/fehler.d.ts +31 -0
  200. package/dist/esm/invoice/fehler.js +33 -0
  201. package/dist/esm/invoice/index.d.ts +21 -0
  202. package/dist/esm/invoice/index.js +20 -0
  203. package/dist/esm/{rechnung → invoice}/summen.d.ts +12 -12
  204. package/dist/esm/{rechnung → invoice}/summen.js +12 -12
  205. package/dist/esm/invoice/texte.d.ts +224 -0
  206. package/dist/esm/invoice/texte.js +421 -0
  207. package/dist/{cjs/rechnung → esm/invoice}/typen.d.ts +32 -11
  208. package/dist/esm/{rechnung → invoice}/vertrag.d.ts +97 -71
  209. package/dist/esm/{rechnung → invoice}/vertrag.js +143 -81
  210. package/dist/esm/models/cancellation.d.ts +43 -24
  211. package/dist/esm/models/cancellation.js +90 -45
  212. package/dist/esm/models/hobex-receipt.d.ts +3 -3
  213. package/dist/esm/models/hobex-receipt.js +35 -35
  214. package/dist/esm/models/index.d.ts +6 -5
  215. package/dist/esm/models/index.js +6 -5
  216. package/dist/esm/models/payment-errors.d.ts +32 -15
  217. package/dist/esm/models/payment-errors.js +77 -32
  218. package/dist/esm/models/receipt-company.d.ts +6 -5
  219. package/dist/esm/models/receipt-company.js +4 -4
  220. package/dist/esm/models/receipt-email.d.ts +32 -18
  221. package/dist/esm/models/receipt-email.js +65 -23
  222. package/dist/esm/models/receipt-errors.d.ts +39 -0
  223. package/dist/esm/models/receipt-errors.js +87 -0
  224. package/dist/esm/models/receipt-item.d.ts +9 -1
  225. package/dist/esm/models/receipt-item.js +3 -0
  226. package/dist/esm/models/receipt-summary.d.ts +10 -4
  227. package/dist/esm/models/receipt-summary.js +9 -3
  228. package/dist/esm/models/receipt.d.ts +31 -2
  229. package/dist/esm/models/receipt.js +12 -2
  230. package/dist/esm/models/voucher.d.ts +7 -6
  231. package/dist/esm/models/voucher.js +2 -7
  232. package/dist/esm/partner/ablauf.d.ts +10 -10
  233. package/dist/esm/partner/ablauf.js +27 -27
  234. package/dist/esm/partner/api.d.ts +26 -23
  235. package/dist/esm/partner/api.js +13 -15
  236. package/dist/esm/partner/auth.d.ts +1 -1
  237. package/dist/esm/partner/auth.js +2 -2
  238. package/dist/esm/partner/betrieb.d.ts +7 -7
  239. package/dist/esm/partner/betrieb.js +8 -8
  240. package/dist/esm/partner/endpunkte.d.ts +27 -14
  241. package/dist/esm/partner/endpunkte.js +79 -39
  242. package/dist/esm/partner/fehler.d.ts +60 -30
  243. package/dist/esm/partner/fehler.js +91 -35
  244. package/dist/esm/partner/index.d.ts +13 -12
  245. package/dist/esm/partner/index.js +12 -11
  246. package/dist/esm/partner/secret.d.ts +3 -3
  247. package/dist/esm/partner/secret.js +5 -5
  248. package/dist/esm/partner/typen.d.ts +129 -71
  249. package/dist/esm/partner/typen.js +75 -2
  250. package/dist/esm/partner/webhook-signatur.d.ts +2 -2
  251. package/dist/esm/partner/webhook-signatur.js +12 -12
  252. package/dist/esm/partner/webhooks.d.ts +60 -32
  253. package/dist/esm/partner/webhooks.js +38 -32
  254. package/dist/esm/payments/hobex.d.ts +2 -2
  255. package/dist/esm/payments/hobex.js +4 -4
  256. package/dist/esm/payments/stripe.d.ts +2 -2
  257. package/dist/esm/payments/stripe.js +4 -4
  258. package/dist/esm/pos/artikel.d.ts +90 -0
  259. package/dist/esm/pos/artikel.js +79 -0
  260. package/dist/esm/pos/client.d.ts +27 -0
  261. package/dist/esm/pos/client.js +137 -0
  262. package/dist/esm/pos/drucker.d.ts +86 -0
  263. package/dist/esm/pos/drucker.js +71 -0
  264. package/dist/esm/pos/errors.d.ts +36 -0
  265. package/dist/esm/pos/errors.js +88 -0
  266. package/dist/esm/pos/index.d.ts +15 -0
  267. package/dist/esm/pos/index.js +20 -0
  268. package/dist/esm/pos/settings.d.ts +313 -0
  269. package/dist/esm/pos/settings.js +367 -0
  270. package/dist/esm/pos/texte.d.ts +883 -0
  271. package/dist/esm/pos/texte.js +481 -0
  272. package/dist/esm/{kasse → pos}/trinkgeld.d.ts +1 -1
  273. package/dist/esm/{kasse → pos}/trinkgeld.js +2 -2
  274. package/dist/esm/printing/escpos.d.ts +29 -29
  275. package/dist/esm/printing/escpos.js +56 -56
  276. package/dist/esm/printing/index.d.ts +2 -2
  277. package/dist/esm/printing/index.js +2 -2
  278. package/dist/esm/printing/qr-groesse.d.ts +38 -38
  279. package/dist/esm/printing/qr-groesse.js +42 -42
  280. package/dist/esm/printing/webusb.d.ts +2 -2
  281. package/dist/esm/printing/webusb.js +4 -4
  282. package/dist/esm/react/index.d.ts +21 -21
  283. package/dist/esm/react/index.js +39 -29
  284. package/dist/esm/receipt/bild.d.ts +4 -4
  285. package/dist/esm/receipt/bild.js +11 -11
  286. package/dist/esm/receipt/blatt.d.ts +46 -46
  287. package/dist/esm/receipt/blatt.js +55 -55
  288. package/dist/esm/receipt/discount.d.ts +1 -1
  289. package/dist/esm/receipt/discount.js +7 -7
  290. package/dist/esm/receipt/due.d.ts +86 -0
  291. package/dist/esm/receipt/due.js +257 -0
  292. package/dist/esm/receipt/epos.d.ts +22 -22
  293. package/dist/esm/receipt/epos.js +47 -47
  294. package/dist/esm/receipt/grid.d.ts +10 -10
  295. package/dist/esm/receipt/grid.js +18 -18
  296. package/dist/esm/receipt/index.d.ts +9 -8
  297. package/dist/esm/receipt/index.js +9 -8
  298. package/dist/esm/receipt/layout-escpos.d.ts +24 -24
  299. package/dist/esm/receipt/layout-escpos.js +51 -51
  300. package/dist/esm/receipt/layout.d.ts +28 -23
  301. package/dist/esm/receipt/layout.js +44 -20
  302. package/dist/esm/receipt/marke-daten.d.ts +8 -8
  303. package/dist/esm/receipt/marke-daten.js +7 -7
  304. package/dist/esm/receipt/marke.d.ts +7 -7
  305. package/dist/esm/receipt/marke.js +10 -10
  306. package/dist/esm/register/errors.d.ts +61 -0
  307. package/dist/esm/register/errors.js +104 -0
  308. package/dist/esm/register/index.d.ts +14 -1
  309. package/dist/esm/register/index.js +13 -0
  310. package/dist/esm/register/pairing.d.ts +55 -36
  311. package/dist/esm/register/pairing.js +33 -29
  312. package/dist/esm/register/session.d.ts +5 -5
  313. package/dist/esm/register/session.js +7 -7
  314. package/dist/esm/stored/draht.d.ts +45 -0
  315. package/dist/esm/stored/draht.js +208 -0
  316. package/dist/esm/stored/einstellungen.d.ts +23 -0
  317. package/dist/esm/stored/einstellungen.js +196 -0
  318. package/dist/esm/stored/index.d.ts +109 -0
  319. package/dist/esm/stored/index.js +217 -0
  320. package/dist/esm/stored/vokabular.d.ts +18 -0
  321. package/dist/esm/stored/vokabular.js +386 -0
  322. package/dist/esm/version.d.ts +7 -0
  323. package/dist/esm/version.js +7 -0
  324. package/dist/esm/vienna-time.d.ts +1 -1
  325. package/dist/esm/vienna-time.js +2 -2
  326. package/fixtures/{erwartet/storno-rabatt.lines.json → expected/cancellation-discount.lines.json} +2 -2
  327. package/fixtures/expected/cancellation-discount.sheet32.json +248 -0
  328. package/fixtures/{erwartet/storno-rabatt.blatt48.json → expected/cancellation-discount.sheet48.json} +119 -119
  329. package/fixtures/{erwartet/storno-voll.lines.json → expected/cancellation-full.lines.json} +2 -2
  330. package/fixtures/expected/cancellation-full.sheet32.json +218 -0
  331. package/fixtures/{erwartet/storno-voll.blatt48.json → expected/cancellation-full.sheet48.json} +107 -107
  332. package/fixtures/{erwartet/storno-teil.lines.json → expected/cancellation-partial.lines.json} +2 -2
  333. package/fixtures/expected/cancellation-partial.sheet32.json +206 -0
  334. package/fixtures/{erwartet/storno-teil.blatt48.json → expected/cancellation-partial.sheet48.json} +101 -101
  335. package/fixtures/{erwartet/storno-split-voll.lines.json → expected/cancellation-split-full.lines.json} +2 -2
  336. package/fixtures/expected/cancellation-split-full.sheet32.json +320 -0
  337. package/fixtures/{erwartet/storno-split-voll.blatt48.json → expected/cancellation-split-full.sheet48.json} +158 -158
  338. package/fixtures/{erwartet/storno-split-teil.lines.json → expected/cancellation-split-partial.lines.json} +2 -2
  339. package/fixtures/expected/cancellation-split-partial.sheet32.json +230 -0
  340. package/fixtures/{erwartet/storno-split-teil.blatt48.json → expected/cancellation-split-partial.sheet48.json} +113 -113
  341. package/fixtures/{erwartet/karte-eigener.lines.json → expected/card-custom.lines.json} +1 -1
  342. package/fixtures/expected/card-custom.sheet32.json +158 -0
  343. package/fixtures/{erwartet/karte-eigener.blatt48.json → expected/card-custom.sheet48.json} +80 -80
  344. package/fixtures/{erwartet/karte-gptom-ios.lines.json → expected/card-gptom-ios.lines.json} +1 -1
  345. package/fixtures/expected/card-gptom-ios.sheet32.json +230 -0
  346. package/fixtures/{erwartet/karte-gptom-ios.blatt48.json → expected/card-gptom-ios.sheet48.json} +116 -116
  347. package/fixtures/{erwartet/karte-gptom.lines.json → expected/card-gptom.lines.json} +1 -1
  348. package/fixtures/expected/card-gptom.sheet32.json +230 -0
  349. package/fixtures/{erwartet/karte-gptom.blatt48.json → expected/card-gptom.sheet48.json} +116 -116
  350. package/fixtures/{erwartet/karte-hobex-cloud.lines.json → expected/card-hobex-cloud.lines.json} +1 -1
  351. package/fixtures/expected/card-hobex-cloud.sheet32.json +200 -0
  352. package/fixtures/{erwartet/karte-hobex-cloud.blatt48.json → expected/card-hobex-cloud.sheet48.json} +101 -101
  353. package/fixtures/{erwartet/karte-hobex-hps.lines.json → expected/card-hobex-hps.lines.json} +1 -1
  354. package/fixtures/expected/card-hobex-hps.sheet32.json +224 -0
  355. package/fixtures/{erwartet/karte-hobex-hps.blatt48.json → expected/card-hobex-hps.sheet48.json} +113 -113
  356. package/fixtures/{erwartet/karte-mypos.lines.json → expected/card-mypos.lines.json} +1 -1
  357. package/fixtures/expected/card-mypos.sheet32.json +254 -0
  358. package/fixtures/{erwartet/karte-mypos.blatt48.json → expected/card-mypos.sheet48.json} +122 -122
  359. package/fixtures/{erwartet/karte-stripe-eps.lines.json → expected/card-stripe-eps.lines.json} +1 -1
  360. package/fixtures/expected/card-stripe-eps.sheet32.json +194 -0
  361. package/fixtures/{erwartet/karte-stripe-eps.blatt48.json → expected/card-stripe-eps.sheet48.json} +98 -98
  362. package/fixtures/{erwartet/karte-stripe.lines.json → expected/card-stripe.lines.json} +1 -1
  363. package/fixtures/expected/card-stripe.sheet32.json +212 -0
  364. package/fixtures/{erwartet/karte-stripe.blatt48.json → expected/card-stripe.sheet48.json} +107 -107
  365. package/fixtures/{erwartet/karte-sumup.lines.json → expected/card-sumup.lines.json} +1 -1
  366. package/fixtures/expected/card-sumup.sheet32.json +218 -0
  367. package/fixtures/{erwartet/karte-sumup.blatt48.json → expected/card-sumup.sheet48.json} +104 -104
  368. package/fixtures/{erwartet/rabattzeilen.lines.json → expected/discount-lines.lines.json} +1 -1
  369. package/fixtures/expected/discount-lines.sheet32.json +200 -0
  370. package/fixtures/{erwartet/rabattzeilen.blatt48.json → expected/discount-lines.sheet48.json} +98 -98
  371. package/fixtures/{erwartet/rabatt-chef-trinkgeld.lines.json → expected/discount-owner-tip.lines.json} +1 -1
  372. package/fixtures/expected/discount-owner-tip.sheet32.json +212 -0
  373. package/fixtures/{erwartet/rabatt-chef-trinkgeld.blatt48.json → expected/discount-owner-tip.sheet48.json} +104 -104
  374. package/fixtures/{erwartet/rabatt-einfach.lines.json → expected/discount-simple.lines.json} +1 -1
  375. package/fixtures/expected/discount-simple.sheet32.json +182 -0
  376. package/fixtures/{erwartet/rabatt-einfach.blatt48.json → expected/discount-simple.sheet48.json} +89 -89
  377. package/fixtures/{erwartet/rabatt-trinkgeld.lines.json → expected/discount-tip.lines.json} +1 -1
  378. package/fixtures/expected/discount-tip.sheet32.json +212 -0
  379. package/fixtures/{erwartet/rabatt-trinkgeld.blatt48.json → expected/discount-tip.sheet48.json} +104 -104
  380. package/fixtures/{erwartet/rabatt-wertgutschein.lines.json → expected/discount-value-voucher.lines.json} +1 -1
  381. package/fixtures/expected/discount-value-voucher.sheet32.json +218 -0
  382. package/fixtures/{erwartet/rabatt-wertgutschein.blatt48.json → expected/discount-value-voucher.sheet48.json} +107 -107
  383. package/fixtures/{erwartet/langer-artikelname.lines.json → expected/long-item-name.lines.json} +1 -1
  384. package/fixtures/expected/long-item-name.sheet32.json +176 -0
  385. package/fixtures/{erwartet/langer-artikelname.blatt48.json → expected/long-item-name.sheet48.json} +86 -86
  386. package/fixtures/{erwartet/verkauf-karte.lines.json → expected/sale-card.lines.json} +1 -1
  387. package/fixtures/expected/sale-card.sheet32.json +176 -0
  388. package/fixtures/{erwartet/verkauf-karte.blatt48.json → expected/sale-card.sheet48.json} +86 -86
  389. package/fixtures/{erwartet/verkauf-bar.lines.json → expected/sale-cash.lines.json} +1 -1
  390. package/fixtures/expected/sale-cash.sheet32.json +176 -0
  391. package/fixtures/{erwartet/verkauf-bar.blatt48.json → expected/sale-cash.sheet48.json} +86 -86
  392. package/fixtures/{erwartet/verkauf-kleinunternehmer.lines.json → expected/sale-small-business.lines.json} +1 -1
  393. package/fixtures/expected/sale-small-business.sheet32.json +182 -0
  394. package/fixtures/{erwartet/verkauf-kleinunternehmer.blatt48.json → expected/sale-small-business.sheet48.json} +89 -89
  395. package/fixtures/{erwartet/signaturausfall-verkauf.lines.json → expected/signature-outage-sale.lines.json} +1 -1
  396. package/fixtures/expected/signature-outage-sale.sheet32.json +194 -0
  397. package/fixtures/{erwartet/signaturausfall-verkauf.blatt48.json → expected/signature-outage-sale.sheet48.json} +92 -92
  398. package/fixtures/{erwartet/split-karte-karte-bar.lines.json → expected/split-card-card-cash.lines.json} +1 -1
  399. package/fixtures/expected/split-card-card-cash.sheet32.json +356 -0
  400. package/fixtures/{erwartet/split-karte-karte-bar.blatt48.json → expected/split-card-card-cash.sheet48.json} +170 -170
  401. package/fixtures/{erwartet/split-bar-rueckgeld.lines.json → expected/split-cash-change.lines.json} +1 -1
  402. package/fixtures/expected/split-cash-change.sheet32.json +194 -0
  403. package/fixtures/{erwartet/split-bar-rueckgeld.blatt48.json → expected/split-cash-change.sheet48.json} +92 -92
  404. package/fixtures/{erwartet/split-langer-betrag.lines.json → expected/split-long-amount.lines.json} +1 -1
  405. package/fixtures/expected/split-long-amount.sheet32.json +266 -0
  406. package/fixtures/{erwartet/split-langer-betrag.blatt48.json → expected/split-long-amount.sheet48.json} +131 -131
  407. package/fixtures/{erwartet/split-eine-karte-trinkgeld.lines.json → expected/split-one-card-tip.lines.json} +1 -1
  408. package/fixtures/expected/split-one-card-tip.sheet32.json +242 -0
  409. package/fixtures/{erwartet/split-eine-karte-trinkgeld.blatt48.json → expected/split-one-card-tip.sheet48.json} +113 -113
  410. package/fixtures/{erwartet/split-tischrunde-trinkgeld.lines.json → expected/split-table-round-tip.lines.json} +1 -1
  411. package/fixtures/expected/split-table-round-tip.sheet32.json +470 -0
  412. package/fixtures/{erwartet/split-tischrunde-trinkgeld.blatt48.json → expected/split-table-round-tip.sheet48.json} +218 -218
  413. package/fixtures/{erwartet/split-trinkgeld-karte.lines.json → expected/split-tip-card.lines.json} +1 -1
  414. package/fixtures/expected/split-tip-card.sheet32.json +272 -0
  415. package/fixtures/{erwartet/split-trinkgeld-karte.blatt48.json → expected/split-tip-card.sheet48.json} +128 -128
  416. package/fixtures/{erwartet/split-zwei-karten-gleicher-anbieter.lines.json → expected/split-two-cards-same-provider.lines.json} +1 -1
  417. package/fixtures/expected/split-two-cards-same-provider.sheet32.json +326 -0
  418. package/fixtures/{erwartet/split-zwei-karten-gleicher-anbieter.blatt48.json → expected/split-two-cards-same-provider.sheet48.json} +149 -149
  419. package/fixtures/{erwartet/testkasse-verkauf.lines.json → expected/test-cashregister-sale.lines.json} +3 -3
  420. package/fixtures/expected/test-cashregister-sale.sheet32.json +224 -0
  421. package/fixtures/{erwartet/testkasse-verkauf.blatt48.json → expected/test-cashregister-sale.sheet48.json} +110 -110
  422. package/fixtures/{erwartet/testsignatur-verkauf.lines.json → expected/test-signature-sale.lines.json} +3 -3
  423. package/fixtures/expected/test-signature-sale.sheet32.json +236 -0
  424. package/fixtures/{erwartet/testsignatur-verkauf.blatt48.json → expected/test-signature-sale.sheet48.json} +110 -110
  425. package/fixtures/{erwartet → expected}/training.lines.json +2 -2
  426. package/fixtures/expected/training.sheet32.json +236 -0
  427. package/fixtures/{erwartet/training.blatt48.json → expected/training.sheet48.json} +110 -110
  428. package/fixtures/{erwartet/null-jahr.lines.json → expected/zero-annual.lines.json} +2 -2
  429. package/fixtures/expected/zero-annual.sheet32.json +212 -0
  430. package/fixtures/{erwartet/null-jahr.blatt48.json → expected/zero-annual.sheet48.json} +95 -95
  431. package/fixtures/{erwartet/null-schluss.lines.json → expected/zero-final.lines.json} +2 -2
  432. package/fixtures/expected/zero-final.sheet32.json +206 -0
  433. package/fixtures/{erwartet/null-schluss.blatt48.json → expected/zero-final.sheet48.json} +95 -95
  434. package/fixtures/{erwartet/null-pruef.lines.json → expected/zero-manual.lines.json} +2 -2
  435. package/fixtures/expected/zero-manual.sheet32.json +206 -0
  436. package/fixtures/{erwartet/null-pruef.blatt48.json → expected/zero-manual.sheet48.json} +95 -95
  437. package/fixtures/{erwartet/null-monat.lines.json → expected/zero-monthly.lines.json} +2 -2
  438. package/fixtures/expected/zero-monthly.sheet32.json +206 -0
  439. package/fixtures/{erwartet/null-monat.blatt48.json → expected/zero-monthly.sheet48.json} +95 -95
  440. package/fixtures/{erwartet/null-ausfall.lines.json → expected/zero-outage-end.lines.json} +2 -2
  441. package/fixtures/expected/zero-outage-end.sheet32.json +206 -0
  442. package/fixtures/{erwartet/null-ausfall.blatt48.json → expected/zero-outage-end.sheet48.json} +95 -95
  443. package/fixtures/{erwartet/null-start.lines.json → expected/zero-start.lines.json} +2 -2
  444. package/fixtures/expected/zero-start.sheet32.json +206 -0
  445. package/fixtures/{erwartet/null-start.blatt48.json → expected/zero-start.sheet48.json} +95 -95
  446. package/fixtures/hobex-hps-codes.json +12 -12
  447. package/fixtures/invoice-api-examples/brands-ok.json +8 -0
  448. package/fixtures/{rechnung-api-beispiele/credit-fehler-grund.json → invoice-api-examples/credit-error-reason.json} +6 -6
  449. package/fixtures/{rechnung-api-beispiele → invoice-api-examples}/credit-ok.json +6 -6
  450. package/fixtures/{rechnung-api-beispiele/customer-fehler-uid.json → invoice-api-examples/customer-error-vat-id.json} +4 -4
  451. package/fixtures/invoice-api-examples/customer-get-error-both.json +15 -0
  452. package/fixtures/{rechnung-api-beispiele → invoice-api-examples}/customer-ok.json +4 -4
  453. package/fixtures/{rechnung-api-beispiele/customer-search-fehler-leer.json → invoice-api-examples/customer-search-error-empty.json} +4 -4
  454. package/fixtures/{rechnung-api-beispiele/issue-rabatt.json → invoice-api-examples/issue-discount.json} +6 -6
  455. package/fixtures/{rechnung-api-beispiele/issue-englisch.json → invoice-api-examples/issue-english.json} +7 -7
  456. package/fixtures/{rechnung-api-beispiele/issue-fehler-cent.json → invoice-api-examples/issue-error-cent.json} +6 -6
  457. package/fixtures/{rechnung-api-beispiele/issue-fehler-sprache.json → invoice-api-examples/issue-error-language.json} +5 -5
  458. package/fixtures/{rechnung-api-beispiele/issue-fehler-negativ.json → invoice-api-examples/issue-error-negative.json} +6 -6
  459. package/fixtures/{rechnung-api-beispiele/issue-fehler-zahlungsart.json → invoice-api-examples/issue-error-payment-method.json} +8 -6
  460. package/fixtures/{rechnung-api-beispiele/issue-fehler-preis-beide.json → invoice-api-examples/issue-error-price-both.json} +6 -6
  461. package/fixtures/{rechnung-api-beispiele/issue-fehler-preis-fehlt.json → invoice-api-examples/issue-error-price-missing.json} +6 -6
  462. package/fixtures/{rechnung-api-beispiele/issue-fehler-menge.json → invoice-api-examples/issue-error-quantity.json} +6 -6
  463. package/fixtures/{rechnung-api-beispiele/issue-fehler-satz.json → invoice-api-examples/issue-error-rate.json} +6 -6
  464. package/fixtures/{rechnung-api-beispiele/issue-fehler-einheit.json → invoice-api-examples/issue-error-unit.json} +5 -5
  465. package/fixtures/{rechnung-api-beispiele/issue-fehler-unbekannt.json → invoice-api-examples/issue-error-unknown.json} +6 -6
  466. package/fixtures/{rechnung-api-beispiele/issue-brutto-20.json → invoice-api-examples/issue-gross-20.json} +6 -6
  467. package/fixtures/{rechnung-api-beispiele/issue-mikropreis.json → invoice-api-examples/issue-micro-price.json} +6 -6
  468. package/fixtures/{rechnung-api-beispiele/issue-gemischt.json → invoice-api-examples/issue-mixed.json} +6 -6
  469. package/fixtures/{rechnung-api-beispiele/issue-netto-20.json → invoice-api-examples/issue-net-20.json} +6 -6
  470. package/fixtures/{rechnung-api-beispiele/issue-bezahlt.json → invoice-api-examples/issue-paid.json} +7 -7
  471. package/fixtures/{rechnung-api-beispiele/issue-kleinunternehmer.json → invoice-api-examples/issue-small-business.json} +6 -6
  472. package/fixtures/invoice-api-examples/payment-error-on-site.json +17 -0
  473. package/fixtures/invoice-api-examples/payment-error-without-key.json +16 -0
  474. package/fixtures/invoice-api-examples/payment-recorded-later.json +14 -0
  475. package/fixtures/{rechnung-api-beispiele/setup-status-fehler-feld.json → invoice-api-examples/setup-status-error-field.json} +4 -4
  476. package/fixtures/invoice-api-examples/setup-status-ok.json +8 -0
  477. package/fixtures/{rechnung-api.schema.json → invoice-api.schema.json} +24 -24
  478. package/fixtures/{rechnung-rechnen-zufall.json → invoice-calc-random.json} +828 -828
  479. package/fixtures/{rechnung-rechnen.json → invoice-calc.json} +47 -47
  480. package/fixtures/invoice-texts.json +464 -0
  481. package/fixtures/{rechnung-summen.json → invoice-totals.json} +25 -25
  482. package/fixtures/{position-aus-euro.json → item-from-euro.json} +26 -26
  483. package/fixtures/manifest.json +252 -252
  484. package/fixtures/pos-message-cases.json +32 -0
  485. package/fixtures/pos-settings-defaults.json +149 -0
  486. package/fixtures/{kasse-texte.json → pos-texts.json} +416 -416
  487. package/fixtures/receipt-due-generated.json +1218 -0
  488. package/fixtures/{belege/storno-rabatt.json → receipts/cancellation-discount.json} +3 -3
  489. package/fixtures/{belege/storno-voll.json → receipts/cancellation-full.json} +3 -3
  490. package/fixtures/{belege/storno-teil.json → receipts/cancellation-partial.json} +3 -3
  491. package/fixtures/{belege/storno-split-voll.json → receipts/cancellation-split-full.json} +3 -3
  492. package/fixtures/{belege/storno-split-teil.json → receipts/cancellation-split-partial.json} +3 -3
  493. package/fixtures/{belege/karte-eigener.json → receipts/card-custom.json} +2 -2
  494. package/fixtures/{belege/karte-gptom-ios.json → receipts/card-gptom-ios.json} +2 -2
  495. package/fixtures/{belege/karte-gptom.json → receipts/card-gptom.json} +2 -2
  496. package/fixtures/{belege/karte-hobex-cloud.json → receipts/card-hobex-cloud.json} +2 -2
  497. package/fixtures/{belege/karte-hobex-hps.json → receipts/card-hobex-hps.json} +2 -2
  498. package/fixtures/{belege/karte-mypos.json → receipts/card-mypos.json} +2 -2
  499. package/fixtures/{belege/karte-stripe-eps.json → receipts/card-stripe-eps.json} +2 -2
  500. package/fixtures/{belege/karte-stripe.json → receipts/card-stripe.json} +2 -2
  501. package/fixtures/{belege/karte-sumup.json → receipts/card-sumup.json} +2 -2
  502. package/fixtures/{belege/rabattzeilen.json → receipts/discount-lines.json} +2 -2
  503. package/fixtures/{belege/rabatt-chef-trinkgeld.json → receipts/discount-owner-tip.json} +2 -2
  504. package/fixtures/{belege/rabatt-einfach.json → receipts/discount-simple.json} +2 -2
  505. package/fixtures/{belege/rabatt-trinkgeld.json → receipts/discount-tip.json} +2 -2
  506. package/fixtures/{belege/rabatt-wertgutschein.json → receipts/discount-value-voucher.json} +2 -2
  507. package/fixtures/{belege/langer-artikelname.json → receipts/long-item-name.json} +2 -2
  508. package/fixtures/{belege/verkauf-karte.json → receipts/sale-card.json} +2 -2
  509. package/fixtures/{belege/verkauf-bar.json → receipts/sale-cash.json} +2 -2
  510. package/fixtures/{belege/verkauf-kleinunternehmer.json → receipts/sale-small-business.json} +1 -1
  511. package/fixtures/{belege/signaturausfall-verkauf.json → receipts/signature-outage-sale.json} +2 -2
  512. package/fixtures/{belege/split-karte-karte-bar.json → receipts/split-card-card-cash.json} +2 -2
  513. package/fixtures/{belege/split-bar-rueckgeld.json → receipts/split-cash-change.json} +2 -2
  514. package/fixtures/{belege/split-langer-betrag.json → receipts/split-long-amount.json} +2 -2
  515. package/fixtures/{belege/split-eine-karte-trinkgeld.json → receipts/split-one-card-tip.json} +2 -2
  516. package/fixtures/{belege/split-tischrunde-trinkgeld.json → receipts/split-table-round-tip.json} +2 -2
  517. package/fixtures/{belege/split-trinkgeld-karte.json → receipts/split-tip-card.json} +2 -2
  518. package/fixtures/{belege/split-zwei-karten-gleicher-anbieter.json → receipts/split-two-cards-same-provider.json} +2 -2
  519. package/fixtures/{belege/testsignatur-verkauf.json → receipts/test-cashregister-sale.json} +3 -3
  520. package/fixtures/{belege/testkasse-verkauf.json → receipts/test-signature-sale.json} +3 -3
  521. package/fixtures/{belege → receipts}/training.json +2 -2
  522. package/fixtures/{belege/null-jahr.json → receipts/zero-annual.json} +5 -5
  523. package/fixtures/{belege/null-schluss.json → receipts/zero-final.json} +5 -5
  524. package/fixtures/{belege/null-pruef.json → receipts/zero-manual.json} +5 -5
  525. package/fixtures/{belege/null-monat.json → receipts/zero-monthly.json} +5 -5
  526. package/fixtures/{belege/null-ausfall.json → receipts/zero-outage-end.json} +5 -5
  527. package/fixtures/{belege/null-start.json → receipts/zero-start.json} +5 -5
  528. package/fixtures/renames-1.0.json +1490 -0
  529. package/fixtures/{kasse-settings-standard.json → stored/pos-settings-defaults.json} +7 -7
  530. package/fixtures/surface.json +877 -0
  531. package/fixtures/v3/README.md +125 -0
  532. package/fixtures/v3/antworten/belege.json +4738 -0
  533. package/fixtures/v3/antworten/belegmail.json +154 -0
  534. package/fixtures/v3/antworten/kasse-belege.json +4304 -0
  535. package/fixtures/v3/antworten/kasse.json +12716 -0
  536. package/fixtures/v3/antworten/rechnungen.json +1712 -0
  537. package/fixtures/v3/antworten/storno.json +737 -0
  538. package/fixtures/v3/stored/belege.json +502 -0
  539. package/fixtures/v3/stored/kasse.json +3461 -0
  540. package/fixtures/v3/stored/rechnungen.json +750 -0
  541. package/fixtures/v3/v3-vokabular.json +3375 -0
  542. package/fixtures/v3/zahlbetrag-faelle.json +794 -0
  543. package/package.json +32 -18
  544. package/dist/cjs/kasse/artikel.d.ts +0 -83
  545. package/dist/cjs/kasse/artikel.js +0 -79
  546. package/dist/cjs/kasse/client.d.ts +0 -10
  547. package/dist/cjs/kasse/client.js +0 -38
  548. package/dist/cjs/kasse/drucker.d.ts +0 -59
  549. package/dist/cjs/kasse/drucker.js +0 -50
  550. package/dist/cjs/kasse/index.d.ts +0 -13
  551. package/dist/cjs/kasse/index.js +0 -83
  552. package/dist/cjs/kasse/settings.d.ts +0 -229
  553. package/dist/cjs/kasse/settings.js +0 -172
  554. package/dist/cjs/kasse/texte.d.ts +0 -868
  555. package/dist/cjs/kasse/texte.js +0 -474
  556. package/dist/cjs/rechnung/fehler.d.ts +0 -21
  557. package/dist/cjs/rechnung/fehler.js +0 -44
  558. package/dist/cjs/rechnung/index.d.ts +0 -21
  559. package/dist/cjs/rechnung/index.js +0 -82
  560. package/dist/cjs/rechnung/texte.d.ts +0 -222
  561. package/dist/cjs/rechnung/texte.js +0 -425
  562. package/dist/esm/kasse/artikel.d.ts +0 -83
  563. package/dist/esm/kasse/artikel.js +0 -70
  564. package/dist/esm/kasse/client.d.ts +0 -10
  565. package/dist/esm/kasse/client.js +0 -33
  566. package/dist/esm/kasse/drucker.d.ts +0 -59
  567. package/dist/esm/kasse/drucker.js +0 -45
  568. package/dist/esm/kasse/index.d.ts +0 -13
  569. package/dist/esm/kasse/index.js +0 -18
  570. package/dist/esm/kasse/settings.d.ts +0 -229
  571. package/dist/esm/kasse/settings.js +0 -168
  572. package/dist/esm/kasse/texte.d.ts +0 -868
  573. package/dist/esm/kasse/texte.js +0 -466
  574. package/dist/esm/rechnung/fehler.d.ts +0 -21
  575. package/dist/esm/rechnung/fehler.js +0 -39
  576. package/dist/esm/rechnung/index.d.ts +0 -21
  577. package/dist/esm/rechnung/index.js +0 -20
  578. package/dist/esm/rechnung/texte.d.ts +0 -222
  579. package/dist/esm/rechnung/texte.js +0 -421
  580. package/fixtures/erwartet/karte-eigener.blatt32.json +0 -158
  581. package/fixtures/erwartet/karte-gptom-ios.blatt32.json +0 -230
  582. package/fixtures/erwartet/karte-gptom.blatt32.json +0 -230
  583. package/fixtures/erwartet/karte-hobex-cloud.blatt32.json +0 -200
  584. package/fixtures/erwartet/karte-hobex-hps.blatt32.json +0 -224
  585. package/fixtures/erwartet/karte-mypos.blatt32.json +0 -254
  586. package/fixtures/erwartet/karte-stripe-eps.blatt32.json +0 -194
  587. package/fixtures/erwartet/karte-stripe.blatt32.json +0 -212
  588. package/fixtures/erwartet/karte-sumup.blatt32.json +0 -218
  589. package/fixtures/erwartet/langer-artikelname.blatt32.json +0 -176
  590. package/fixtures/erwartet/null-ausfall.blatt32.json +0 -206
  591. package/fixtures/erwartet/null-jahr.blatt32.json +0 -212
  592. package/fixtures/erwartet/null-monat.blatt32.json +0 -206
  593. package/fixtures/erwartet/null-pruef.blatt32.json +0 -206
  594. package/fixtures/erwartet/null-schluss.blatt32.json +0 -206
  595. package/fixtures/erwartet/null-start.blatt32.json +0 -206
  596. package/fixtures/erwartet/rabatt-chef-trinkgeld.blatt32.json +0 -212
  597. package/fixtures/erwartet/rabatt-einfach.blatt32.json +0 -182
  598. package/fixtures/erwartet/rabatt-trinkgeld.blatt32.json +0 -212
  599. package/fixtures/erwartet/rabatt-wertgutschein.blatt32.json +0 -218
  600. package/fixtures/erwartet/rabattzeilen.blatt32.json +0 -200
  601. package/fixtures/erwartet/signaturausfall-verkauf.blatt32.json +0 -194
  602. package/fixtures/erwartet/split-bar-rueckgeld.blatt32.json +0 -194
  603. package/fixtures/erwartet/split-eine-karte-trinkgeld.blatt32.json +0 -242
  604. package/fixtures/erwartet/split-karte-karte-bar.blatt32.json +0 -356
  605. package/fixtures/erwartet/split-langer-betrag.blatt32.json +0 -266
  606. package/fixtures/erwartet/split-tischrunde-trinkgeld.blatt32.json +0 -470
  607. package/fixtures/erwartet/split-trinkgeld-karte.blatt32.json +0 -272
  608. package/fixtures/erwartet/split-zwei-karten-gleicher-anbieter.blatt32.json +0 -326
  609. package/fixtures/erwartet/storno-rabatt.blatt32.json +0 -248
  610. package/fixtures/erwartet/storno-split-teil.blatt32.json +0 -230
  611. package/fixtures/erwartet/storno-split-voll.blatt32.json +0 -320
  612. package/fixtures/erwartet/storno-teil.blatt32.json +0 -206
  613. package/fixtures/erwartet/storno-voll.blatt32.json +0 -218
  614. package/fixtures/erwartet/testkasse-verkauf.blatt32.json +0 -224
  615. package/fixtures/erwartet/testsignatur-verkauf.blatt32.json +0 -236
  616. package/fixtures/erwartet/training.blatt32.json +0 -236
  617. package/fixtures/erwartet/verkauf-bar.blatt32.json +0 -176
  618. package/fixtures/erwartet/verkauf-karte.blatt32.json +0 -176
  619. package/fixtures/erwartet/verkauf-kleinunternehmer.blatt32.json +0 -182
  620. package/fixtures/kasse-meldungen-faelle.json +0 -32
  621. package/fixtures/oberflaeche.json +0 -558
  622. package/fixtures/rechnung-api-beispiele/brands-ok.json +0 -8
  623. package/fixtures/rechnung-api-beispiele/customer-get-fehler-beide.json +0 -15
  624. package/fixtures/rechnung-api-beispiele/setup-status-ok.json +0 -8
  625. package/fixtures/rechnung-api-beispiele/zahlung-fehler-ohne-schluessel.json +0 -14
  626. package/fixtures/rechnung-api-beispiele/zahlung-fehler-vor-ort.json +0 -15
  627. package/fixtures/rechnung-api-beispiele/zahlung-nachtrag.json +0 -14
  628. package/fixtures/rechnung-texte.json +0 -464
  629. /package/dist/cjs/{rechnung → invoice}/typen.js +0 -0
  630. /package/dist/esm/{rechnung → invoice}/typen.js +0 -0
  631. /package/fixtures/{erwartet/storno-rabatt.grid32.txt → expected/cancellation-discount.grid32.txt} +0 -0
  632. /package/fixtures/{erwartet/storno-rabatt.grid48.txt → expected/cancellation-discount.grid48.txt} +0 -0
  633. /package/fixtures/{erwartet/storno-voll.grid32.txt → expected/cancellation-full.grid32.txt} +0 -0
  634. /package/fixtures/{erwartet/storno-voll.grid48.txt → expected/cancellation-full.grid48.txt} +0 -0
  635. /package/fixtures/{erwartet/storno-teil.grid32.txt → expected/cancellation-partial.grid32.txt} +0 -0
  636. /package/fixtures/{erwartet/storno-teil.grid48.txt → expected/cancellation-partial.grid48.txt} +0 -0
  637. /package/fixtures/{erwartet/storno-split-voll.grid32.txt → expected/cancellation-split-full.grid32.txt} +0 -0
  638. /package/fixtures/{erwartet/storno-split-voll.grid48.txt → expected/cancellation-split-full.grid48.txt} +0 -0
  639. /package/fixtures/{erwartet/storno-split-teil.grid32.txt → expected/cancellation-split-partial.grid32.txt} +0 -0
  640. /package/fixtures/{erwartet/storno-split-teil.grid48.txt → expected/cancellation-split-partial.grid48.txt} +0 -0
  641. /package/fixtures/{erwartet/karte-eigener.grid32.txt → expected/card-custom.grid32.txt} +0 -0
  642. /package/fixtures/{erwartet/karte-eigener.grid48.txt → expected/card-custom.grid48.txt} +0 -0
  643. /package/fixtures/{erwartet/karte-gptom-ios.grid32.txt → expected/card-gptom-ios.grid32.txt} +0 -0
  644. /package/fixtures/{erwartet/karte-gptom-ios.grid48.txt → expected/card-gptom-ios.grid48.txt} +0 -0
  645. /package/fixtures/{erwartet/karte-gptom.grid32.txt → expected/card-gptom.grid32.txt} +0 -0
  646. /package/fixtures/{erwartet/karte-gptom.grid48.txt → expected/card-gptom.grid48.txt} +0 -0
  647. /package/fixtures/{erwartet/karte-hobex-cloud.grid32.txt → expected/card-hobex-cloud.grid32.txt} +0 -0
  648. /package/fixtures/{erwartet/karte-hobex-cloud.grid48.txt → expected/card-hobex-cloud.grid48.txt} +0 -0
  649. /package/fixtures/{erwartet/karte-hobex-hps.grid32.txt → expected/card-hobex-hps.grid32.txt} +0 -0
  650. /package/fixtures/{erwartet/karte-hobex-hps.grid48.txt → expected/card-hobex-hps.grid48.txt} +0 -0
  651. /package/fixtures/{erwartet/karte-mypos.grid32.txt → expected/card-mypos.grid32.txt} +0 -0
  652. /package/fixtures/{erwartet/karte-mypos.grid48.txt → expected/card-mypos.grid48.txt} +0 -0
  653. /package/fixtures/{erwartet/karte-stripe-eps.grid32.txt → expected/card-stripe-eps.grid32.txt} +0 -0
  654. /package/fixtures/{erwartet/karte-stripe-eps.grid48.txt → expected/card-stripe-eps.grid48.txt} +0 -0
  655. /package/fixtures/{erwartet/karte-stripe.grid32.txt → expected/card-stripe.grid32.txt} +0 -0
  656. /package/fixtures/{erwartet/karte-stripe.grid48.txt → expected/card-stripe.grid48.txt} +0 -0
  657. /package/fixtures/{erwartet/karte-sumup.grid32.txt → expected/card-sumup.grid32.txt} +0 -0
  658. /package/fixtures/{erwartet/karte-sumup.grid48.txt → expected/card-sumup.grid48.txt} +0 -0
  659. /package/fixtures/{erwartet/rabattzeilen.grid32.txt → expected/discount-lines.grid32.txt} +0 -0
  660. /package/fixtures/{erwartet/rabattzeilen.grid48.txt → expected/discount-lines.grid48.txt} +0 -0
  661. /package/fixtures/{erwartet/rabatt-chef-trinkgeld.grid32.txt → expected/discount-owner-tip.grid32.txt} +0 -0
  662. /package/fixtures/{erwartet/rabatt-chef-trinkgeld.grid48.txt → expected/discount-owner-tip.grid48.txt} +0 -0
  663. /package/fixtures/{erwartet/rabatt-einfach.grid32.txt → expected/discount-simple.grid32.txt} +0 -0
  664. /package/fixtures/{erwartet/rabatt-einfach.grid48.txt → expected/discount-simple.grid48.txt} +0 -0
  665. /package/fixtures/{erwartet/rabatt-trinkgeld.grid32.txt → expected/discount-tip.grid32.txt} +0 -0
  666. /package/fixtures/{erwartet/rabatt-trinkgeld.grid48.txt → expected/discount-tip.grid48.txt} +0 -0
  667. /package/fixtures/{erwartet/rabatt-wertgutschein.grid32.txt → expected/discount-value-voucher.grid32.txt} +0 -0
  668. /package/fixtures/{erwartet/rabatt-wertgutschein.grid48.txt → expected/discount-value-voucher.grid48.txt} +0 -0
  669. /package/fixtures/{erwartet/logo-probe-hoch.raster32.txt → expected/logo-sample-tall.raster32.txt} +0 -0
  670. /package/fixtures/{erwartet/logo-probe.raster32.txt → expected/logo-sample.raster32.txt} +0 -0
  671. /package/fixtures/{erwartet/langer-artikelname.grid32.txt → expected/long-item-name.grid32.txt} +0 -0
  672. /package/fixtures/{erwartet/langer-artikelname.grid48.txt → expected/long-item-name.grid48.txt} +0 -0
  673. /package/fixtures/{erwartet/verkauf-karte.grid32.txt → expected/sale-card.grid32.txt} +0 -0
  674. /package/fixtures/{erwartet/verkauf-karte.grid48.txt → expected/sale-card.grid48.txt} +0 -0
  675. /package/fixtures/{erwartet/verkauf-bar.grid32.txt → expected/sale-cash.grid32.txt} +0 -0
  676. /package/fixtures/{erwartet/verkauf-bar.grid48.txt → expected/sale-cash.grid48.txt} +0 -0
  677. /package/fixtures/{erwartet/verkauf-kleinunternehmer.grid32.txt → expected/sale-small-business.grid32.txt} +0 -0
  678. /package/fixtures/{erwartet/verkauf-kleinunternehmer.grid48.txt → expected/sale-small-business.grid48.txt} +0 -0
  679. /package/fixtures/{erwartet/signaturausfall-verkauf.grid32.txt → expected/signature-outage-sale.grid32.txt} +0 -0
  680. /package/fixtures/{erwartet/signaturausfall-verkauf.grid48.txt → expected/signature-outage-sale.grid48.txt} +0 -0
  681. /package/fixtures/{erwartet/split-karte-karte-bar.grid32.txt → expected/split-card-card-cash.grid32.txt} +0 -0
  682. /package/fixtures/{erwartet/split-karte-karte-bar.grid48.txt → expected/split-card-card-cash.grid48.txt} +0 -0
  683. /package/fixtures/{erwartet/split-bar-rueckgeld.grid32.txt → expected/split-cash-change.grid32.txt} +0 -0
  684. /package/fixtures/{erwartet/split-bar-rueckgeld.grid48.txt → expected/split-cash-change.grid48.txt} +0 -0
  685. /package/fixtures/{erwartet/split-langer-betrag.grid32.txt → expected/split-long-amount.grid32.txt} +0 -0
  686. /package/fixtures/{erwartet/split-langer-betrag.grid48.txt → expected/split-long-amount.grid48.txt} +0 -0
  687. /package/fixtures/{erwartet/split-eine-karte-trinkgeld.grid32.txt → expected/split-one-card-tip.grid32.txt} +0 -0
  688. /package/fixtures/{erwartet/split-eine-karte-trinkgeld.grid48.txt → expected/split-one-card-tip.grid48.txt} +0 -0
  689. /package/fixtures/{erwartet/split-tischrunde-trinkgeld.grid32.txt → expected/split-table-round-tip.grid32.txt} +0 -0
  690. /package/fixtures/{erwartet/split-tischrunde-trinkgeld.grid48.txt → expected/split-table-round-tip.grid48.txt} +0 -0
  691. /package/fixtures/{erwartet/split-trinkgeld-karte.grid32.txt → expected/split-tip-card.grid32.txt} +0 -0
  692. /package/fixtures/{erwartet/split-trinkgeld-karte.grid48.txt → expected/split-tip-card.grid48.txt} +0 -0
  693. /package/fixtures/{erwartet/split-zwei-karten-gleicher-anbieter.grid32.txt → expected/split-two-cards-same-provider.grid32.txt} +0 -0
  694. /package/fixtures/{erwartet/split-zwei-karten-gleicher-anbieter.grid48.txt → expected/split-two-cards-same-provider.grid48.txt} +0 -0
  695. /package/fixtures/{erwartet/testkasse-verkauf.grid32.txt → expected/test-cashregister-sale.grid32.txt} +0 -0
  696. /package/fixtures/{erwartet/testkasse-verkauf.grid48.txt → expected/test-cashregister-sale.grid48.txt} +0 -0
  697. /package/fixtures/{erwartet/testsignatur-verkauf.grid32.txt → expected/test-signature-sale.grid32.txt} +0 -0
  698. /package/fixtures/{erwartet/testsignatur-verkauf.grid48.txt → expected/test-signature-sale.grid48.txt} +0 -0
  699. /package/fixtures/{erwartet → expected}/training.grid32.txt +0 -0
  700. /package/fixtures/{erwartet → expected}/training.grid48.txt +0 -0
  701. /package/fixtures/{erwartet/null-jahr.grid32.txt → expected/zero-annual.grid32.txt} +0 -0
  702. /package/fixtures/{erwartet/null-jahr.grid48.txt → expected/zero-annual.grid48.txt} +0 -0
  703. /package/fixtures/{erwartet/null-schluss.grid32.txt → expected/zero-final.grid32.txt} +0 -0
  704. /package/fixtures/{erwartet/null-schluss.grid48.txt → expected/zero-final.grid48.txt} +0 -0
  705. /package/fixtures/{erwartet/null-pruef.grid32.txt → expected/zero-manual.grid32.txt} +0 -0
  706. /package/fixtures/{erwartet/null-pruef.grid48.txt → expected/zero-manual.grid48.txt} +0 -0
  707. /package/fixtures/{erwartet/null-monat.grid32.txt → expected/zero-monthly.grid32.txt} +0 -0
  708. /package/fixtures/{erwartet/null-monat.grid48.txt → expected/zero-monthly.grid48.txt} +0 -0
  709. /package/fixtures/{erwartet/null-ausfall.grid32.txt → expected/zero-outage-end.grid32.txt} +0 -0
  710. /package/fixtures/{erwartet/null-ausfall.grid48.txt → expected/zero-outage-end.grid48.txt} +0 -0
  711. /package/fixtures/{erwartet/null-start.grid32.txt → expected/zero-start.grid32.txt} +0 -0
  712. /package/fixtures/{erwartet/null-start.grid48.txt → expected/zero-start.grid48.txt} +0 -0
package/README.md CHANGED
@@ -36,6 +36,7 @@ models, same enum values, checked against each other in tests.
36
36
  - [What a fiscal cash register in Austria must do](#what-a-fiscal-cash-register-in-austria-must-do)
37
37
  - [Try it first, or use the ready-made register](#try-it-first-or-use-the-ready-made-register)
38
38
  - [Requirements and subpaths](#requirements-and-subpaths)
39
+ - [Base URLs and the `/v3` marker](#base-urls-and-the-v3-marker)
39
40
  - [Authentication](#authentication)
40
41
  - [Amounts are integer cents](#amounts-are-integer-cents)
41
42
  - [Errors](#errors)
@@ -43,9 +44,12 @@ models, same enum values, checked against each other in tests.
43
44
  - [Cancellation (Storno)](#cancellation-storno)
44
45
  - [Sending a receipt by email](#sending-a-receipt-by-email)
45
46
  - [Receipt printing: QR code, logo, printers](#receipt-printing-qr-code-logo-printers)
47
+ - [Register settings, articles and printers (`./pos`)](#register-settings-articles-and-printers-pos)
48
+ - [Stored documents (`./stored`)](#stored-documents-stored)
46
49
  - [Card payments](#card-payments)
47
50
  - [Partner API (`./partner`)](#partner-api-partner)
48
- - [Invoice API (`./rechnung`)](#invoice-api-rechnung)
51
+ - [Invoice API (`./invoice`)](#invoice-api-invoice)
52
+ - [Migrating from 0.x](#migrating-from-0x)
49
53
  - [Development](#development)
50
54
  - [Contract files for the twin packages](#contract-files-for-the-twin-packages)
51
55
  - [Glossary](#glossary)
@@ -65,40 +69,70 @@ import {
65
69
  apiKeyAuth,
66
70
  KeckPaymentMethod,
67
71
  VatRate,
72
+ receiptDueCents,
73
+ receiptLayoutFromResult,
68
74
  } from '@kreiseck/kasseneck-api';
69
- import { buildReceiptLayout, renderReceiptGrid, escPosLayoutBytes } from '@kreiseck/kasseneck-api/receipt';
75
+ import { renderReceiptGrid, escPosLayoutBytes } from '@kreiseck/kasseneck-api/receipt';
70
76
 
71
77
  const api = createKasseneckApi({
72
78
  auth: apiKeyAuth({ apiKey: 'kr_live_…', cashregisterToken: 'cb_live_…' }),
73
79
  });
74
80
 
75
- // Sell, and get the company data for the receipt header in the same call.
76
- const { receipt, company, testKasse, testSignatur, pruefangaben } = await api.sellReceiptWithCompany({
77
- paymentMethod: KeckPaymentMethod.cash,
78
- items: [
79
- { name: 'Café Latte', quantity: 2, vat: VatRate.vat20, priceCents: 390 },
80
- { name: 'Marmeladeweckerl', quantity: 1, vat: VatRate.vat10, priceCents: 250 },
81
- ],
82
- // Optional tip in cents; the backend books it as a signed tip line.
83
- // With its own payment method or recipients: { cents, paymentMethod, recipients }.
84
- tip: 100,
81
+ const items = [
82
+ { name: 'Café Latte', quantity: 2, vat: VatRate.vat20, priceCents: 390 },
83
+ { name: 'Marmeladeweckerl', quantity: 1, vat: VatRate.vat10, priceCents: 250 },
84
+ ];
85
+ // Optional tip in cents; the backend books it as a signed tip line.
86
+ // With its own payment method or recipients: { cents, paymentMethod, recipients }.
87
+ const tip = 100;
88
+
89
+ // The payments must add up to exactly this amount (whole cents). Who gets a
90
+ // tip without recipients is the logged-in register user: 'owner' or 'staff'.
91
+ const dueCents = receiptDueCents(items, [], 'standard', { tip, tipRecipient: 'staff' }); // 1130
92
+
93
+ // Sell, and get the company data and the receipt layout in the same call.
94
+ const result = await api.sellReceiptWithCompany({
95
+ items,
96
+ tip,
97
+ payments: [{ method: KeckPaymentMethod.cash, amountCents: dueCents, tenderedCents: 2000 }],
85
98
  });
86
99
 
87
- // Layout: a plain data model (lines, alignment, columns, QR code).
88
- // testKasse / testSignatur add the "not a valid receipt" banner where needed.
89
- const layout = buildReceiptLayout(receipt, company, { paperSize: 'mm58', testKasse, testSignatur, pruefangaben });
100
+ // Layout: a plain data model (lines, alignment, columns, QR code). The server
101
+ // sends it as `layout` (80 mm), and it always wins; only without it does
102
+ // receiptLayoutFromResult build one from the same response (test banners
103
+ // included) in `fallbackPaperSize` (default 'mm58'). The print width is chosen
104
+ // by the print path (`paperSize` below), never by this helper.
105
+ const layout = receiptLayoutFromResult(result);
90
106
 
91
107
  // Character grid: exactly 32 (58 mm) or 48 (80 mm) characters per line.
92
108
  // Screen, printed receipt and PDF all use this one grid.
93
- const grid = renderReceiptGrid(layout); // grid.lines[i].text, .bold, .kind, .qr
109
+ const grid = renderReceiptGrid(layout, { charsPerLine: 32 }); // grid.lines[i].text, .bold, .kind, .qr
94
110
 
95
111
  // ESC/POS bytes for a thermal printer; they print exactly the grid lines.
96
- const bytes = escPosLayoutBytes(layout);
112
+ const bytes = escPosLayoutBytes(layout, { paperSize: 'mm58' });
97
113
  ```
98
114
 
99
115
  The receipt returned by `sellReceiptWithCompany` (or `sellReceipt`) has already
100
116
  been signed, chained and stored in the data capture log (*DEP*) by the backend.
101
117
 
118
+ **Payments are mandatory.** Every sale carries `payments[]` (several per receipt:
119
+ card plus cash and so on); card details (`provider`, `providerPaymentId`,
120
+ `providerData`) belong to the single payment. `receiptDueCents` computes the
121
+ amount the payments must match, exactly as the backend does (tax buckets,
122
+ discount vouchers, tips, value vouchers). If they do not match, the backend
123
+ rejects the receipt with `payments_sum_mismatch` without using up a receipt
124
+ number; `paymentsExpectedCents(error)` gives its amount. The package never
125
+ retries on its own: a card payment has already been charged.
126
+
127
+ The list may be empty only when the amount due is 0. The single
128
+ `paymentMethod` of 0.x and the card fields beside it (`creditCardProvider`,
129
+ `cardPaymentId`, `cardPaymentData`) are rejected before anything is sent.
130
+ `receiptDueCents` needs `tipRecipient` (`'owner'` or `'staff'`, the role of the
131
+ signed-in register user) as soon as a tip has no `recipients`: an owner's tip
132
+ is turnover, spread over the VAT rates of the goods and discounted with them,
133
+ while a staff tip goes untouched into the 0 % bucket. Only the register knows
134
+ which one applies, so the helper never guesses.
135
+
102
136
  ## What a fiscal cash register in Austria must do
103
137
 
104
138
  The obligation to use a fiscal cash register and to issue receipts is set out
@@ -166,17 +200,70 @@ adapter:
166
200
  | `…/printing` | ESC/POS generation (byte sequences for thermal printers), QR sizing, printing over WebUSB. |
167
201
  | `…/payments` | Stripe payment links, Hobex cloud (both HTTP endpoints of the backend), and Hobex **HPS** via **Kasseneck Connect** (local device agent that talks to the terminal). |
168
202
  | `…/register` | Sign-in for the browser register: pair and unpair a device, list its users and sessions, sign in by PIN, renew and end the session. |
169
- | `…/kasse` | Tile register: register settings (business-wide and per device), article groups and articles for tiles, discount distribution per VAT rate, scopes of register permissions, network printers and print jobs, tip recipients, the register's message catalogue. |
203
+ | `…/pos` | Tile register: register settings (business-wide and per device), article groups and articles for tiles, discount distribution per VAT rate, scopes of register permissions, network printers and print jobs, tip recipients, the register's message catalogue. |
170
204
  | `…/partner` | Partner API (`/v3`, English): create businesses, FinanzOnline link, signature, cash registers, credentials, webhooks with signature verification. **Belongs on a server.** |
171
- | `…/rechnung` | Invoice API: create and search customers, issue finalised invoices, credit notes and cancellation, PDF and e-invoice XML, the contract as data. **Belongs on a server.** |
172
- | `…/rechnung/rechnen` | Pure calculation core for invoice totals (integers, no transport, no dependency beyond types). Safe to run in the browser. |
205
+ | `…/stored` | Stored Firestore documents (inner form, German) as the same English models the `/v3` wire returns: receipts with company and layout, register settings, articles. For clients that read Firestore directly, such as the admin panel. |
206
+ | `…/invoice` | Invoice API: create and search customers, issue finalised invoices, credit notes and cancellation, PDF and e-invoice XML, the contract as data. **Belongs on a server.** |
207
+ | `…/invoice/calc` | Pure calculation core for invoice totals (integers, no transport, no dependency beyond types). Safe to run in the browser. |
173
208
  | `…/react` | Thin React adapter that renders a receipt layout or a receipt sheet. Needs React. |
174
- | `…/fixtures/*` | Golden receipts (JSON): inputs `belege/<name>.json`, promised line output `erwartet/<name>.lines.json`, `manifest.json` with checksums. The backend, the browser register and the Flutter package check against the same files. |
209
+ | `…/fixtures/*` | Golden receipts (JSON): inputs `receipts/<name>.json`, promised line output `expected/<name>.lines.json`, `manifest.json` with checksums. The backend, the browser register and the Flutter package check against the same files. |
175
210
 
176
211
  Every exported function carries its documentation as TSDoc in the shipped type
177
212
  declarations, so your editor shows it on hover. That is also the reference for
178
213
  the partner and invoice endpoints; this README shows how to use the client.
179
214
 
215
+ ## Base URLs and the `/v3` marker
216
+
217
+ 1.x speaks only the English API `/v3`. Every field name, every value your code
218
+ branches on and every error code is English; texts for people (`message`,
219
+ `serverMessage`, `nextSteps`, the printed receipt) stay German, as do the
220
+ terms of the BMF and FinanzOnline.
221
+
222
+ | Path | Default | Option | Used for |
223
+ |---|---|---|---|
224
+ | public | `https://api.kasseneck.at/v3` (`DEFAULT_BASE_URL`) | `baseUrl` | receipts with `apiKeyAuth`, reports, payments, FinanzOnline, invoice and partner API |
225
+ | register (POS) | `https://kasse.kasseneck.at/api/v3` (`POS_BASE_URL`) | `posBaseUrl` | pairing, sign-in, settings, articles, printers; with `registerUserAuth` also receipts, cancellation and receipt email |
226
+ | same origin | `/api/v3` | `posBaseUrl: '/api/v3'` | the browser register served from `kasse.kasseneck.at` itself |
227
+
228
+ The package picks the path per call; `PUBLIC_CALLS` and `POS_CALLS` list which
229
+ call goes where. A base of your own (a proxy, the emulator) must end in `/v3`
230
+ once trailing slashes are removed, otherwise creating the client throws a
231
+ `KasseneckValidationError` right away. There is no `/v1` and no bare `/api` in
232
+ the 1.x line.
233
+
234
+ ```ts
235
+ import { createKasseneckApi, registerUserAuth } from '@kreiseck/kasseneck-api';
236
+
237
+ // Browser register on kasse.kasseneck.at: same origin, no CORS involved.
238
+ const pos = createKasseneckApi({
239
+ auth: registerUserAuth({ getIdToken, getSessionId, cashregisterId: 'kasse-1' }),
240
+ posBaseUrl: '/api/v3',
241
+ clientHeader: 'kasse-web/2026.09.28', // optional; default kasseneck-api/<version>
242
+ });
243
+ ```
244
+
245
+ **The marker, fail closed.** Each request to a Kasseneck base (the two hosts
246
+ above over https, or a relative path) carries `Kasseneck-Api-Version: v3` and
247
+ `Kasseneck-Client`. Each response is checked **before** its body is read:
248
+
249
+ - HTTP 200 with `text/html` is the hosting fallback page; the call never
250
+ arrived: `KasseneckApiError` with `code: 'route_missing'`.
251
+ - A response without `Kasseneck-Api-Version: v3` came from an edge that does
252
+ not speak `/v3`: `code: 'dialect_mismatch'` with `outcome: 'unknown'`
253
+ (behind an old edge a receipt may have been signed). See [Errors](#errors).
254
+ - HTTP 404 with the marker and an error envelope is how `/v3` answers an
255
+ unknown endpoint: `code: 'not_found'`.
256
+
257
+ The package never falls back to another version. A mismatch is an error, not
258
+ a reason to try `/v1`.
259
+
260
+ **Browser on another origin.** A browser that calls `https://api.kasseneck.at/v3`
261
+ from a foreign origin sends a CORS preflight that asks for the two headers
262
+ above. Until the backend allows them in the `/v3` preflight, set
263
+ `omitKasseneckHeaders: true` on such a client. Only the request headers are
264
+ dropped; the response check stays. The browser register on its own origin
265
+ (`/api/v3`) and any Node process need nothing of this.
266
+
180
267
  ## Authentication
181
268
 
182
269
  The client takes an **exchangeable authentication**: an object that supplies
@@ -208,8 +295,8 @@ const register = registerUserAuth({
208
295
 
209
296
  Six calls run **without any identity**, because they are how an identity comes
210
297
  into being or how a device manages itself. They live in `…/register` and take
211
- **no authentication**, only the connection settings (base URL, timeout,
212
- `fetch`):
298
+ **no authentication**, only the connection settings (`posBaseUrl`, timeout,
299
+ `fetch`); they always go to the register path:
213
300
 
214
301
  | Call | Proof instead of authentication |
215
302
  |---|---|
@@ -226,6 +313,28 @@ const paired = await pairRegisterDevice({ code: 'K7NPQR34', label: 'Bar' });
226
313
  const session = await registerUserLogin({ ...paired, userId: 'ru-1', pin: '1234' });
227
314
  ```
228
315
 
316
+ `paired` carries `companyName`, `cashregisterLabel` and `testEnvironment`. A
317
+ device record stored under 0.x (device id and secret) keeps working: the calls
318
+ only send the device credentials, no new pairing is needed.
319
+
320
+ Sign-in errors carry a code from `REGISTER_ERROR_CODES`. Decide with
321
+ `isRegisterError(error, code)`; seconds to wait, the name of the device that
322
+ holds a session and the like come from `registerErrorDetails(error)`
323
+ (`deviceLabel`, `takeoverAllowed`, `retryAfterSec`, `distanceM`,
324
+ `pairedDevices`, `licenses`), never from the message text:
325
+
326
+ ```ts
327
+ import { isRegisterError, registerErrorDetails, registerPinLogin } from '@kreiseck/kasseneck-api/register';
328
+
329
+ try {
330
+ await registerPinLogin({ ...paired, pin });
331
+ } catch (error) {
332
+ if (isRegisterError(error, 'too_many_attempts')) {
333
+ showWait(registerErrorDetails(error).retryAfterSec);
334
+ } else throw error;
335
+ }
336
+ ```
337
+
229
338
  With `session.customToken` the app signs in to the sign-in service; the
230
339
  resulting ID token together with `session.sessionId` feeds `registerUserAuth`.
231
340
  `renewRegisterSession` and `endRegisterSession` then run with
@@ -261,7 +370,7 @@ For the same reason a receipt line's `quantity` is a **whole number**. A
261
370
  fractional one is rejected before anything is sent.
262
371
 
263
372
  The invoice API has its own units: unit prices in cents or micro-euros,
264
- quantities with up to three decimals. See [Invoice API](#invoice-api-rechnung).
373
+ quantities with up to three decimals. See [Invoice API](#invoice-api-invoice).
265
374
 
266
375
  ## Errors
267
376
 
@@ -271,18 +380,88 @@ a type guard:
271
380
 
272
381
  | Class | Guard | Meaning |
273
382
  |---|---|---|
274
- | `KasseneckApiError` | `isKasseneckApiError` | The backend received the request and rejected it (locked register, missing module, invalid parameter). Retrying does not help. Carries `code` (where the endpoint defines one), `serverMessage` (German display text) and `details`. |
275
- | `KasseneckHttpError` | `isKasseneckHttpError` | The response was not a usable envelope: HTTP 404/500, empty body, HTML instead of JSON. `reason` tells the cases apart. |
276
- | `KasseneckNetworkError` | `isKasseneckNetworkError` | No response at all: network down, DNS, aborted connection or timeout (`timedOut`). |
383
+ | `KasseneckApiError` | `isKasseneckApiError` | The backend answered with an error envelope (locked register, missing module, invalid parameter), or the package refused the response (`route_missing`, `dialect_mismatch`, `response_unreadable`). Carries `code`, `outcome`, `serverMessage` (German display text) and `details`. |
384
+ | `KasseneckHttpError` | `isKasseneckHttpError` | The response was not a usable envelope: HTTP 404/500 without envelope, empty body, text instead of JSON. `reason` tells the cases apart; `outcome` as below. |
385
+ | `KasseneckNetworkError` | `isKasseneckNetworkError` | No response at all: network down, DNS, aborted connection or timeout (`timedOut`). `outcome` as below. |
277
386
  | `KasseneckAuthError` | `isKasseneckAuthError` | The request was never sent because authentication failed (missing credentials, or the token or session provider threw). |
278
- | `KasseneckValidationError` | `isKasseneckValidationError` | Wrong shape. `scope: 'request'`: your input breaks a rule the package knows before sending. `scope: 'response'`: the backend reported success but the payload lacked what the call promises. |
387
+ | `KasseneckValidationError` | `isKasseneckValidationError` | Wrong shape. `scope: 'request'`: your input breaks a rule the package knows before sending. `scope: 'response'`: the backend reported success but the payload of a non-signing call lacked what it promises (on `createReceipt` and `cancelReceipt` that is `response_unreadable` instead). |
279
388
 
280
389
  **None of them ever contains a secret**: no key, no token, neither the sent nor
281
390
  the received body.
282
391
 
283
- **Decide on the code, not the text.** Where an endpoint has a catalogue of
284
- error codes (cancellation, receipt email, partner and invoice API), branch on
285
- `error.code`. The German `serverMessage` is for display and may change.
392
+ **Decide on the code, not the text.** Every code is English, lower case,
393
+ `snake_case`, and every endpoint group ships its catalogue with a guard:
394
+
395
+ | Catalogue | Guard | Where |
396
+ |---|---|---|
397
+ | `RECEIPT_ERROR_CODES` | `isReceiptError` | `createReceipt`, `getReceipt` |
398
+ | `CANCELLATION_ERROR_CODES` | `isCancellationError` | `cancelReceipt` |
399
+ | `PAYMENT_ERROR_CODES` | `isPaymentError` | `payments[]` of a sale or cancellation |
400
+ | `RECEIPT_EMAIL_ERROR_CODES` | `isReceiptEmailError` | `sendReceiptEmail` |
401
+ | `REGISTER_ERROR_CODES` | `isRegisterError` (`…/register`) | pairing and sign-in |
402
+ | `POS_ERROR_CODES` | `isPosError` (`…/pos`) | settings, articles, printers, tip recipients |
403
+ | `PARTNER_ERROR_CODES` + `PARTNER_REQUEST_ERROR_CODES` | `isPartnerError` (`…/partner`) | partner API |
404
+ | `INVOICE_ERROR_CODES` + `INVOICE_REQUEST_ERROR_CODES` | `isInvoiceError` (`…/invoice`) | invoice API |
405
+
406
+ Every group has the same helpers: `is…ErrorCode(value)`, `…ErrorCode(error)`
407
+ (the code if the group knows it), `is…Error(error, code?)` (a type guard; without
408
+ `code` it asks whether the error belongs to the group) and
409
+ `…FieldErrors(error)` for the fields of a `validation` error
410
+ (`receiptFieldErrors`, `cancellationFieldErrors`, `paymentFieldErrors`,
411
+ `receiptEmailFieldErrors`, `registerFieldErrors`, `posFieldErrors`,
412
+ `invoiceFieldErrors`, `partnerFieldErrors`). Each list holds the group's own
413
+ codes, then the sign-in and edge codes that can reach the same call, then the
414
+ codes the package sets itself (`CLIENT_ERROR_CODES`: `route_missing`, and
415
+ `response_unreadable` on receipts and cancellations). A sale can fail with a
416
+ code from `RECEIPT_ERROR_CODES` or `PAYMENT_ERROR_CODES`, a cancellation with
417
+ one from `CANCELLATION_ERROR_CODES` or `PAYMENT_ERROR_CODES`. The invoice and
418
+ partner catalogues stay exactly the server's; their `…_REQUEST_ERROR_CODES`
419
+ add the rest. The German `serverMessage` is for display and may change.
420
+
421
+ Validation is strict: the 0.x ways of paying (`paymentMethod` and its card
422
+ fields), unknown keys in tips, layout options, register settings and the
423
+ receipt email, and values outside a settings field's value list throw a
424
+ `KasseneckValidationError` before anything is sent, instead of being dropped
425
+ silently. For a layout option of 0.x the message names its English successor.
426
+
427
+ ### `outcome: 'unknown'`: never retry, look it up
428
+
429
+ `KasseneckApiError`, `KasseneckHttpError` and `KasseneckNetworkError` carry
430
+ `outcome`. `'rejected'` means no signing operation is left open: no receipt was
431
+ signed and nothing went to FinanzOnline, so retrying the same request does not
432
+ create a second receipt (whether it helps depends on the code). `'unknown'` means the operation **may have been carried out**, for
433
+ `createReceipt` a signed receipt in the chain. Then never send it again: read
434
+ the result back (`getReceipt`, `listMyReceipts`, the original of a
435
+ cancellation) and continue from there. `isOutcomeUnknown(error)` covers all
436
+ three classes. The outcome is unknown for:
437
+
438
+ - `dialect_mismatch`, `receipt_outcome_unknown`, `cancellation_outcome_unknown`;
439
+ - `response_translation_failed`, unless `details.handled === false`;
440
+ - `response_unreadable`: a signing call reported success, but the response
441
+ lacks what the call promises (no receipt, no reference, no remaining
442
+ quantities);
443
+ - on the signing calls `createReceipt`, `cancelReceipt` and
444
+ `financeWebService`: a network error or timeout after sending began, HTTP
445
+ 5xx, and HTTP 200 with the `Kasseneck-Api-Version: v3` marker but an empty,
446
+ non-JSON (also `text/html`) or status-less body (`KasseneckHttpError`,
447
+ `reason` `empty-body`, `not-json` or `missing-status`). HTML without the
448
+ marker stays `route_missing` with `'rejected'`: no function saw the call.
449
+
450
+ `outcome` only covers signing. After a network error on `issueInvoice` an
451
+ invoice may still have been issued; retry it with the same `idempotencyKey`.
452
+
453
+ ```ts
454
+ import { isOutcomeUnknown, paymentsExpectedCents } from '@kreiseck/kasseneck-api';
455
+
456
+ try {
457
+ await api.sellReceipt({ items, payments });
458
+ } catch (error) {
459
+ if (isOutcomeUnknown(error)) return reloadReceiptsAndAsk(); // never sell again blindly
460
+ const expected = paymentsExpectedCents(error); // payments_sum_mismatch
461
+ if (expected !== undefined) return askAgain(expected);
462
+ throw error;
463
+ }
464
+ ```
286
465
 
287
466
  ## Receipts
288
467
 
@@ -290,17 +469,48 @@ The facade from `createKasseneckApi` offers `sellReceipt` and
290
469
  `sellReceiptWithCompany`, `zeroReceipt` for a zero receipt (*Nullbeleg*),
291
470
  `getReceipt` and `getReceiptWithCompany`, `listMyReceipts`, `cancelReceipt`,
292
471
  `sendReceiptEmail`, the report downloads, the FinanzOnline status queries
293
- (`getCashboxStatus`, `getSignatureStatus`) and the Stripe and Hobex cloud
472
+ (`getCashboxStatus`, `getSignatureStatus`), `getReportV2({ start, end })` for
473
+ the raw receipts and company data of a period, and the Stripe and Hobex cloud
294
474
  payments.
295
475
 
476
+ The models are English throughout: the company has `taxNumber` and `vatId`, a
477
+ receipt `headerVersionId`, `layoutRuleset` and `registrationInfo`, a receipt
478
+ in the list `cancellationStatus` (`none`, `partial`, `full`, or `'unknown'` for
479
+ a value this version does not know: then offer no cancellation). The same
480
+ rule holds for print job states and register settings: a value the package
481
+ does not know is shown as `'unknown'` or kept as sent, never mapped onto a
482
+ known one.
483
+
296
484
  **Layout rule sets.** `buildReceiptLayout` sets receipts according to a
297
- numbered rule set. Without the `regelwerk` option the current one applies
298
- (`AKTUELLES_REGELWERK`, currently 2: zero receipts carry a block
485
+ numbered rule set. Without the `ruleset` option the current one applies
486
+ (`CURRENT_LAYOUT_RULESET`, currently 2: zero receipts carry a block
299
487
  "Prüfangaben" with the registration data, which `getReceiptWithCompany`
300
- returns as `pruefangaben`). The backend stores the rule set with each receipt,
488
+ returns as `registrationInfo`). The backend stores the rule set with each receipt,
301
489
  and `getReceiptWithCompany` also returns the backend-built `layout` in that
302
490
  rule set, so an old receipt looks the way it did when it was issued.
303
491
 
492
+ **Print and show the server's layout.** `layout` in a `…WithCompany` result
493
+ is a `ReceiptLayout` (`ruleset`, banner lines with `tone: 'receipt_type' |
494
+ 'warning'`) and goes unchanged to `escPosLayoutBytes`, `eposPrintXml`,
495
+ `receiptSheet` and the React views; `receiptLayoutFromResult(result)` returns
496
+ it whenever it is there. Only without it does the helper build the layout,
497
+ in `fallbackPaperSize` (default `mm58`, as in 0.x). The server layout is
498
+ always 80 mm: on 58 mm paper choose the width at the print path
499
+ (`escPosLayoutBytes(layout, { paperSize: 'mm58' })`, `charsPerLine: 32`); the VAT
500
+ table then keeps the columns of the 80 mm grid. On the public channel only this layout carries the card block, because
501
+ the receipt itself comes without provider data. If you build the layout
502
+ yourself, pass the options from the same response:
503
+
504
+ ```ts
505
+ buildReceiptLayout(receipt, company, { paperSize: 'mm80', testCashregister, testSignature, registrationInfo });
506
+ ```
507
+
508
+ The options of 0.x (`testKasse`, `testSignatur`, `pruefangaben`,
509
+ `regelwerk`) are rejected with a `KasseneckValidationError` instead of being
510
+ ignored: a test receipt must never lose its "TESTKASSE" banner. The printed
511
+ text stays German, and the CSS classes of the React banner stay
512
+ `keck-receipt-banner--belegart` and `--warnung`.
513
+
304
514
  Times on receipts are read as **Vienna wall-clock time**
305
515
  (`parseServerTimeStamp`), never through `new Date(text)`.
306
516
 
@@ -311,9 +521,12 @@ A cancellation (*Storno*) refers to the original receipt, in full or in part:
311
521
  ```ts
312
522
  const result = await api.cancelReceipt({
313
523
  receipt: original, // or: cashregisterId + originalReceiptId
314
- reason: 'fehleingabe', // catalogue: CANCELLATION_REASONS
524
+ reason: 'input_error', // catalogue: CANCELLATION_REASONS
315
525
  items: [{ index: 0, quantity: 1 }], // omit = cancel all remaining quantities
316
526
  note: 'Customer only wanted one', // internal, stored, never printed
527
+ // Refund per original payment (negative, refundOf = id of that payment).
528
+ // Omit it and the server refunds the remainder of every original payment.
529
+ payments: [{ method: KeckPaymentMethod.cash, amountCents: -390, refundOf: 'p1' }],
317
530
  });
318
531
  result.receipt; // the signed cancellation receipt (receiptType cancellation)
319
532
  result.cancellationOf; // reference to the original
@@ -328,20 +541,20 @@ fully cancelled receipt cannot be cancelled again. On a receipt you have read,
328
541
  cancellation dialog); the server has the final word.
329
542
 
330
543
  Every business error of `cancelReceipt` carries `KasseneckApiError.code` from
331
- `CANCELLATION_ERROR_CODES` (for example `bereits_storniert`,
332
- `menge_ueber_rest`, `nur_eigene_belege`):
544
+ `CANCELLATION_ERROR_CODES` (for example `already_cancelled`,
545
+ `quantity_exceeds_remaining`, `own_receipts_only`):
333
546
 
334
547
  ```ts
335
548
  import { isKasseneckApiError, isCancellationErrorCode } from '@kreiseck/kasseneck-api';
336
549
 
337
550
  try {
338
- await api.cancelReceipt({ receipt: original, reason: 'fehleingabe' });
551
+ await api.cancelReceipt({ receipt: original, reason: 'input_error' });
339
552
  } catch (error) {
340
553
  if (!isKasseneckApiError(error) || !isCancellationErrorCode(error.code)) throw error;
341
554
  switch (error.code) {
342
- case 'bereits_storniert': // show the receipt as cancelled, disable the button
343
- case 'menge_ueber_rest': // reload the remaining quantities (someone was faster)
344
- case 'nur_eigene_belege': // ask a manager
555
+ case 'already_cancelled': // show the receipt as cancelled, disable the button
556
+ case 'quantity_exceeds_remaining': // reload the remaining quantities (someone was faster)
557
+ case 'own_receipts_only': // ask a manager
345
558
  showHint(error.code);
346
559
  break;
347
560
  default:
@@ -350,11 +563,14 @@ try {
350
563
  }
351
564
  ```
352
565
 
353
- **Deprecated:** `createCancelReceipt` (cancellation through `createReceipt`
354
- with freely passed, negated lines) remains available for compatibility but is
355
- `@deprecated`: no reference to the original, no remaining quantities, no
356
- protection against double cancellation, no voucher handling. The backend adds
357
- `deprecation` to its response on this path.
566
+ **Card refunds.** The terminal refund needs the transaction id of the original
567
+ card payment: `payments[].providerPaymentId` of the original receipt. Only the
568
+ register channel (`registerUserAuth`, `kasse.kasseneck.at/api/v3`) returns it;
569
+ the public channel leaves provider data out. The refund payment then carries
570
+ the id of the refund itself. `cancellation_outcome_unknown` means the
571
+ cancellation may have been booked: read the original again, never retry.
572
+
573
+ `createCancelReceipt` and cancelling through `createReceipt` are gone in 1.0.
358
574
 
359
575
  **Vouchers.** A value voucher is only mirrored on a full cancellation (without
360
576
  `items`); it cannot be split. A discount voucher is already part of the
@@ -378,11 +594,11 @@ it omit that line.
378
594
  const confirmation = await api.sendReceiptEmail({
379
595
  fullReceiptId: original.fullReceiptId, // or: await api.generateFullReceiptId(receiptId)
380
596
  to: 'guest@example.at',
381
- sprache: 'de', // optional; the backend currently only uses 'de'
597
+ language: 'de', // optional; the backend currently only uses 'de'
382
598
  });
383
599
  confirmation.to; // address as the backend logged it (trimmed, lower case)
384
600
  confirmation.at; // time, ISO with Vienna offset
385
- confirmation.via; // 'eigen' | 'plattform' | 'plattform-fallback' | null
601
+ confirmation.via; // 'own' | 'platform' | 'platform_fallback' | null
386
602
  ```
387
603
 
388
604
  The email contains a **link to the public receipt page**, not a PDF
@@ -394,8 +610,8 @@ The cash register comes from the authentication (`cashregister-token` header or
394
610
  the parameter set by `registerUserAuth`), not from the options. A receipt of
395
611
  another register therefore gets the same answer as a receipt that does not
396
612
  exist. The codes are in `RECEIPT_EMAIL_ERROR_CODES` (`isReceiptEmailErrorCode`):
397
- `adresse_ungueltig`, `beleg_nicht_gefunden`, `zu_oft` (5 emails per receipt in
398
- 24 hours, 30 per register per hour) and `versand_fehlgeschlagen`.
613
+ `invalid_address`, `receipt_not_found`, `too_many_requests` (5 emails per
614
+ receipt in 24 hours, 30 per register per hour) and `send_failed`.
399
615
 
400
616
  ## Receipt printing: QR code, logo, printers
401
617
 
@@ -408,34 +624,34 @@ receipt the worst possible result. So this package calculates the size instead
408
624
  of setting it:
409
625
 
410
626
  ```ts
411
- import { qrGroesseFuer, QR_DRUCK_PUNKTE } from '@kreiseck/kasseneck-api/printing';
627
+ import { qrSizingFor, QR_PRINT_WIDTH_DOTS } from '@kreiseck/kasseneck-api/printing';
412
628
 
413
- const qrSize = qrGroesseFuer({ nutzlast: receipt.qr, papierbreitePunkte: QR_DRUCK_PUNKTE.mm58 });
414
- // qrSize.punkte: dots per module; null = does not fit even with the exception size
415
- // qrSize.unterMindestmass: printed, but below 4 dots per module
629
+ const qrSize = qrSizingFor({ payload: receipt.qr, paperWidthDots: QR_PRINT_WIDTH_DOTS.mm58 });
630
+ // qrSize.moduleDots: dots per module; null = does not fit even with the exception size
631
+ // qrSize.belowMinimum: printed, but below 4 dots per module
416
632
  ```
417
633
 
418
- On the receipt path this happens automatically. `qrGroesse` is a **cap**, not
634
+ On the receipt path this happens automatically. `qrModuleSize` is a **cap**, not
419
635
  a target: the largest size that fits is printed, at most the cap. `auto` (the
420
636
  default) caps at 6 dots per module, as in the Dart twin and on the Epson path;
421
- `klein` caps at 4, `mittel` at 6, `gross` at 8. All print paths use error
637
+ `small` caps at 4, `medium` at 6, `large` at 8. All print paths use error
422
638
  correction level M.
423
639
 
424
640
  ```ts
425
- import { escPosLayoutErgebnis } from '@kreiseck/kasseneck-api/receipt';
641
+ import { escPosLayoutResult } from '@kreiseck/kasseneck-api/receipt';
426
642
 
427
- const { bytes, qrFehler, qrAusweich } = escPosLayoutErgebnis(layout, {
428
- qrGroesse: 'gross', // 'auto' | 'klein' | 'mittel' | 'gross'
429
- qrModus: 'nativeModel1', // older printers that only support model 1
643
+ const { bytes, qrError, qrFallback } = escPosLayoutResult(layout, {
644
+ qrModuleSize: 'large', // 'auto' | 'small' | 'medium' | 'large'
645
+ qrMode: 'nativeModel1', // older printers that only support model 1
430
646
  qrMatrix: matrixFor, // fallback: the QR code as an image instead of none
431
647
  });
432
648
  ```
433
649
 
434
650
  The Epson ePOS path (`eposPrintXml` / `eposDirectPrint`) calculates the same
435
- way; `eposPrintXmlErgebnis` returns `{ xml, qrFehler, qrAusweich }`. The default
651
+ way; `eposPrintXmlResult` returns `{ xml, qrError, qrFallback }`. The default
436
652
  there is also `auto`.
437
653
 
438
- `qrFehler` means "receipt without QR code": tell the customer. `qrAusweich`
654
+ `qrError` means "receipt without QR code": tell the customer. `qrFallback`
439
655
  means "printed, but the configured mode does not suit this device": tell the
440
656
  manager. The image fallback only runs with a `qrMatrix` function that turns
441
657
  the payload into a finished matrix; the package itself neither encodes QR
@@ -448,25 +664,26 @@ logo, QR code and the Kasseneck logo at the end, with sizes as a share of the
448
664
  sheet width and in lines (one line = two character widths).
449
665
 
450
666
  ```tsx
451
- import { BelegBlattView } from '@kreiseck/kasseneck-api/react';
667
+ import { ReceiptSheetView } from '@kreiseck/kasseneck-api/react';
452
668
 
453
- const { receipt, company, logoStufe } = await api.getReceiptWithCompany(receiptId);
454
- const layout = buildReceiptLayout(receipt, company);
669
+ const result = await api.getReceiptWithCompany(receiptId);
670
+ const { company, logoScale } = result;
671
+ const layout = receiptLayoutFromResult(result);
455
672
 
456
- <BelegBlattView
673
+ <ReceiptSheetView
457
674
  layout={layout}
458
- logo={company.logoUrl ? { url: company.logoUrl, stufe: logoStufe } : null}
459
- marke={company.showKreiseckLogo}
675
+ logo={company.logoUrl ? { url: company.logoUrl, size: logoScale } : null}
676
+ brandMark={company.showKreiseckLogo}
460
677
  renderQr={(data) => <QrSvg data={data} />}
461
678
  />
462
679
  ```
463
680
 
464
681
  ```ts
465
- import { escPosLayoutBytes, logoMass, logoRaster } from '@kreiseck/kasseneck-api/receipt';
682
+ import { escPosLayoutBytes, logoDimensions, rasterizeLogo } from '@kreiseck/kasseneck-api/receipt';
466
683
 
467
- const logoSize = logoMass({ stufe: 'M', pxBreite: image.width, pxHoehe: image.height }, 48);
468
- const raster = logoRaster(imageData.data, image.width, image.height, logoSize, 48);
469
- escPosLayoutBytes(layout, { paperSize: 'mm80', logo: { stufe: 'M', pxBreite: image.width, pxHoehe: image.height, raster }, marke: true });
684
+ const logoSize = logoDimensions({ size: 'M', pixelWidth: image.width, pixelHeight: image.height }, 48);
685
+ const raster = rasterizeLogo(imageData.data, image.width, image.height, logoSize, 48);
686
+ escPosLayoutBytes(layout, { paperSize: 'mm80', logo: { size: 'M', pixelWidth: image.width, pixelHeight: image.height, raster }, brandMark: true });
470
687
  ```
471
688
 
472
689
  Logo sizes: S 42 % × 5 lines, M 62 % × 8, L 80 % × 12, XL 94 % × 16, always
@@ -480,10 +697,91 @@ The package generates ESC/POS bytes and ePOS XML, and it ships three ways to
480
697
  deliver them: **WebUSB** (`usbConnectPrinter`, `usbPrint` in `…/printing`, for
481
698
  Chromium-based browsers), **Epson ePOS over HTTP** (`eposDirectPrint` in
482
699
  `…/receipt`) and **print jobs** for network printers managed by the backend
483
- (`listMyPrinters`, `createPrintJob` in `…/kasse`). Bluetooth, serial ports and
700
+ (`listMyPrinters`, `createPrintJob` in `…/pos`). Bluetooth, serial ports and
484
701
  raw TCP sockets are up to your application. PDF generation is not part of the
485
702
  package.
486
703
 
704
+ ## Register settings, articles and printers (`./pos`)
705
+
706
+ The calls of the tile register run on the register path and take a transport
707
+ from `createTransport` with the same options as `createKasseneckApi`.
708
+ Settings come as `{ business, device }` with English keys and values
709
+ (`theme: 'night'`, `receiptOutput: 'ask'`, `shortcuts.checkout`), merged with
710
+ the defaults `POS_BUSINESS_DEFAULTS` and `POS_DEVICE_DEFAULTS`.
711
+
712
+ **Send only what changed.** The server merges deeply, so a write carries only
713
+ the changed fields. `posSettingsChanges(before, after)` computes them; it sends
714
+ `vatRates` and `shortcuts` as whole maps, which is what the server expects:
715
+
716
+ ```ts
717
+ import { createTransport, registerUserAuth } from '@kreiseck/kasseneck-api';
718
+ import { getPosSettings, setMyPosSettings, posSettingsChanges, isPosError, posFieldErrors } from '@kreiseck/kasseneck-api/pos';
719
+
720
+ const transport = createTransport({ auth: registerUserAuth({ getIdToken, getSessionId, cashregisterId }), posBaseUrl: '/api/v3' });
721
+
722
+ const before = await getPosSettings(transport);
723
+ const after = { ...before.business, theme: 'night' as const, fontSize: 'L' as const };
724
+ try {
725
+ await setMyPosSettings(transport, posSettingsChanges(before.business, after));
726
+ } catch (error) {
727
+ if (isPosError(error, 'validation')) showFieldErrors(posFieldErrors(error)); // [{ field: 'business.color', message }]
728
+ else throw error;
729
+ }
730
+ ```
731
+
732
+ Never send back the whole merged block. A value the server knows and this
733
+ version does not (`theme: 'sepia'`) is read and kept as it is;
734
+ `unknownPosSettingValues(settings)` names such paths, so the interface can show
735
+ them as not editable. Left unchanged, such a value is not sent and stays on the
736
+ server; inside a whole block it would be rejected before sending. The same
737
+ check rejects unknown keys (also the German keys of 0.x such as `stil`),
738
+ values outside a field's list, a `vatRates` map without any rate switched on,
739
+ unknown shortcut actions and a key bound twice (`posShortcutConflict`).
740
+ Per-device settings go through `setMyRegisterDeviceSettings(transport, deviceId,
741
+ changes)`.
742
+
743
+ A state you stored yourself (for example settings cached in `localStorage`)
744
+ goes through `sanitizePosSettings` or `mergePosSettings` first: both drop the
745
+ German values of 0.x, so an old cache falls back to the defaults instead of
746
+ sending a German value.
747
+
748
+ The rest of `…/pos`: `listMyArticles` and `listMyArticleGroups` for the tiles
749
+ (`visible`, `quantityRule: 'piece' | 'decimal'`, `askQuantity`,
750
+ `maxQuantity`), `listMyPrinters`, `createPrintJob` and `getPrintJob` for
751
+ network printers (poll until `isPrintJobFinished(job)`; an unknown state is
752
+ `'unknown'` and ends the polling), `listMyTipRecipients`, `setMyPosLogo`, and
753
+ the register's text catalogue (`MESSAGES`, `LABELS`, `messageText`,
754
+ `labelText`). Text keys are English (`cancellation.outcome_unknown`,
755
+ `split.add_payment`), and so are the placeholders:
756
+ `messageText('checkout.locked', { reason })`. The rendered German texts are
757
+ the same as in 0.x.
758
+
759
+ ## Stored documents (`./stored`)
760
+
761
+ For clients that read Firestore directly, such as the admin panel. Stored
762
+ documents keep the internal German form; `…/stored` turns them into the same
763
+ English models the `/v3` wire returns, following the server's own rules
764
+ (layout rule set, logo size, `TESTKASSE` banner, the settings merge):
765
+
766
+ ```ts
767
+ import { fromStoredReceiptWithCompany, fromStoredPosSettings, invalidStoredPosSettings } from '@kreiseck/kasseneck-api/stored';
768
+
769
+ // The header version the receipt names (receipt.headerVersionId), plus the account document.
770
+ const result = fromStoredReceiptWithCompany(receiptDoc, {
771
+ headerVersion: { id: headerDoc.id, data: headerDoc.data() },
772
+ account: accountDoc.data(),
773
+ });
774
+ receiptLayoutFromResult(result); // the same layout getReceiptWithCompany returns
775
+
776
+ const settings = fromStoredPosSettings({ betrieb, geraet }); // stored register settings
777
+ invalidStoredPosSettings({ betrieb, geraet }); // paths the server would drop
778
+ ```
779
+
780
+ `fromStoredReceipt`, `fromStoredCompany` and `fromStoredArticle` complete the
781
+ set. A broken document throws a `KasseneckValidationError`. There is no
782
+ reader for stored invoices: the server computes the invoice view, so read it
783
+ with `getInvoice` and `listInvoices`.
784
+
487
785
  ## Card payments
488
786
 
489
787
  `…/payments` covers three ways to take card payments from a browser or a Node
@@ -538,22 +836,23 @@ The partner key (`pk_live_…`) belongs on a **server**. It can create
538
836
  businesses and, with the extra scope `credentials:read`, fetch their secrets.
539
837
 
540
838
  This subpath talks to the English Partner API **`/v3`**
541
- (`PARTNER_BASE_URL`, `https://api.kasseneck.at/v3`): every field name and
542
- every value your code branches on is English, including every error code
543
- (`PARTNER_FEHLER_CODES`). Texts for humans (`message`, `note`, `statusText`,
544
- `nextSteps`) stay German. Everything else in this package (receipts,
545
- invoices, the register, printing, payments) still uses `/v1`
546
- (`DEFAULT_BASE_URL`) until those endpoints have a `/v3` of their own.
839
+ (`PARTNER_BASE_URL`, `https://api.kasseneck.at/v3`) like the rest of the
840
+ package: every field name and every value your code branches on is English,
841
+ including every error code (`PARTNER_ERROR_CODES`, and
842
+ `PARTNER_REQUEST_ERROR_CODES` for rejected keys and scopes). Texts for humans
843
+ (`message`, `note`, `statusText`, `nextSteps`) stay German.
844
+ `partner.errorAdvice(code)` always returns a sentence, with a general fallback
845
+ for a code this version does not know.
547
846
 
548
847
  ```ts
549
- import { createPartnerApi, istPartnerFehler } from '@kreiseck/kasseneck-api/partner';
848
+ import { createPartnerApi, isPartnerError } from '@kreiseck/kasseneck-api/partner';
550
849
 
551
850
  const partner = createPartnerApi({ partnerKey: process.env.KASSENECK_PARTNER_KEY! });
552
851
 
553
852
  const { customerId } = await partner.createPartnerCustomer({
554
853
  appId: 'app_…',
555
854
  idempotencyKey: customerNumber, // your own number; protects against duplicates
556
- business, // master data (type Betrieb): legalForm 'sole_proprietor', state 'AT-5', …
855
+ business, // master data (type Business): legalForm 'sole_proprietor', state 'AT-5', …
557
856
  // env: 'test' is allowed even with a LIVE key: that is how you rehearse the
558
857
  // whole chain without a second key. Never the other way round.
559
858
  });
@@ -566,20 +865,29 @@ await partner.createCustomerCashregister({ customerId }); // automatic: true is
566
865
  ```
567
866
 
568
867
  The order is strict, and each step complains with its own code if an earlier
569
- one is missing. The order ships as data (`PARTNER_ABLAUF`), and for every code
868
+ one is missing. The order ships as data (`PARTNER_FLOW`), and for every code
570
869
  there is an action hint:
571
870
 
572
871
  ```ts
573
872
  try {
574
873
  await partner.activateCashregister(customerId, cashregisterId);
575
874
  } catch (error) {
576
- if (istPartnerFehler(error, 'signature_not_ready')) {
875
+ if (isPartnerError(error, 'signature_not_ready')) {
577
876
  // The signature of THIS register is not ready yet: wait for signature.ready.
578
- console.error(partner.fehlerRat('signature_not_ready'));
877
+ console.error(partner.errorAdvice('signature_not_ready'));
579
878
  }
580
879
  }
581
880
  ```
582
881
 
882
+ `reportCustomerContract` reports a contract the business accepted through
883
+ the partner (terms of use or data processing agreement, with the text version
884
+ and its hash).
885
+
886
+ The two migration notes below are history from the 0.x line and use the names
887
+ of their time (`PARTNER_FEHLER_CODES`, `partnerFehlerRat`, the aliases
888
+ `Rechtsform`, `Bundesland`, `KontaktRolle`). For the move to 1.0 see
889
+ [Migrating from 0.x](#migrating-from-0x).
890
+
583
891
  ### Migrating from 0.27.x
584
892
 
585
893
  0.28.0 is a breaking change for `./partner` only. The client now calls `/v3`
@@ -722,7 +1030,7 @@ app.post('/kasseneck-webhook', express.raw({ type: '*/*' }), async (req, res) =>
722
1030
  });
723
1031
  ```
724
1032
 
725
- ## Invoice API (`./rechnung`)
1033
+ ## Invoice API (`./invoice`)
726
1034
 
727
1035
  For shops, accounting and industry software: issue **invoices** (*Rechnung*,
728
1036
  § 11 UStG), not receipts, with the `api_key` of an account. An invoice is
@@ -730,9 +1038,9 @@ For shops, accounting and industry software: issue **invoices** (*Rechnung*,
730
1038
  and can only be corrected by a credit note. The key belongs on a **server**.
731
1039
 
732
1040
  ```ts
733
- import { createRechnungApi, istRechnungFehler } from '@kreiseck/kasseneck-api/rechnung';
1041
+ import { createInvoiceApi, isInvoiceError } from '@kreiseck/kasseneck-api/invoice';
734
1042
 
735
- const invoices = createRechnungApi({ apiKey: process.env.KASSENECK_API_KEY! });
1043
+ const invoices = createInvoiceApi({ apiKey: process.env.KASSENECK_API_KEY! });
736
1044
 
737
1045
  // 1. Create the customer once; externalId is your own customer number.
738
1046
  let customer;
@@ -743,7 +1051,7 @@ try {
743
1051
  externalId: 'shop-4711',
744
1052
  });
745
1053
  } catch (error) {
746
- if (!istRechnungFehler(error, 'customer_exists')) throw error;
1054
+ if (!isInvoiceError(error, 'customer_exists')) throw error;
747
1055
  customer = await invoices.getCustomer({ externalId: 'shop-4711' });
748
1056
  }
749
1057
 
@@ -759,7 +1067,7 @@ const { invoice, replayed } = await invoices.issueInvoice({
759
1067
 
760
1068
  // 3. Fetch the files.
761
1069
  const pdf = await invoices.getInvoicePdf(invoice.id); // Uint8Array, with Factur-X
762
- const xml = await invoices.getInvoiceXml(invoice.id, 'ubl'); // Peppol UBL as text
1070
+ const { xml, filename } = await invoices.getInvoiceXml(invoice.id, 'ubl'); // Peppol UBL, filename invoice-<number>.xml
763
1071
 
764
1072
  // 4. Correct, only by credit note.
765
1073
  await invoices.createCreditNote({
@@ -811,13 +1119,13 @@ const copy = await invoices.getInvoicePdf(invoice.id, { language: 'de' });
811
1119
  The translated copy carries the same number, is marked on every page as a
812
1120
  translation that is not an invoice of its own ("Übersetzung – keine eigene
813
1121
  Rechnung"), and has no embedded e-invoice. The texts of both languages ship as
814
- `RECHNUNG_TEXTE` and `fixtures/rechnung-texte.json`.
1122
+ `INVOICE_TEXTS` and `fixtures/invoice-texts.json`.
815
1123
 
816
1124
  **Units are keys, not free text.** `items[].unit` takes a value from
817
1125
  `INVOICE_UNITS` (`piece`, `hour`, `day`, `flat_rate`, `kilogram`,
818
1126
  `square_metre`, …; default `piece`). The printed abbreviation follows the
819
1127
  invoice language (`Stk` or `pcs`), and the e-invoice carries the UN/ECE code
820
- from `RECHNUNG_EINHEITEN_CODES` (`C62`, `HUR`, …). Free text such as `"Std"` is
1128
+ from `INVOICE_UNIT_CODES` (`C62`, `HUR`, …). Free text such as `"Std"` is
821
1129
  a `validation` error on field `items[0].unit`.
822
1130
 
823
1131
  **Already paid?** If you take the payment online and invoice afterwards, pass
@@ -849,8 +1157,23 @@ invoice anyway.
849
1157
  `onSite`:
850
1158
 
851
1159
  ```ts
852
- payment: { method: 'card', onSite: true } // terminal at the point of sale
853
- payment: { method: 'card' } // card payment in the online shop
1160
+ // Terminal at the point of sale: a cash sale.
1161
+ await invoices.issueInvoice({
1162
+ idempotencyKey: `counter-${orderNumber}`,
1163
+ customerId: customer.id,
1164
+ priceMode: 'gross', serviceStart: '2026-09-16',
1165
+ items: [{ description: 'Coffee beans 1 kg', quantity: 1, unitPriceCents: 2490, vatRate: 10, unit: 'piece' }],
1166
+ payment: { method: 'card', onSite: true },
1167
+ });
1168
+
1169
+ // Card payment in the online shop: not a cash sale, so no onSite.
1170
+ await invoices.issueInvoice({
1171
+ idempotencyKey: `shop-${orderNumber}`,
1172
+ customerId: customer.id,
1173
+ priceMode: 'gross', serviceStart: '2026-09-16',
1174
+ items: [{ description: 'Coffee beans 1 kg', quantity: 1, unitPriceCents: 2490, vatRate: 10, unit: 'piece' }],
1175
+ payment: { method: 'card', reference: payment.id },
1176
+ });
854
1177
  ```
855
1178
 
856
1179
  For those cases the response's `notice` list contains `cash_receipt_required`:
@@ -869,9 +1192,9 @@ you then get the invoice that was already issued (`replayed: true`). The same
869
1192
  key with different data gives `idempotency_conflict`.
870
1193
 
871
1194
  Validation errors arrive as `validation` with field paths
872
- (`rechnungFeldFehler(error)` → `[{ field: 'items[0].vatRate', message }]`).
873
- The contract itself ships as data (`RECHNUNG_ANFRAGEN`) and as a JSON Schema at
874
- `@kreiseck/kasseneck-api/fixtures/rechnung-api.schema.json`; the backend
1195
+ (`invoiceFieldErrors(error)` → `[{ field: 'items[0].vatRate', message }]`).
1196
+ The contract itself ships as data (`INVOICE_REQUESTS`) and as a JSON Schema at
1197
+ `@kreiseck/kasseneck-api/fixtures/invoice-api.schema.json`; the backend
875
1198
  validates against exactly this file.
876
1199
 
877
1200
  ### Calculating invoice totals in advance
@@ -893,7 +1216,7 @@ const { preview, notice } = await invoices.previewInvoice(request);
893
1216
  await invoices.issueInvoice(request);
894
1217
  ```
895
1218
 
896
- **Without the server.** `@kreiseck/kasseneck-api/rechnung/rechnen` is the pure
1219
+ **Without the server.** `@kreiseck/kasseneck-api/invoice/calc` is the pure
897
1220
  calculation core: no transport, no key, runs in the browser too. It calculates
898
1221
  with integers (BigInt) instead of floating point and rounds exactly once per
899
1222
  VAT rate. Prices are in micro-euros (`unitPriceMicros`), quantities in
@@ -901,19 +1224,19 @@ thousandths (`quantityMilli`), discount and VAT rate in hundredths of a
901
1224
  percent (`discountBp`, `vatRateBp`):
902
1225
 
903
1226
  ```ts
904
- import { rechnungRechnen, positionAusEuro } from '@kreiseck/kasseneck-api/rechnung/rechnen';
1227
+ import { calculateInvoice, itemFromEuro } from '@kreiseck/kasseneck-api/invoice/calc';
905
1228
 
906
- rechnungRechnen(
1229
+ calculateInvoice(
907
1230
  [{ unitPriceMicros: 14_790_000, quantityMilli: 1000, vatRateBp: 2000 }],
908
1231
  { priceMode: 'gross' },
909
1232
  );
910
1233
  // { netCents: 1233, vatCents: 246, grossCents: 1479, byRate: [{ rateBp: 2000, … }], lines: […] }
911
1234
 
912
- positionAusEuro({ unitPrice: 14.79, quantity: 1, vatRate: 20 });
1235
+ itemFromEuro({ unitPrice: 14.79, quantity: 1, vatRate: 20 });
913
1236
  // { ok: true, position: { unitPriceMicros: 14790000, quantityMilli: 1000, discountBp: 0, vatRateBp: 2000 } }
914
1237
  ```
915
1238
 
916
- `positionAusEuro(item)` converts a euro line (`unitPrice`, `quantity`,
1239
+ `itemFromEuro(item)` converts a euro line (`unitPrice`, `quantity`,
917
1240
  `vatRate`, `discountPct`) into this form without loss, or names the field and
918
1241
  the reason when that is not possible. Since 23 September 2026 the server
919
1242
  calculates every new invoice with this core. In **gross mode** the gross amount
@@ -921,17 +1244,47 @@ per rate is the agreed price: net = round(gross × 100 / (100 + rate)),
921
1244
  VAT = gross − net. In **net mode** the VAT per rate is rounded from the net
922
1245
  sum. Rounding is commercial (half a cent rounds away from zero). Totals are
923
1246
  positive for credit notes too; the sign is in the document type
924
- (`docType: 'GU'`). Test cases: `fixtures/rechnung-rechnen.json`,
925
- `fixtures/rechnung-rechnen-zufall.json`, `fixtures/position-aus-euro.json`.
1247
+ (`docType: 'credit_note'`). Test cases: `fixtures/invoice-calc.json`,
1248
+ `fixtures/invoice-calc-random.json`, `fixtures/item-from-euro.json`.
926
1249
 
927
- **`rechnungSummen` is deprecated.** The older helper in `…/rechnung` works on
1250
+ **`computeInvoiceTotals` is deprecated.** The older helper in `…/invoice` works on
928
1251
  `unitPriceCents` lines with the previous floating-point formula and does not
929
1252
  run through the core. At half-cent boundaries it can differ from an invoice
930
1253
  issued today by one cent per VAT rate, and by a few cents across several
931
- rates. Example: € 21.35 net at 10 % gives € 23.48 gross with `rechnungSummen`,
1254
+ rates. Example: € 21.35 net at 10 % gives € 23.48 gross with `computeInvoiceTotals`,
932
1255
  but € 23.49 with the core and on the invoice. It stays unchanged for existing
933
- callers; use `rechnungRechnen` or `previewInvoice` in new code. Test cases for
934
- the old formula: `fixtures/rechnung-summen.json`.
1256
+ callers; use `calculateInvoice` or `previewInvoice` in new code. Test cases for
1257
+ the old formula: `fixtures/invoice-totals.json`.
1258
+
1259
+ ## Migrating from 0.x
1260
+
1261
+ 1.0 is one breaking step: the wire, the exported names and the contract files
1262
+ all become English at once. The full list is in the
1263
+ [CHANGELOG](https://github.com/kreiseck-at/kasseneck-api/blob/main/CHANGELOG.md#100);
1264
+ the fixture renames are machine-readable in `fixtures/renames-1.0.json`. The
1265
+ short version:
1266
+
1267
+ - **Wire.** Only `/v3`: `api.kasseneck.at/v3` and `kasse.kasseneck.at/api/v3`.
1268
+ A `baseUrl` ending in `/v1` or `/api` throws. `baseUrl` now covers public
1269
+ calls only; whoever passed it to pairing, sign-in or register calls (the
1270
+ browser register used `/api`) switches to `posBaseUrl: '/api/v3'`.
1271
+ - **Payments.** `payments[]` is mandatory; `paymentMethod`,
1272
+ `createCancelReceipt` and cancelling through `createReceipt` are gone.
1273
+ `receiptDueCents` needs `tipRecipient` for a tip without recipients.
1274
+ - **Outcome.** Check `isOutcomeUnknown(error)` before any retry of a sale or
1275
+ cancellation.
1276
+ - **Names.** German export names are English (`KASSE_BASE_URL` is
1277
+ `POS_BASE_URL`, `mergeKasseSettings` is `mergePosSettings`,
1278
+ `rechnungRechnen` is `calculateInvoice`, …), and so are field names, values
1279
+ and error codes. There are no aliases.
1280
+ - **Subpaths.** `./kasse` is `./pos`, `./rechnung` is `./invoice`,
1281
+ `./rechnung/rechnen` is `./invoice/calc`; `./stored` is new.
1282
+ - **Texts.** Catalogue keys and placeholders are English
1283
+ (`storno.ergebnis_unklar` is `cancellation.outcome_unknown`, `{betrag}` is
1284
+ `{amount}`); every rendered text is byte for byte the same.
1285
+
1286
+ 0.x stays on `/v1` and gets fixes only, published under the npm dist-tag `legacy`
1287
+ (`npm install @kreiseck/kasseneck-api@legacy`).
935
1288
 
936
1289
  ## Development
937
1290
 
@@ -953,18 +1306,20 @@ address returns the HTML fallback page instead of the function, and no mock
953
1306
  sees that.
954
1307
 
955
1308
  The check needs **no credentials**. A call without authentication answers,
956
- when there is a function behind it, with
957
- `{"status":"error","message":"Ungültiger Request: Authorization key erwartet."}`.
958
- That is the proof: the call was accepted and authentication was checked. An
959
- HTML page or a 404 proves that there is no function. That is why the script
960
- looks for a `status` field and not for success.
1309
+ when there is a function behind it, with an error envelope (`status` field)
1310
+ and the header `Kasseneck-Api-Version: v3`. That is the proof: the call was
1311
+ accepted and authentication was checked. An HTML page, a 404 or a missing
1312
+ marker proves that there is no `/v3` function. That is why the script looks
1313
+ for the envelope and the marker, not for success. Each call is asked at the
1314
+ address the transport really picks for it: public calls at
1315
+ `api.kasseneck.at/v3`, register-only calls at `kasse.kasseneck.at/api/v3`.
961
1316
 
962
1317
  It is deliberately outside `npm test` because it needs the network. Without a
963
- network it says so and exits with 0. Calls that deliberately have no rewrite
964
- under `/v1` (the register path via `kasse.kasseneck.at/api`, the calls with an
965
- ID token) are listed with a reason in `scripts/erreichbarkeit-ausnahmen.json`.
966
- If an exception becomes reachable, the check fails; otherwise the list would
967
- never shrink.
1318
+ network it says so and exits with 0. CI runs the local part on every push;
1319
+ the network part runs daily. A call that deliberately has no function would be
1320
+ listed with a reason in `scripts/erreichbarkeit-ausnahmen.json`; since 1.0 that
1321
+ list is empty. If an exception becomes reachable, the check fails; otherwise
1322
+ the list would never shrink.
968
1323
 
969
1324
  ## Contract files for the twin packages
970
1325
 
@@ -974,19 +1329,24 @@ in machine form what both sides agreed on, among them:
974
1329
 
975
1330
  | File | Contents | Generated by |
976
1331
  |---|---|---|
977
- | `kasse-settings-standard.json` | field names and defaults of the register settings | `npm run fixtures:kasse` |
978
- | `oberflaeche.json` | call names, enum values, permission keys, key actions, partner lists | `npm run fixtures:oberflaeche` |
1332
+ | `pos-settings-defaults.json` | field names and defaults of the register settings as sent on `/api/v3` (`business`, `device`), derived from the backend contract in `fixtures/v3/` | `npm run fixtures:kasse` |
1333
+ | `stored/pos-settings-defaults.json` | the same defaults in the stored (internal, German) form (`betrieb`, `geraet`) | `npm run fixtures:kasse` |
1334
+ | `surface.json` | base URLs (`baseUrls.public`, `baseUrls.pos`), the calls per path (`calls`, and the backend's `routes`), settings value lists (`enums`, keyed by field), other register lists (`pos`), register error codes, permission keys, shortcut actions, partner and invoice lists | `npm run fixtures:oberflaeche` |
979
1335
  | `hobex-hps-codes.json` | measured HPS result codes, their meaning and whether they settle an outcome (the contract behind `isConclusive`) | `npm run fixtures:hobex-hps-codes` |
980
- | `kasse-texte.json` | the register's message catalogue | `npm run fixtures:texte` |
981
- | `rechnung-texte.json` | invoice texts in both languages | `npm run fixtures:rechnungstexte` |
982
- | `rechnung-api.schema.json` | JSON Schema of the invoice API | `npm run fixtures:rechnung` |
1336
+ | `pos-texts.json` | the register's message catalogue | `npm run fixtures:texte` |
1337
+ | `invoice-texts.json` | invoice texts in both languages | `npm run fixtures:rechnungstexte` |
1338
+ | `invoice-api.schema.json` | JSON Schema of the invoice API | `npm run fixtures:rechnung` |
1339
+ | `pos-message-cases.json` | error cases and the message each one must show in both registers | by hand |
1340
+ | `receipt-due-generated.json` | 1206 amounts due computed by the backend's own code, the reference for `receiptDueCents` | `node scripts/v3-zahlbetrag-generieren.mjs` |
1341
+ | `v3/` | the backend's `/v3` contract (vocabulary, response cases, stored cases, amounts due), copied byte for byte | `node scripts/v3-vertrag-holen.mjs` |
1342
+ | `renames-1.0.json` | everything in these files that changed from 0.x to 1.0: paths (`files`), text catalogue keys (`texts`), placeholders, structural keys (`structure`), machine values (`values`), shape changes (`shapes`); rendered texts are unchanged | `npm run fixtures:umbenennung` |
983
1343
 
984
1344
  They are generated and never edited by hand. CI regenerates the register
985
- settings and `oberflaeche.json` and fails if they differ from the committed
1345
+ settings and `surface.json` and fails if they differ from the committed
986
1346
  files; the test suite checks the others against the code.
987
1347
 
988
- `oberflaeche.json`, `hobex-hps-codes.json`, `kasse-texte.json` and
989
- `rechnung-texte.json` carry the package version. **After every `npm version`,
1348
+ `surface.json`, `hobex-hps-codes.json`, `pos-texts.json` and
1349
+ `invoice-texts.json` carry the package version. **After every `npm version`,
990
1350
  regenerate them and commit them along**, otherwise the tests fail.
991
1351
 
992
1352
  ### And the other direction