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

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 +317 -0
  2. package/README.de.md +11 -7
  3. package/README.md +509 -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 +94 -19
  13. package/dist/cjs/client/errors.js +132 -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 +196 -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 +234 -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 +11 -3
  94. package/dist/cjs/payments/hobex.js +17 -5
  95. package/dist/cjs/payments/stripe.d.ts +5 -2
  96. package/dist/cjs/payments/stripe.js +10 -5
  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 +94 -19
  174. package/dist/esm/client/errors.js +129 -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 +195 -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 +233 -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 +11 -3
  255. package/dist/esm/payments/hobex.js +18 -6
  256. package/dist/esm/payments/stripe.d.ts +5 -2
  257. package/dist/esm/payments/stripe.js +11 -6
  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,106 @@ 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 operation with an effect is left open: no
431
+ receipt was signed, nothing went to FinanzOnline and no money moved, so
432
+ retrying the same request does not create a second receipt or charge (whether
433
+ it helps depends on the code). `'unknown'` means the operation **may have been carried out**, for
434
+ `createReceipt` a signed receipt in the chain. Then never send it again: read
435
+ the result back (`getReceipt`, `listMyReceipts`, the original of a
436
+ cancellation) and continue from there. `isOutcomeUnknown(error)` covers all
437
+ three classes. The outcome is unknown for:
438
+
439
+ - `dialect_mismatch`, `receipt_outcome_unknown`, `cancellation_outcome_unknown`;
440
+ - `response_translation_failed`, unless `details.handled === false`;
441
+ - `response_unreadable`: a signing or money-moving call reported success,
442
+ but the response lacks what the call promises (no receipt, no reference, no
443
+ remaining quantities, no Hobex receipt, no captured payment intent);
444
+ - on the calls with an effect: the signing calls `createReceipt`,
445
+ `cancelReceipt` and `financeWebService`, and the money calls `hobexPay`
446
+ (`hobexPayApi`, charges a card), `hobexRefund` (`hobexRefundApi`) and
447
+ `stripeCaptureIntent`: a network error or timeout after sending began, HTTP
448
+ 5xx, and HTTP 200 with the `Kasseneck-Api-Version: v3` marker but an empty,
449
+ non-JSON (also `text/html`) or status-less body (`KasseneckHttpError`,
450
+ `reason` `empty-body`, `not-json` or `missing-status`). HTML without the
451
+ marker stays `route_missing` with `'rejected'`: no function saw the call.
452
+
453
+ On the money calls an unknown outcome means the card may have been charged,
454
+ the refund may have gone through, the payment may have been captured. A
455
+ rejection of `hobexRefund` throws a `KasseneckApiError` with its `code`; it
456
+ never returns `false`, because a `false` on an unclear outcome invites a
457
+ second refund.
458
+
459
+ **Never retry these six calls, and never put a retrying layer under the
460
+ package.** A `fetch` passed in `options.fetch` (or a proxy or service worker in
461
+ front of it) must not resend a request by itself after a network error, a
462
+ timeout or a 5xx: a silent second send is a second signed receipt, a second
463
+ charge or a second refund, and the package cannot see it. Look the result up
464
+ instead (`getReceipt`, `listMyReceipts`, the Hobex transaction by its
465
+ `transactionId`, the Stripe session).
466
+
467
+ `outcome` only covers signing and the money calls. After a network error on
468
+ `issueInvoice` an invoice may still have been issued; retry it with the same
469
+ `idempotencyKey`.
470
+
471
+ ```ts
472
+ import { isOutcomeUnknown, paymentsExpectedCents } from '@kreiseck/kasseneck-api';
473
+
474
+ try {
475
+ await api.sellReceipt({ items, payments });
476
+ } catch (error) {
477
+ if (isOutcomeUnknown(error)) return reloadReceiptsAndAsk(); // never sell again blindly
478
+ const expected = paymentsExpectedCents(error); // payments_sum_mismatch
479
+ if (expected !== undefined) return askAgain(expected);
480
+ throw error;
481
+ }
482
+ ```
286
483
 
287
484
  ## Receipts
288
485
 
@@ -290,17 +487,48 @@ The facade from `createKasseneckApi` offers `sellReceipt` and
290
487
  `sellReceiptWithCompany`, `zeroReceipt` for a zero receipt (*Nullbeleg*),
291
488
  `getReceipt` and `getReceiptWithCompany`, `listMyReceipts`, `cancelReceipt`,
292
489
  `sendReceiptEmail`, the report downloads, the FinanzOnline status queries
293
- (`getCashboxStatus`, `getSignatureStatus`) and the Stripe and Hobex cloud
490
+ (`getCashboxStatus`, `getSignatureStatus`), `getReportV2({ start, end })` for
491
+ the raw receipts and company data of a period, and the Stripe and Hobex cloud
294
492
  payments.
295
493
 
494
+ The models are English throughout: the company has `taxNumber` and `vatId`, a
495
+ receipt `headerVersionId`, `layoutRuleset` and `registrationInfo`, a receipt
496
+ in the list `cancellationStatus` (`none`, `partial`, `full`, or `'unknown'` for
497
+ a value this version does not know: then offer no cancellation). The same
498
+ rule holds for print job states and register settings: a value the package
499
+ does not know is shown as `'unknown'` or kept as sent, never mapped onto a
500
+ known one.
501
+
296
502
  **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
503
+ numbered rule set. Without the `ruleset` option the current one applies
504
+ (`CURRENT_LAYOUT_RULESET`, currently 2: zero receipts carry a block
299
505
  "Prüfangaben" with the registration data, which `getReceiptWithCompany`
300
- returns as `pruefangaben`). The backend stores the rule set with each receipt,
506
+ returns as `registrationInfo`). The backend stores the rule set with each receipt,
301
507
  and `getReceiptWithCompany` also returns the backend-built `layout` in that
302
508
  rule set, so an old receipt looks the way it did when it was issued.
303
509
 
510
+ **Print and show the server's layout.** `layout` in a `…WithCompany` result
511
+ is a `ReceiptLayout` (`ruleset`, banner lines with `tone: 'receipt_type' |
512
+ 'warning'`) and goes unchanged to `escPosLayoutBytes`, `eposPrintXml`,
513
+ `receiptSheet` and the React views; `receiptLayoutFromResult(result)` returns
514
+ it whenever it is there. Only without it does the helper build the layout,
515
+ in `fallbackPaperSize` (default `mm58`, as in 0.x). The server layout is
516
+ always 80 mm: on 58 mm paper choose the width at the print path
517
+ (`escPosLayoutBytes(layout, { paperSize: 'mm58' })`, `charsPerLine: 32`); the VAT
518
+ table then keeps the columns of the 80 mm grid. On the public channel only this layout carries the card block, because
519
+ the receipt itself comes without provider data. If you build the layout
520
+ yourself, pass the options from the same response:
521
+
522
+ ```ts
523
+ buildReceiptLayout(receipt, company, { paperSize: 'mm80', testCashregister, testSignature, registrationInfo });
524
+ ```
525
+
526
+ The options of 0.x (`testKasse`, `testSignatur`, `pruefangaben`,
527
+ `regelwerk`) are rejected with a `KasseneckValidationError` instead of being
528
+ ignored: a test receipt must never lose its "TESTKASSE" banner. The printed
529
+ text stays German, and the CSS classes of the React banner stay
530
+ `keck-receipt-banner--belegart` and `--warnung`.
531
+
304
532
  Times on receipts are read as **Vienna wall-clock time**
305
533
  (`parseServerTimeStamp`), never through `new Date(text)`.
306
534
 
@@ -311,9 +539,12 @@ A cancellation (*Storno*) refers to the original receipt, in full or in part:
311
539
  ```ts
312
540
  const result = await api.cancelReceipt({
313
541
  receipt: original, // or: cashregisterId + originalReceiptId
314
- reason: 'fehleingabe', // catalogue: CANCELLATION_REASONS
542
+ reason: 'input_error', // catalogue: CANCELLATION_REASONS
315
543
  items: [{ index: 0, quantity: 1 }], // omit = cancel all remaining quantities
316
544
  note: 'Customer only wanted one', // internal, stored, never printed
545
+ // Refund per original payment (negative, refundOf = id of that payment).
546
+ // Omit it and the server refunds the remainder of every original payment.
547
+ payments: [{ method: KeckPaymentMethod.cash, amountCents: -390, refundOf: 'p1' }],
317
548
  });
318
549
  result.receipt; // the signed cancellation receipt (receiptType cancellation)
319
550
  result.cancellationOf; // reference to the original
@@ -328,20 +559,20 @@ fully cancelled receipt cannot be cancelled again. On a receipt you have read,
328
559
  cancellation dialog); the server has the final word.
329
560
 
330
561
  Every business error of `cancelReceipt` carries `KasseneckApiError.code` from
331
- `CANCELLATION_ERROR_CODES` (for example `bereits_storniert`,
332
- `menge_ueber_rest`, `nur_eigene_belege`):
562
+ `CANCELLATION_ERROR_CODES` (for example `already_cancelled`,
563
+ `quantity_exceeds_remaining`, `own_receipts_only`):
333
564
 
334
565
  ```ts
335
566
  import { isKasseneckApiError, isCancellationErrorCode } from '@kreiseck/kasseneck-api';
336
567
 
337
568
  try {
338
- await api.cancelReceipt({ receipt: original, reason: 'fehleingabe' });
569
+ await api.cancelReceipt({ receipt: original, reason: 'input_error' });
339
570
  } catch (error) {
340
571
  if (!isKasseneckApiError(error) || !isCancellationErrorCode(error.code)) throw error;
341
572
  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
573
+ case 'already_cancelled': // show the receipt as cancelled, disable the button
574
+ case 'quantity_exceeds_remaining': // reload the remaining quantities (someone was faster)
575
+ case 'own_receipts_only': // ask a manager
345
576
  showHint(error.code);
346
577
  break;
347
578
  default:
@@ -350,11 +581,14 @@ try {
350
581
  }
351
582
  ```
352
583
 
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.
584
+ **Card refunds.** The terminal refund needs the transaction id of the original
585
+ card payment: `payments[].providerPaymentId` of the original receipt. Only the
586
+ register channel (`registerUserAuth`, `kasse.kasseneck.at/api/v3`) returns it;
587
+ the public channel leaves provider data out. The refund payment then carries
588
+ the id of the refund itself. `cancellation_outcome_unknown` means the
589
+ cancellation may have been booked: read the original again, never retry.
590
+
591
+ `createCancelReceipt` and cancelling through `createReceipt` are gone in 1.0.
358
592
 
359
593
  **Vouchers.** A value voucher is only mirrored on a full cancellation (without
360
594
  `items`); it cannot be split. A discount voucher is already part of the
@@ -378,11 +612,11 @@ it omit that line.
378
612
  const confirmation = await api.sendReceiptEmail({
379
613
  fullReceiptId: original.fullReceiptId, // or: await api.generateFullReceiptId(receiptId)
380
614
  to: 'guest@example.at',
381
- sprache: 'de', // optional; the backend currently only uses 'de'
615
+ language: 'de', // optional; the backend currently only uses 'de'
382
616
  });
383
617
  confirmation.to; // address as the backend logged it (trimmed, lower case)
384
618
  confirmation.at; // time, ISO with Vienna offset
385
- confirmation.via; // 'eigen' | 'plattform' | 'plattform-fallback' | null
619
+ confirmation.via; // 'own' | 'platform' | 'platform_fallback' | null
386
620
  ```
387
621
 
388
622
  The email contains a **link to the public receipt page**, not a PDF
@@ -394,8 +628,8 @@ The cash register comes from the authentication (`cashregister-token` header or
394
628
  the parameter set by `registerUserAuth`), not from the options. A receipt of
395
629
  another register therefore gets the same answer as a receipt that does not
396
630
  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`.
631
+ `invalid_address`, `receipt_not_found`, `too_many_requests` (5 emails per
632
+ receipt in 24 hours, 30 per register per hour) and `send_failed`.
399
633
 
400
634
  ## Receipt printing: QR code, logo, printers
401
635
 
@@ -408,34 +642,34 @@ receipt the worst possible result. So this package calculates the size instead
408
642
  of setting it:
409
643
 
410
644
  ```ts
411
- import { qrGroesseFuer, QR_DRUCK_PUNKTE } from '@kreiseck/kasseneck-api/printing';
645
+ import { qrSizingFor, QR_PRINT_WIDTH_DOTS } from '@kreiseck/kasseneck-api/printing';
412
646
 
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
647
+ const qrSize = qrSizingFor({ payload: receipt.qr, paperWidthDots: QR_PRINT_WIDTH_DOTS.mm58 });
648
+ // qrSize.moduleDots: dots per module; null = does not fit even with the exception size
649
+ // qrSize.belowMinimum: printed, but below 4 dots per module
416
650
  ```
417
651
 
418
- On the receipt path this happens automatically. `qrGroesse` is a **cap**, not
652
+ On the receipt path this happens automatically. `qrModuleSize` is a **cap**, not
419
653
  a target: the largest size that fits is printed, at most the cap. `auto` (the
420
654
  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
655
+ `small` caps at 4, `medium` at 6, `large` at 8. All print paths use error
422
656
  correction level M.
423
657
 
424
658
  ```ts
425
- import { escPosLayoutErgebnis } from '@kreiseck/kasseneck-api/receipt';
659
+ import { escPosLayoutResult } from '@kreiseck/kasseneck-api/receipt';
426
660
 
427
- const { bytes, qrFehler, qrAusweich } = escPosLayoutErgebnis(layout, {
428
- qrGroesse: 'gross', // 'auto' | 'klein' | 'mittel' | 'gross'
429
- qrModus: 'nativeModel1', // older printers that only support model 1
661
+ const { bytes, qrError, qrFallback } = escPosLayoutResult(layout, {
662
+ qrModuleSize: 'large', // 'auto' | 'small' | 'medium' | 'large'
663
+ qrMode: 'nativeModel1', // older printers that only support model 1
430
664
  qrMatrix: matrixFor, // fallback: the QR code as an image instead of none
431
665
  });
432
666
  ```
433
667
 
434
668
  The Epson ePOS path (`eposPrintXml` / `eposDirectPrint`) calculates the same
435
- way; `eposPrintXmlErgebnis` returns `{ xml, qrFehler, qrAusweich }`. The default
669
+ way; `eposPrintXmlResult` returns `{ xml, qrError, qrFallback }`. The default
436
670
  there is also `auto`.
437
671
 
438
- `qrFehler` means "receipt without QR code": tell the customer. `qrAusweich`
672
+ `qrError` means "receipt without QR code": tell the customer. `qrFallback`
439
673
  means "printed, but the configured mode does not suit this device": tell the
440
674
  manager. The image fallback only runs with a `qrMatrix` function that turns
441
675
  the payload into a finished matrix; the package itself neither encodes QR
@@ -448,25 +682,26 @@ logo, QR code and the Kasseneck logo at the end, with sizes as a share of the
448
682
  sheet width and in lines (one line = two character widths).
449
683
 
450
684
  ```tsx
451
- import { BelegBlattView } from '@kreiseck/kasseneck-api/react';
685
+ import { ReceiptSheetView } from '@kreiseck/kasseneck-api/react';
452
686
 
453
- const { receipt, company, logoStufe } = await api.getReceiptWithCompany(receiptId);
454
- const layout = buildReceiptLayout(receipt, company);
687
+ const result = await api.getReceiptWithCompany(receiptId);
688
+ const { company, logoScale } = result;
689
+ const layout = receiptLayoutFromResult(result);
455
690
 
456
- <BelegBlattView
691
+ <ReceiptSheetView
457
692
  layout={layout}
458
- logo={company.logoUrl ? { url: company.logoUrl, stufe: logoStufe } : null}
459
- marke={company.showKreiseckLogo}
693
+ logo={company.logoUrl ? { url: company.logoUrl, size: logoScale } : null}
694
+ brandMark={company.showKreiseckLogo}
460
695
  renderQr={(data) => <QrSvg data={data} />}
461
696
  />
462
697
  ```
463
698
 
464
699
  ```ts
465
- import { escPosLayoutBytes, logoMass, logoRaster } from '@kreiseck/kasseneck-api/receipt';
700
+ import { escPosLayoutBytes, logoDimensions, rasterizeLogo } from '@kreiseck/kasseneck-api/receipt';
466
701
 
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 });
702
+ const logoSize = logoDimensions({ size: 'M', pixelWidth: image.width, pixelHeight: image.height }, 48);
703
+ const raster = rasterizeLogo(imageData.data, image.width, image.height, logoSize, 48);
704
+ escPosLayoutBytes(layout, { paperSize: 'mm80', logo: { size: 'M', pixelWidth: image.width, pixelHeight: image.height, raster }, brandMark: true });
470
705
  ```
471
706
 
472
707
  Logo sizes: S 42 % × 5 lines, M 62 % × 8, L 80 % × 12, XL 94 % × 16, always
@@ -480,10 +715,91 @@ The package generates ESC/POS bytes and ePOS XML, and it ships three ways to
480
715
  deliver them: **WebUSB** (`usbConnectPrinter`, `usbPrint` in `…/printing`, for
481
716
  Chromium-based browsers), **Epson ePOS over HTTP** (`eposDirectPrint` in
482
717
  `…/receipt`) and **print jobs** for network printers managed by the backend
483
- (`listMyPrinters`, `createPrintJob` in `…/kasse`). Bluetooth, serial ports and
718
+ (`listMyPrinters`, `createPrintJob` in `…/pos`). Bluetooth, serial ports and
484
719
  raw TCP sockets are up to your application. PDF generation is not part of the
485
720
  package.
486
721
 
722
+ ## Register settings, articles and printers (`./pos`)
723
+
724
+ The calls of the tile register run on the register path and take a transport
725
+ from `createTransport` with the same options as `createKasseneckApi`.
726
+ Settings come as `{ business, device }` with English keys and values
727
+ (`theme: 'night'`, `receiptOutput: 'ask'`, `shortcuts.checkout`), merged with
728
+ the defaults `POS_BUSINESS_DEFAULTS` and `POS_DEVICE_DEFAULTS`.
729
+
730
+ **Send only what changed.** The server merges deeply, so a write carries only
731
+ the changed fields. `posSettingsChanges(before, after)` computes them; it sends
732
+ `vatRates` and `shortcuts` as whole maps, which is what the server expects:
733
+
734
+ ```ts
735
+ import { createTransport, registerUserAuth } from '@kreiseck/kasseneck-api';
736
+ import { getPosSettings, setMyPosSettings, posSettingsChanges, isPosError, posFieldErrors } from '@kreiseck/kasseneck-api/pos';
737
+
738
+ const transport = createTransport({ auth: registerUserAuth({ getIdToken, getSessionId, cashregisterId }), posBaseUrl: '/api/v3' });
739
+
740
+ const before = await getPosSettings(transport);
741
+ const after = { ...before.business, theme: 'night' as const, fontSize: 'L' as const };
742
+ try {
743
+ await setMyPosSettings(transport, posSettingsChanges(before.business, after));
744
+ } catch (error) {
745
+ if (isPosError(error, 'validation')) showFieldErrors(posFieldErrors(error)); // [{ field: 'business.color', message }]
746
+ else throw error;
747
+ }
748
+ ```
749
+
750
+ Never send back the whole merged block. A value the server knows and this
751
+ version does not (`theme: 'sepia'`) is read and kept as it is;
752
+ `unknownPosSettingValues(settings)` names such paths, so the interface can show
753
+ them as not editable. Left unchanged, such a value is not sent and stays on the
754
+ server; inside a whole block it would be rejected before sending. The same
755
+ check rejects unknown keys (also the German keys of 0.x such as `stil`),
756
+ values outside a field's list, a `vatRates` map without any rate switched on,
757
+ unknown shortcut actions and a key bound twice (`posShortcutConflict`).
758
+ Per-device settings go through `setMyRegisterDeviceSettings(transport, deviceId,
759
+ changes)`.
760
+
761
+ A state you stored yourself (for example settings cached in `localStorage`)
762
+ goes through `sanitizePosSettings` or `mergePosSettings` first: both drop the
763
+ German values of 0.x, so an old cache falls back to the defaults instead of
764
+ sending a German value.
765
+
766
+ The rest of `…/pos`: `listMyArticles` and `listMyArticleGroups` for the tiles
767
+ (`visible`, `quantityRule: 'piece' | 'decimal'`, `askQuantity`,
768
+ `maxQuantity`), `listMyPrinters`, `createPrintJob` and `getPrintJob` for
769
+ network printers (poll until `isPrintJobFinished(job)`; an unknown state is
770
+ `'unknown'` and ends the polling), `listMyTipRecipients`, `setMyPosLogo`, and
771
+ the register's text catalogue (`MESSAGES`, `LABELS`, `messageText`,
772
+ `labelText`). Text keys are English (`cancellation.outcome_unknown`,
773
+ `split.add_payment`), and so are the placeholders:
774
+ `messageText('checkout.locked', { reason })`. The rendered German texts are
775
+ the same as in 0.x.
776
+
777
+ ## Stored documents (`./stored`)
778
+
779
+ For clients that read Firestore directly, such as the admin panel. Stored
780
+ documents keep the internal German form; `…/stored` turns them into the same
781
+ English models the `/v3` wire returns, following the server's own rules
782
+ (layout rule set, logo size, `TESTKASSE` banner, the settings merge):
783
+
784
+ ```ts
785
+ import { fromStoredReceiptWithCompany, fromStoredPosSettings, invalidStoredPosSettings } from '@kreiseck/kasseneck-api/stored';
786
+
787
+ // The header version the receipt names (receipt.headerVersionId), plus the account document.
788
+ const result = fromStoredReceiptWithCompany(receiptDoc, {
789
+ headerVersion: { id: headerDoc.id, data: headerDoc.data() },
790
+ account: accountDoc.data(),
791
+ });
792
+ receiptLayoutFromResult(result); // the same layout getReceiptWithCompany returns
793
+
794
+ const settings = fromStoredPosSettings({ betrieb, geraet }); // stored register settings
795
+ invalidStoredPosSettings({ betrieb, geraet }); // paths the server would drop
796
+ ```
797
+
798
+ `fromStoredReceipt`, `fromStoredCompany` and `fromStoredArticle` complete the
799
+ set. A broken document throws a `KasseneckValidationError`. There is no
800
+ reader for stored invoices: the server computes the invoice view, so read it
801
+ with `getInvoice` and `listInvoices`.
802
+
487
803
  ## Card payments
488
804
 
489
805
  `…/payments` covers three ways to take card payments from a browser or a Node
@@ -494,6 +810,11 @@ process:
494
810
  - **Hobex cloud** (`hobexPay`, `hobexRefund`): a terminal registered with
495
811
  Hobex, controlled over the network through the backend. Amounts are passed in
496
812
  cents; the package converts to euros for Hobex.
813
+
814
+ `hobexPay`, `hobexRefund` and `stripeCaptureIntent` move money. They are never
815
+ retried, neither by the app nor by a retrying `fetch` under the package: on
816
+ `isOutcomeUnknown(error)` look the payment up (see
817
+ [`outcome: 'unknown'`](#outcome-unknown-never-retry-look-it-up)).
497
818
  - **Hobex HPS via Kasseneck Connect**, described below.
498
819
 
499
820
  ### Hobex HPS via Kasseneck Connect
@@ -538,22 +859,23 @@ The partner key (`pk_live_…`) belongs on a **server**. It can create
538
859
  businesses and, with the extra scope `credentials:read`, fetch their secrets.
539
860
 
540
861
  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.
862
+ (`PARTNER_BASE_URL`, `https://api.kasseneck.at/v3`) like the rest of the
863
+ package: every field name and every value your code branches on is English,
864
+ including every error code (`PARTNER_ERROR_CODES`, and
865
+ `PARTNER_REQUEST_ERROR_CODES` for rejected keys and scopes). Texts for humans
866
+ (`message`, `note`, `statusText`, `nextSteps`) stay German.
867
+ `partner.errorAdvice(code)` always returns a sentence, with a general fallback
868
+ for a code this version does not know.
547
869
 
548
870
  ```ts
549
- import { createPartnerApi, istPartnerFehler } from '@kreiseck/kasseneck-api/partner';
871
+ import { createPartnerApi, isPartnerError } from '@kreiseck/kasseneck-api/partner';
550
872
 
551
873
  const partner = createPartnerApi({ partnerKey: process.env.KASSENECK_PARTNER_KEY! });
552
874
 
553
875
  const { customerId } = await partner.createPartnerCustomer({
554
876
  appId: 'app_…',
555
877
  idempotencyKey: customerNumber, // your own number; protects against duplicates
556
- business, // master data (type Betrieb): legalForm 'sole_proprietor', state 'AT-5', …
878
+ business, // master data (type Business): legalForm 'sole_proprietor', state 'AT-5', …
557
879
  // env: 'test' is allowed even with a LIVE key: that is how you rehearse the
558
880
  // whole chain without a second key. Never the other way round.
559
881
  });
@@ -566,20 +888,29 @@ await partner.createCustomerCashregister({ customerId }); // automatic: true is
566
888
  ```
567
889
 
568
890
  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
891
+ one is missing. The order ships as data (`PARTNER_FLOW`), and for every code
570
892
  there is an action hint:
571
893
 
572
894
  ```ts
573
895
  try {
574
896
  await partner.activateCashregister(customerId, cashregisterId);
575
897
  } catch (error) {
576
- if (istPartnerFehler(error, 'signature_not_ready')) {
898
+ if (isPartnerError(error, 'signature_not_ready')) {
577
899
  // The signature of THIS register is not ready yet: wait for signature.ready.
578
- console.error(partner.fehlerRat('signature_not_ready'));
900
+ console.error(partner.errorAdvice('signature_not_ready'));
579
901
  }
580
902
  }
581
903
  ```
582
904
 
905
+ `reportCustomerContract` reports a contract the business accepted through
906
+ the partner (terms of use or data processing agreement, with the text version
907
+ and its hash).
908
+
909
+ The two migration notes below are history from the 0.x line and use the names
910
+ of their time (`PARTNER_FEHLER_CODES`, `partnerFehlerRat`, the aliases
911
+ `Rechtsform`, `Bundesland`, `KontaktRolle`). For the move to 1.0 see
912
+ [Migrating from 0.x](#migrating-from-0x).
913
+
583
914
  ### Migrating from 0.27.x
584
915
 
585
916
  0.28.0 is a breaking change for `./partner` only. The client now calls `/v3`
@@ -722,7 +1053,7 @@ app.post('/kasseneck-webhook', express.raw({ type: '*/*' }), async (req, res) =>
722
1053
  });
723
1054
  ```
724
1055
 
725
- ## Invoice API (`./rechnung`)
1056
+ ## Invoice API (`./invoice`)
726
1057
 
727
1058
  For shops, accounting and industry software: issue **invoices** (*Rechnung*,
728
1059
  § 11 UStG), not receipts, with the `api_key` of an account. An invoice is
@@ -730,9 +1061,9 @@ For shops, accounting and industry software: issue **invoices** (*Rechnung*,
730
1061
  and can only be corrected by a credit note. The key belongs on a **server**.
731
1062
 
732
1063
  ```ts
733
- import { createRechnungApi, istRechnungFehler } from '@kreiseck/kasseneck-api/rechnung';
1064
+ import { createInvoiceApi, isInvoiceError } from '@kreiseck/kasseneck-api/invoice';
734
1065
 
735
- const invoices = createRechnungApi({ apiKey: process.env.KASSENECK_API_KEY! });
1066
+ const invoices = createInvoiceApi({ apiKey: process.env.KASSENECK_API_KEY! });
736
1067
 
737
1068
  // 1. Create the customer once; externalId is your own customer number.
738
1069
  let customer;
@@ -743,7 +1074,7 @@ try {
743
1074
  externalId: 'shop-4711',
744
1075
  });
745
1076
  } catch (error) {
746
- if (!istRechnungFehler(error, 'customer_exists')) throw error;
1077
+ if (!isInvoiceError(error, 'customer_exists')) throw error;
747
1078
  customer = await invoices.getCustomer({ externalId: 'shop-4711' });
748
1079
  }
749
1080
 
@@ -759,7 +1090,7 @@ const { invoice, replayed } = await invoices.issueInvoice({
759
1090
 
760
1091
  // 3. Fetch the files.
761
1092
  const pdf = await invoices.getInvoicePdf(invoice.id); // Uint8Array, with Factur-X
762
- const xml = await invoices.getInvoiceXml(invoice.id, 'ubl'); // Peppol UBL as text
1093
+ const { xml, filename } = await invoices.getInvoiceXml(invoice.id, 'ubl'); // Peppol UBL, filename invoice-<number>.xml
763
1094
 
764
1095
  // 4. Correct, only by credit note.
765
1096
  await invoices.createCreditNote({
@@ -811,13 +1142,13 @@ const copy = await invoices.getInvoicePdf(invoice.id, { language: 'de' });
811
1142
  The translated copy carries the same number, is marked on every page as a
812
1143
  translation that is not an invoice of its own ("Übersetzung – keine eigene
813
1144
  Rechnung"), and has no embedded e-invoice. The texts of both languages ship as
814
- `RECHNUNG_TEXTE` and `fixtures/rechnung-texte.json`.
1145
+ `INVOICE_TEXTS` and `fixtures/invoice-texts.json`.
815
1146
 
816
1147
  **Units are keys, not free text.** `items[].unit` takes a value from
817
1148
  `INVOICE_UNITS` (`piece`, `hour`, `day`, `flat_rate`, `kilogram`,
818
1149
  `square_metre`, …; default `piece`). The printed abbreviation follows the
819
1150
  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
1151
+ from `INVOICE_UNIT_CODES` (`C62`, `HUR`, …). Free text such as `"Std"` is
821
1152
  a `validation` error on field `items[0].unit`.
822
1153
 
823
1154
  **Already paid?** If you take the payment online and invoice afterwards, pass
@@ -849,8 +1180,23 @@ invoice anyway.
849
1180
  `onSite`:
850
1181
 
851
1182
  ```ts
852
- payment: { method: 'card', onSite: true } // terminal at the point of sale
853
- payment: { method: 'card' } // card payment in the online shop
1183
+ // Terminal at the point of sale: a cash sale.
1184
+ await invoices.issueInvoice({
1185
+ idempotencyKey: `counter-${orderNumber}`,
1186
+ customerId: customer.id,
1187
+ priceMode: 'gross', serviceStart: '2026-09-16',
1188
+ items: [{ description: 'Coffee beans 1 kg', quantity: 1, unitPriceCents: 2490, vatRate: 10, unit: 'piece' }],
1189
+ payment: { method: 'card', onSite: true },
1190
+ });
1191
+
1192
+ // Card payment in the online shop: not a cash sale, so no onSite.
1193
+ await invoices.issueInvoice({
1194
+ idempotencyKey: `shop-${orderNumber}`,
1195
+ customerId: customer.id,
1196
+ priceMode: 'gross', serviceStart: '2026-09-16',
1197
+ items: [{ description: 'Coffee beans 1 kg', quantity: 1, unitPriceCents: 2490, vatRate: 10, unit: 'piece' }],
1198
+ payment: { method: 'card', reference: payment.id },
1199
+ });
854
1200
  ```
855
1201
 
856
1202
  For those cases the response's `notice` list contains `cash_receipt_required`:
@@ -869,9 +1215,9 @@ you then get the invoice that was already issued (`replayed: true`). The same
869
1215
  key with different data gives `idempotency_conflict`.
870
1216
 
871
1217
  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
1218
+ (`invoiceFieldErrors(error)` → `[{ field: 'items[0].vatRate', message }]`).
1219
+ The contract itself ships as data (`INVOICE_REQUESTS`) and as a JSON Schema at
1220
+ `@kreiseck/kasseneck-api/fixtures/invoice-api.schema.json`; the backend
875
1221
  validates against exactly this file.
876
1222
 
877
1223
  ### Calculating invoice totals in advance
@@ -893,7 +1239,7 @@ const { preview, notice } = await invoices.previewInvoice(request);
893
1239
  await invoices.issueInvoice(request);
894
1240
  ```
895
1241
 
896
- **Without the server.** `@kreiseck/kasseneck-api/rechnung/rechnen` is the pure
1242
+ **Without the server.** `@kreiseck/kasseneck-api/invoice/calc` is the pure
897
1243
  calculation core: no transport, no key, runs in the browser too. It calculates
898
1244
  with integers (BigInt) instead of floating point and rounds exactly once per
899
1245
  VAT rate. Prices are in micro-euros (`unitPriceMicros`), quantities in
@@ -901,19 +1247,19 @@ thousandths (`quantityMilli`), discount and VAT rate in hundredths of a
901
1247
  percent (`discountBp`, `vatRateBp`):
902
1248
 
903
1249
  ```ts
904
- import { rechnungRechnen, positionAusEuro } from '@kreiseck/kasseneck-api/rechnung/rechnen';
1250
+ import { calculateInvoice, itemFromEuro } from '@kreiseck/kasseneck-api/invoice/calc';
905
1251
 
906
- rechnungRechnen(
1252
+ calculateInvoice(
907
1253
  [{ unitPriceMicros: 14_790_000, quantityMilli: 1000, vatRateBp: 2000 }],
908
1254
  { priceMode: 'gross' },
909
1255
  );
910
1256
  // { netCents: 1233, vatCents: 246, grossCents: 1479, byRate: [{ rateBp: 2000, … }], lines: […] }
911
1257
 
912
- positionAusEuro({ unitPrice: 14.79, quantity: 1, vatRate: 20 });
1258
+ itemFromEuro({ unitPrice: 14.79, quantity: 1, vatRate: 20 });
913
1259
  // { ok: true, position: { unitPriceMicros: 14790000, quantityMilli: 1000, discountBp: 0, vatRateBp: 2000 } }
914
1260
  ```
915
1261
 
916
- `positionAusEuro(item)` converts a euro line (`unitPrice`, `quantity`,
1262
+ `itemFromEuro(item)` converts a euro line (`unitPrice`, `quantity`,
917
1263
  `vatRate`, `discountPct`) into this form without loss, or names the field and
918
1264
  the reason when that is not possible. Since 23 September 2026 the server
919
1265
  calculates every new invoice with this core. In **gross mode** the gross amount
@@ -921,17 +1267,47 @@ per rate is the agreed price: net = round(gross × 100 / (100 + rate)),
921
1267
  VAT = gross − net. In **net mode** the VAT per rate is rounded from the net
922
1268
  sum. Rounding is commercial (half a cent rounds away from zero). Totals are
923
1269
  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`.
1270
+ (`docType: 'credit_note'`). Test cases: `fixtures/invoice-calc.json`,
1271
+ `fixtures/invoice-calc-random.json`, `fixtures/item-from-euro.json`.
926
1272
 
927
- **`rechnungSummen` is deprecated.** The older helper in `…/rechnung` works on
1273
+ **`computeInvoiceTotals` is deprecated.** The older helper in `…/invoice` works on
928
1274
  `unitPriceCents` lines with the previous floating-point formula and does not
929
1275
  run through the core. At half-cent boundaries it can differ from an invoice
930
1276
  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`,
1277
+ rates. Example: € 21.35 net at 10 % gives € 23.48 gross with `computeInvoiceTotals`,
932
1278
  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`.
1279
+ callers; use `calculateInvoice` or `previewInvoice` in new code. Test cases for
1280
+ the old formula: `fixtures/invoice-totals.json`.
1281
+
1282
+ ## Migrating from 0.x
1283
+
1284
+ 1.0 is one breaking step: the wire, the exported names and the contract files
1285
+ all become English at once. The full list is in the
1286
+ [CHANGELOG](https://github.com/kreiseck-at/kasseneck-api/blob/main/CHANGELOG.md#100);
1287
+ the fixture renames are machine-readable in `fixtures/renames-1.0.json`. The
1288
+ short version:
1289
+
1290
+ - **Wire.** Only `/v3`: `api.kasseneck.at/v3` and `kasse.kasseneck.at/api/v3`.
1291
+ A `baseUrl` ending in `/v1` or `/api` throws. `baseUrl` now covers public
1292
+ calls only; whoever passed it to pairing, sign-in or register calls (the
1293
+ browser register used `/api`) switches to `posBaseUrl: '/api/v3'`.
1294
+ - **Payments.** `payments[]` is mandatory; `paymentMethod`,
1295
+ `createCancelReceipt` and cancelling through `createReceipt` are gone.
1296
+ `receiptDueCents` needs `tipRecipient` for a tip without recipients.
1297
+ - **Outcome.** Check `isOutcomeUnknown(error)` before any retry of a sale or
1298
+ cancellation.
1299
+ - **Names.** German export names are English (`KASSE_BASE_URL` is
1300
+ `POS_BASE_URL`, `mergeKasseSettings` is `mergePosSettings`,
1301
+ `rechnungRechnen` is `calculateInvoice`, …), and so are field names, values
1302
+ and error codes. There are no aliases.
1303
+ - **Subpaths.** `./kasse` is `./pos`, `./rechnung` is `./invoice`,
1304
+ `./rechnung/rechnen` is `./invoice/calc`; `./stored` is new.
1305
+ - **Texts.** Catalogue keys and placeholders are English
1306
+ (`storno.ergebnis_unklar` is `cancellation.outcome_unknown`, `{betrag}` is
1307
+ `{amount}`); every rendered text is byte for byte the same.
1308
+
1309
+ 0.x stays on `/v1` and gets fixes only, published under the npm dist-tag `legacy`
1310
+ (`npm install @kreiseck/kasseneck-api@legacy`).
935
1311
 
936
1312
  ## Development
937
1313
 
@@ -953,18 +1329,20 @@ address returns the HTML fallback page instead of the function, and no mock
953
1329
  sees that.
954
1330
 
955
1331
  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.
1332
+ when there is a function behind it, with an error envelope (`status` field)
1333
+ and the header `Kasseneck-Api-Version: v3`. That is the proof: the call was
1334
+ accepted and authentication was checked. An HTML page, a 404 or a missing
1335
+ marker proves that there is no `/v3` function. That is why the script looks
1336
+ for the envelope and the marker, not for success. Each call is asked at the
1337
+ address the transport really picks for it: public calls at
1338
+ `api.kasseneck.at/v3`, register-only calls at `kasse.kasseneck.at/api/v3`.
961
1339
 
962
1340
  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.
1341
+ network it says so and exits with 0. CI runs the local part on every push;
1342
+ the network part runs daily. A call that deliberately has no function would be
1343
+ listed with a reason in `scripts/erreichbarkeit-ausnahmen.json`; since 1.0 that
1344
+ list is empty. If an exception becomes reachable, the check fails; otherwise
1345
+ the list would never shrink.
968
1346
 
969
1347
  ## Contract files for the twin packages
970
1348
 
@@ -974,19 +1352,24 @@ in machine form what both sides agreed on, among them:
974
1352
 
975
1353
  | File | Contents | Generated by |
976
1354
  |---|---|---|
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` |
1355
+ | `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` |
1356
+ | `stored/pos-settings-defaults.json` | the same defaults in the stored (internal, German) form (`betrieb`, `geraet`) | `npm run fixtures:kasse` |
1357
+ | `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
1358
  | `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` |
1359
+ | `pos-texts.json` | the register's message catalogue | `npm run fixtures:texte` |
1360
+ | `invoice-texts.json` | invoice texts in both languages | `npm run fixtures:rechnungstexte` |
1361
+ | `invoice-api.schema.json` | JSON Schema of the invoice API | `npm run fixtures:rechnung` |
1362
+ | `pos-message-cases.json` | error cases and the message each one must show in both registers | by hand |
1363
+ | `receipt-due-generated.json` | 1206 amounts due computed by the backend's own code, the reference for `receiptDueCents` | `node scripts/v3-zahlbetrag-generieren.mjs` |
1364
+ | `v3/` | the backend's `/v3` contract (vocabulary, response cases, stored cases, amounts due), copied byte for byte | `node scripts/v3-vertrag-holen.mjs` |
1365
+ | `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
1366
 
984
1367
  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
1368
+ settings and `surface.json` and fails if they differ from the committed
986
1369
  files; the test suite checks the others against the code.
987
1370
 
988
- `oberflaeche.json`, `hobex-hps-codes.json`, `kasse-texte.json` and
989
- `rechnung-texte.json` carry the package version. **After every `npm version`,
1371
+ `surface.json`, `hobex-hps-codes.json`, `pos-texts.json` and
1372
+ `invoice-texts.json` carry the package version. **After every `npm version`,
990
1373
  regenerate them and commit them along**, otherwise the tests fail.
991
1374
 
992
1375
  ### And the other direction