@kreiseck/kasseneck-api 0.6.7

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 (294) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +2 -0
  3. package/README.md +206 -0
  4. package/dist/cjs/client/api.d.ts +75 -0
  5. package/dist/cjs/client/api.js +40 -0
  6. package/dist/cjs/client/auth.d.ts +52 -0
  7. package/dist/cjs/client/auth.js +72 -0
  8. package/dist/cjs/client/cashregisters.d.ts +21 -0
  9. package/dist/cjs/client/cashregisters.js +36 -0
  10. package/dist/cjs/client/errors.d.ts +159 -0
  11. package/dist/cjs/client/errors.js +226 -0
  12. package/dist/cjs/client/index.d.ts +8 -0
  13. package/dist/cjs/client/index.js +44 -0
  14. package/dist/cjs/client/receipts.d.ts +245 -0
  15. package/dist/cjs/client/receipts.js +452 -0
  16. package/dist/cjs/client/reports.d.ts +43 -0
  17. package/dist/cjs/client/reports.js +73 -0
  18. package/dist/cjs/client/status.d.ts +43 -0
  19. package/dist/cjs/client/status.js +47 -0
  20. package/dist/cjs/client/transport.d.ts +117 -0
  21. package/dist/cjs/client/transport.js +312 -0
  22. package/dist/cjs/enums/credit-card-provider.d.ts +22 -0
  23. package/dist/cjs/enums/credit-card-provider.js +23 -0
  24. package/dist/cjs/enums/define-enum.d.ts +15 -0
  25. package/dist/cjs/enums/define-enum.js +16 -0
  26. package/dist/cjs/enums/index.d.ts +7 -0
  27. package/dist/cjs/enums/index.js +17 -0
  28. package/dist/cjs/enums/keck-payment-method.d.ts +57 -0
  29. package/dist/cjs/enums/keck-payment-method.js +23 -0
  30. package/dist/cjs/enums/receipt-type.d.ts +41 -0
  31. package/dist/cjs/enums/receipt-type.js +18 -0
  32. package/dist/cjs/enums/stripe-link-mode.d.ts +17 -0
  33. package/dist/cjs/enums/stripe-link-mode.js +18 -0
  34. package/dist/cjs/enums/vat-rate.d.ts +40 -0
  35. package/dist/cjs/enums/vat-rate.js +19 -0
  36. package/dist/cjs/enums/voucher-action.d.ts +10 -0
  37. package/dist/cjs/enums/voucher-action.js +11 -0
  38. package/dist/cjs/enums/voucher-type.d.ts +9 -0
  39. package/dist/cjs/enums/voucher-type.js +10 -0
  40. package/dist/cjs/index.d.ts +5 -0
  41. package/dist/cjs/index.js +97 -0
  42. package/dist/cjs/kasse/artikel.d.ts +83 -0
  43. package/dist/cjs/kasse/artikel.js +79 -0
  44. package/dist/cjs/kasse/client.d.ts +10 -0
  45. package/dist/cjs/kasse/client.js +38 -0
  46. package/dist/cjs/kasse/drucker.d.ts +54 -0
  47. package/dist/cjs/kasse/drucker.js +41 -0
  48. package/dist/cjs/kasse/index.d.ts +11 -0
  49. package/dist/cjs/kasse/index.js +38 -0
  50. package/dist/cjs/kasse/settings.d.ts +115 -0
  51. package/dist/cjs/kasse/settings.js +62 -0
  52. package/dist/cjs/models/cancellation.d.ts +51 -0
  53. package/dist/cjs/models/cancellation.js +45 -0
  54. package/dist/cjs/models/cashregister.d.ts +77 -0
  55. package/dist/cjs/models/cashregister.js +53 -0
  56. package/dist/cjs/models/enum-payload.d.ts +26 -0
  57. package/dist/cjs/models/enum-payload.js +50 -0
  58. package/dist/cjs/models/hobex-receipt.d.ts +63 -0
  59. package/dist/cjs/models/hobex-receipt.js +86 -0
  60. package/dist/cjs/models/index.d.ts +10 -0
  61. package/dist/cjs/models/index.js +46 -0
  62. package/dist/cjs/models/receipt-company.d.ts +71 -0
  63. package/dist/cjs/models/receipt-company.js +52 -0
  64. package/dist/cjs/models/receipt-item.d.ts +100 -0
  65. package/dist/cjs/models/receipt-item.js +108 -0
  66. package/dist/cjs/models/receipt-summary.d.ts +92 -0
  67. package/dist/cjs/models/receipt-summary.js +54 -0
  68. package/dist/cjs/models/receipt.d.ts +108 -0
  69. package/dist/cjs/models/receipt.js +119 -0
  70. package/dist/cjs/models/report-month.d.ts +32 -0
  71. package/dist/cjs/models/report-month.js +65 -0
  72. package/dist/cjs/models/stripe-url-session.d.ts +18 -0
  73. package/dist/cjs/models/stripe-url-session.js +20 -0
  74. package/dist/cjs/models/voucher.d.ts +41 -0
  75. package/dist/cjs/models/voucher.js +56 -0
  76. package/dist/cjs/money.d.ts +23 -0
  77. package/dist/cjs/money.js +35 -0
  78. package/dist/cjs/package.json +1 -0
  79. package/dist/cjs/payments/hobex.d.ts +87 -0
  80. package/dist/cjs/payments/hobex.js +167 -0
  81. package/dist/cjs/payments/index.d.ts +33 -0
  82. package/dist/cjs/payments/index.js +42 -0
  83. package/dist/cjs/payments/stripe.d.ts +61 -0
  84. package/dist/cjs/payments/stripe.js +157 -0
  85. package/dist/cjs/printing/escpos.d.ts +219 -0
  86. package/dist/cjs/printing/escpos.js +636 -0
  87. package/dist/cjs/printing/index.d.ts +3 -0
  88. package/dist/cjs/printing/index.js +33 -0
  89. package/dist/cjs/printing/printable.d.ts +27 -0
  90. package/dist/cjs/printing/printable.js +90 -0
  91. package/dist/cjs/printing/webusb.d.ts +89 -0
  92. package/dist/cjs/printing/webusb.js +110 -0
  93. package/dist/cjs/react/index.d.ts +46 -0
  94. package/dist/cjs/react/index.js +51 -0
  95. package/dist/cjs/receipt/discount.d.ts +12 -0
  96. package/dist/cjs/receipt/discount.js +54 -0
  97. package/dist/cjs/receipt/epos.d.ts +53 -0
  98. package/dist/cjs/receipt/epos.js +95 -0
  99. package/dist/cjs/receipt/grid.d.ts +47 -0
  100. package/dist/cjs/receipt/grid.js +122 -0
  101. package/dist/cjs/receipt/index.d.ts +4 -0
  102. package/dist/cjs/receipt/index.js +29 -0
  103. package/dist/cjs/receipt/layout-escpos.d.ts +35 -0
  104. package/dist/cjs/receipt/layout-escpos.js +67 -0
  105. package/dist/cjs/receipt/layout.d.ts +180 -0
  106. package/dist/cjs/receipt/layout.js +594 -0
  107. package/dist/cjs/register/index.d.ts +51 -0
  108. package/dist/cjs/register/index.js +61 -0
  109. package/dist/cjs/register/pairing.d.ts +248 -0
  110. package/dist/cjs/register/pairing.js +279 -0
  111. package/dist/cjs/register/session.d.ts +37 -0
  112. package/dist/cjs/register/session.js +52 -0
  113. package/dist/cjs/vienna-time.d.ts +23 -0
  114. package/dist/cjs/vienna-time.js +114 -0
  115. package/dist/esm/client/api.d.ts +75 -0
  116. package/dist/esm/client/api.js +37 -0
  117. package/dist/esm/client/auth.d.ts +52 -0
  118. package/dist/esm/client/auth.js +68 -0
  119. package/dist/esm/client/cashregisters.d.ts +21 -0
  120. package/dist/esm/client/cashregisters.js +33 -0
  121. package/dist/esm/client/errors.d.ts +159 -0
  122. package/dist/esm/client/errors.js +212 -0
  123. package/dist/esm/client/index.d.ts +8 -0
  124. package/dist/esm/client/index.js +8 -0
  125. package/dist/esm/client/receipts.d.ts +245 -0
  126. package/dist/esm/client/receipts.js +438 -0
  127. package/dist/esm/client/reports.d.ts +43 -0
  128. package/dist/esm/client/reports.js +69 -0
  129. package/dist/esm/client/status.d.ts +43 -0
  130. package/dist/esm/client/status.js +43 -0
  131. package/dist/esm/client/transport.d.ts +117 -0
  132. package/dist/esm/client/transport.js +307 -0
  133. package/dist/esm/enums/credit-card-provider.d.ts +22 -0
  134. package/dist/esm/enums/credit-card-provider.js +20 -0
  135. package/dist/esm/enums/define-enum.d.ts +15 -0
  136. package/dist/esm/enums/define-enum.js +13 -0
  137. package/dist/esm/enums/index.d.ts +7 -0
  138. package/dist/esm/enums/index.js +7 -0
  139. package/dist/esm/enums/keck-payment-method.d.ts +57 -0
  140. package/dist/esm/enums/keck-payment-method.js +20 -0
  141. package/dist/esm/enums/receipt-type.d.ts +41 -0
  142. package/dist/esm/enums/receipt-type.js +15 -0
  143. package/dist/esm/enums/stripe-link-mode.d.ts +17 -0
  144. package/dist/esm/enums/stripe-link-mode.js +15 -0
  145. package/dist/esm/enums/vat-rate.d.ts +40 -0
  146. package/dist/esm/enums/vat-rate.js +16 -0
  147. package/dist/esm/enums/voucher-action.d.ts +10 -0
  148. package/dist/esm/enums/voucher-action.js +8 -0
  149. package/dist/esm/enums/voucher-type.d.ts +9 -0
  150. package/dist/esm/enums/voucher-type.js +7 -0
  151. package/dist/esm/index.d.ts +5 -0
  152. package/dist/esm/index.js +5 -0
  153. package/dist/esm/kasse/artikel.d.ts +83 -0
  154. package/dist/esm/kasse/artikel.js +70 -0
  155. package/dist/esm/kasse/client.d.ts +10 -0
  156. package/dist/esm/kasse/client.js +33 -0
  157. package/dist/esm/kasse/drucker.d.ts +54 -0
  158. package/dist/esm/kasse/drucker.js +36 -0
  159. package/dist/esm/kasse/index.d.ts +11 -0
  160. package/dist/esm/kasse/index.js +13 -0
  161. package/dist/esm/kasse/settings.d.ts +115 -0
  162. package/dist/esm/kasse/settings.js +58 -0
  163. package/dist/esm/models/cancellation.d.ts +51 -0
  164. package/dist/esm/models/cancellation.js +40 -0
  165. package/dist/esm/models/cashregister.d.ts +77 -0
  166. package/dist/esm/models/cashregister.js +50 -0
  167. package/dist/esm/models/enum-payload.d.ts +26 -0
  168. package/dist/esm/models/enum-payload.js +44 -0
  169. package/dist/esm/models/hobex-receipt.d.ts +63 -0
  170. package/dist/esm/models/hobex-receipt.js +80 -0
  171. package/dist/esm/models/index.d.ts +10 -0
  172. package/dist/esm/models/index.js +10 -0
  173. package/dist/esm/models/receipt-company.d.ts +71 -0
  174. package/dist/esm/models/receipt-company.js +48 -0
  175. package/dist/esm/models/receipt-item.d.ts +100 -0
  176. package/dist/esm/models/receipt-item.js +101 -0
  177. package/dist/esm/models/receipt-summary.d.ts +92 -0
  178. package/dist/esm/models/receipt-summary.js +49 -0
  179. package/dist/esm/models/receipt.d.ts +108 -0
  180. package/dist/esm/models/receipt.js +113 -0
  181. package/dist/esm/models/report-month.d.ts +32 -0
  182. package/dist/esm/models/report-month.js +58 -0
  183. package/dist/esm/models/stripe-url-session.d.ts +18 -0
  184. package/dist/esm/models/stripe-url-session.js +16 -0
  185. package/dist/esm/models/voucher.d.ts +41 -0
  186. package/dist/esm/models/voucher.js +51 -0
  187. package/dist/esm/money.d.ts +23 -0
  188. package/dist/esm/money.js +31 -0
  189. package/dist/esm/payments/hobex.d.ts +87 -0
  190. package/dist/esm/payments/hobex.js +162 -0
  191. package/dist/esm/payments/index.d.ts +33 -0
  192. package/dist/esm/payments/index.js +33 -0
  193. package/dist/esm/payments/stripe.d.ts +61 -0
  194. package/dist/esm/payments/stripe.js +153 -0
  195. package/dist/esm/printing/escpos.d.ts +219 -0
  196. package/dist/esm/printing/escpos.js +616 -0
  197. package/dist/esm/printing/index.d.ts +3 -0
  198. package/dist/esm/printing/index.js +3 -0
  199. package/dist/esm/printing/printable.d.ts +27 -0
  200. package/dist/esm/printing/printable.js +87 -0
  201. package/dist/esm/printing/webusb.d.ts +89 -0
  202. package/dist/esm/printing/webusb.js +101 -0
  203. package/dist/esm/react/index.d.ts +46 -0
  204. package/dist/esm/react/index.js +47 -0
  205. package/dist/esm/receipt/discount.d.ts +12 -0
  206. package/dist/esm/receipt/discount.js +51 -0
  207. package/dist/esm/receipt/epos.d.ts +53 -0
  208. package/dist/esm/receipt/epos.js +86 -0
  209. package/dist/esm/receipt/grid.d.ts +47 -0
  210. package/dist/esm/receipt/grid.js +116 -0
  211. package/dist/esm/receipt/index.d.ts +4 -0
  212. package/dist/esm/receipt/index.js +4 -0
  213. package/dist/esm/receipt/layout-escpos.d.ts +35 -0
  214. package/dist/esm/receipt/layout-escpos.js +64 -0
  215. package/dist/esm/receipt/layout.d.ts +180 -0
  216. package/dist/esm/receipt/layout.js +583 -0
  217. package/dist/esm/register/index.d.ts +51 -0
  218. package/dist/esm/register/index.js +51 -0
  219. package/dist/esm/register/pairing.d.ts +248 -0
  220. package/dist/esm/register/pairing.js +270 -0
  221. package/dist/esm/register/session.d.ts +37 -0
  222. package/dist/esm/register/session.js +48 -0
  223. package/dist/esm/vienna-time.d.ts +23 -0
  224. package/dist/esm/vienna-time.js +110 -0
  225. package/fixtures/belege/langer-artikelname.json +43 -0
  226. package/fixtures/belege/null-ausfall.json +41 -0
  227. package/fixtures/belege/null-jahr.json +41 -0
  228. package/fixtures/belege/null-monat.json +41 -0
  229. package/fixtures/belege/null-pruef.json +41 -0
  230. package/fixtures/belege/null-schluss.json +41 -0
  231. package/fixtures/belege/null-start.json +40 -0
  232. package/fixtures/belege/rabattzeilen.json +61 -0
  233. package/fixtures/belege/signaturausfall-verkauf.json +49 -0
  234. package/fixtures/belege/storno-teil.json +48 -0
  235. package/fixtures/belege/storno-voll.json +54 -0
  236. package/fixtures/belege/testkasse-verkauf.json +50 -0
  237. package/fixtures/belege/testsignatur-verkauf.json +50 -0
  238. package/fixtures/belege/training.json +49 -0
  239. package/fixtures/belege/verkauf-bar.json +49 -0
  240. package/fixtures/belege/verkauf-karte.json +49 -0
  241. package/fixtures/belege/verkauf-kleinunternehmer.json +42 -0
  242. package/fixtures/erwartet/langer-artikelname.grid32.txt +25 -0
  243. package/fixtures/erwartet/langer-artikelname.grid48.txt +24 -0
  244. package/fixtures/erwartet/langer-artikelname.lines.json +216 -0
  245. package/fixtures/erwartet/null-ausfall.grid32.txt +28 -0
  246. package/fixtures/erwartet/null-ausfall.grid48.txt +25 -0
  247. package/fixtures/erwartet/null-ausfall.lines.json +220 -0
  248. package/fixtures/erwartet/null-jahr.grid32.txt +29 -0
  249. package/fixtures/erwartet/null-jahr.grid48.txt +25 -0
  250. package/fixtures/erwartet/null-jahr.lines.json +220 -0
  251. package/fixtures/erwartet/null-monat.grid32.txt +28 -0
  252. package/fixtures/erwartet/null-monat.grid48.txt +25 -0
  253. package/fixtures/erwartet/null-monat.lines.json +220 -0
  254. package/fixtures/erwartet/null-pruef.grid32.txt +28 -0
  255. package/fixtures/erwartet/null-pruef.grid48.txt +25 -0
  256. package/fixtures/erwartet/null-pruef.lines.json +220 -0
  257. package/fixtures/erwartet/null-schluss.grid32.txt +28 -0
  258. package/fixtures/erwartet/null-schluss.grid48.txt +25 -0
  259. package/fixtures/erwartet/null-schluss.lines.json +220 -0
  260. package/fixtures/erwartet/null-start.grid32.txt +28 -0
  261. package/fixtures/erwartet/null-start.grid48.txt +25 -0
  262. package/fixtures/erwartet/null-start.lines.json +220 -0
  263. package/fixtures/erwartet/rabattzeilen.grid32.txt +27 -0
  264. package/fixtures/erwartet/rabattzeilen.grid48.txt +26 -0
  265. package/fixtures/erwartet/rabattzeilen.lines.json +286 -0
  266. package/fixtures/erwartet/signaturausfall-verkauf.grid32.txt +28 -0
  267. package/fixtures/erwartet/signaturausfall-verkauf.grid48.txt +26 -0
  268. package/fixtures/erwartet/signaturausfall-verkauf.lines.json +266 -0
  269. package/fixtures/erwartet/storno-teil.grid32.txt +27 -0
  270. package/fixtures/erwartet/storno-teil.grid48.txt +26 -0
  271. package/fixtures/erwartet/storno-teil.lines.json +237 -0
  272. package/fixtures/erwartet/storno-voll.grid32.txt +29 -0
  273. package/fixtures/erwartet/storno-voll.grid48.txt +28 -0
  274. package/fixtures/erwartet/storno-voll.lines.json +277 -0
  275. package/fixtures/erwartet/testkasse-verkauf.grid32.txt +28 -0
  276. package/fixtures/erwartet/testkasse-verkauf.grid48.txt +27 -0
  277. package/fixtures/erwartet/testkasse-verkauf.lines.json +270 -0
  278. package/fixtures/erwartet/testsignatur-verkauf.grid32.txt +30 -0
  279. package/fixtures/erwartet/testsignatur-verkauf.grid48.txt +27 -0
  280. package/fixtures/erwartet/testsignatur-verkauf.lines.json +270 -0
  281. package/fixtures/erwartet/training.grid32.txt +33 -0
  282. package/fixtures/erwartet/training.grid48.txt +30 -0
  283. package/fixtures/erwartet/training.lines.json +277 -0
  284. package/fixtures/erwartet/verkauf-bar.grid32.txt +25 -0
  285. package/fixtures/erwartet/verkauf-bar.grid48.txt +24 -0
  286. package/fixtures/erwartet/verkauf-bar.lines.json +256 -0
  287. package/fixtures/erwartet/verkauf-karte.grid32.txt +25 -0
  288. package/fixtures/erwartet/verkauf-karte.grid48.txt +24 -0
  289. package/fixtures/erwartet/verkauf-karte.lines.json +256 -0
  290. package/fixtures/erwartet/verkauf-kleinunternehmer.grid32.txt +26 -0
  291. package/fixtures/erwartet/verkauf-kleinunternehmer.grid48.txt +25 -0
  292. package/fixtures/erwartet/verkauf-kleinunternehmer.lines.json +226 -0
  293. package/fixtures/manifest.json +107 -0
  294. package/package.json +135 -0
@@ -0,0 +1,100 @@
1
+ import { VatRate } from '../enums/index.js';
2
+ /**
3
+ * Belegposition — Zwilling von `KasseneckItem` in
4
+ * kasseneck_api/lib/models/kasseneck_item.dart.
5
+ *
6
+ * `priceCents` ist der Einzelpreis in **Cent** (exakte Integer-Arithmetik,
7
+ * keine Gleitkomma-Rundungsfehler). Eine Euro-Variante gibt es hier bewusst
8
+ * nicht — anders als beim Gutschein oder Hobex-Beleg sendet die Nutzlast
9
+ * (v2-Format) den Preis bereits als ganze Cent.
10
+ *
11
+ * `vat` ist beim Lesen entweder der bekannte Steuersatz (Objekt) oder — falls
12
+ * die Nutzlast einen Satz traegt, den dieses Paket noch nicht kennt — der
13
+ * rohe `rate`-Wert als Zahl (siehe [readVatRateByRate]). Ein Aufrufer erkennt
14
+ * den unbekannten Fall am `typeof`: ein Objekt ist bekannt, eine Zahl nicht.
15
+ *
16
+ * `quantity` ist beim **Schreiben** eine ganze Menge; TypeScript kennt keinen
17
+ * Ganzzahltyp, deshalb prueft der Schreibpfad sie zur Laufzeit (siehe
18
+ * [receiptItemIsValid] und [toReceiptItemPayload]). Beim **Lesen** steht hier,
19
+ * was in der Nutzlast stand — auch eine gebrochene Menge aus fremder Hand:
20
+ * lesen tolerant, schreiben streng. `receiptItemTotalCents` liefert dann
21
+ * folgerichtig einen gebrochenen Cent-Betrag; das ist die Wahrheit des
22
+ * Belegs, nicht ein Fehler dieses Pakets.
23
+ */
24
+ export interface ReceiptItem {
25
+ name: string;
26
+ /** Ganze Menge, > 0 zum Senden (siehe Klassenkommentar). */
27
+ quantity: number;
28
+ vat: VatRate | number;
29
+ priceCents: number;
30
+ }
31
+ /**
32
+ * Nutzlast-Form, die dieses Paket **schreibt** (v2):
33
+ * `{ name, quantity, unitPriceCents, vatRate }`.
34
+ */
35
+ export interface ReceiptItemPayload {
36
+ name: string;
37
+ quantity: number;
38
+ unitPriceCents: number;
39
+ vatRate: number;
40
+ }
41
+ /**
42
+ * Nutzlast-Form, die dieses Paket **liest** — v2 und v1 nebeneinander, alles
43
+ * optional (Zwilling von `KasseneckItem.fromJson`).
44
+ *
45
+ * Das ist kein Entgegenkommen, sondern der Normalfall: Das Backend bildet die
46
+ * v2-Felder am Eingang auf v1 ab und **speichert v1** (`normalizeMoneyInputs`
47
+ * in functions/index.js — quantity->amount, vatRate->vat,
48
+ * unitPriceCents->priceOneCents, daraus priceOne). Ein gespeicherter Beleg
49
+ * traegt v1 also immer, v2 nur dann, wenn der erzeugende Client sie
50
+ * mitgesendet hat. Wer hier nur v2 liest, bekommt bei Belegen von
51
+ * Alt-Clients `undefined` in Menge, Steuersatz und Preis — ohne Fehler, aber
52
+ * mit `NaN` in jeder Summe und mit einem Beleg, der sich nicht mehr
53
+ * stornieren laesst.
54
+ */
55
+ export interface ReceiptItemPayloadRead {
56
+ name?: string | null;
57
+ /** v2: Menge */
58
+ quantity?: number | null;
59
+ /** v2: Einzelpreis in Cent */
60
+ unitPriceCents?: number | null;
61
+ /** v2: Steuersatz */
62
+ vatRate?: number | null;
63
+ /** v1: Menge */
64
+ amount?: number | null;
65
+ /** v1: Einzelpreis in Cent */
66
+ priceOneCents?: number | null;
67
+ /** v1: Einzelpreis in Euro */
68
+ priceOne?: number | null;
69
+ /** v1: Steuersatz */
70
+ vat?: number | null;
71
+ }
72
+ export declare function toReceiptItemPayload(item: ReceiptItem): ReceiptItemPayload;
73
+ /**
74
+ * Liest beide Nutzlast-Formen (siehe [ReceiptItemPayloadRead]). Reihenfolge
75
+ * wie im Dart-Vorbild: v2 vor v1, Cent-Angabe vor Euro-Angabe (exakt vor
76
+ * gerundet); die Euro-Angabe wird genau einmal auf Cent gerundet.
77
+ */
78
+ export declare function fromReceiptItemPayload(payload: ReceiptItemPayloadRead): ReceiptItem;
79
+ /**
80
+ * Zeilensumme in Cent. Bei einer selbst erzeugten Position ist sie exakt:
81
+ * ganze Menge mal ganze Cent. Bei einem fremd erzeugten Beleg mit gebrochener
82
+ * Menge ist sie folgerichtig gebrochen — das ist der signierte Betrag, und ihn
83
+ * zu runden hiesse, einen anderen zu drucken.
84
+ */
85
+ export declare function receiptItemTotalCents(item: ReceiptItem): number;
86
+ /**
87
+ * Ist die Position an das Backend sendbar? Zwilling von `KasseneckItem.isValid`
88
+ * im Flutter-Vorbild: ein Name muss da sein und die Menge positiv **und ganz**.
89
+ * Der Preis darf negativ sein — genau das ist eine Stornoposition.
90
+ *
91
+ * Zur Ganzzahligkeit siehe [pruefeMenge]: im Dart-Vorbild ist `quantity` ein
92
+ * `int`, hier traegt der Typ das nicht, also muss es die Laufzeit tun.
93
+ */
94
+ export declare function receiptItemIsValid(item: ReceiptItem): boolean;
95
+ /**
96
+ * Stornoposition zu dieser Position — Zwilling von `KasseneckItem.negative`:
97
+ * gleicher Name, gleiche Menge, gleicher Steuersatz, **negierter** Einzelpreis.
98
+ * Die Menge bleibt positiv; das Vorzeichen sitzt ausschliesslich im Preis.
99
+ */
100
+ export declare function negateReceiptItem(item: ReceiptItem): ReceiptItem;
@@ -0,0 +1,101 @@
1
+ import { VatRate } from '../enums/index.js';
2
+ import { readVatRateByRate, requireVatRateByRate } from './enum-payload.js';
3
+ export function toReceiptItemPayload(item) {
4
+ // Schreibpfad bleibt streng: ein unaufgeloester (unbekannter) Steuersatz
5
+ // darf nicht unbesehen wieder hinausgehen.
6
+ const vat = typeof item.vat === 'number' ? requireVatRateByRate(item.vat) : item.vat;
7
+ pruefeMenge(item.quantity);
8
+ return {
9
+ name: item.name,
10
+ quantity: item.quantity,
11
+ unitPriceCents: item.priceCents,
12
+ vatRate: vat.rate,
13
+ };
14
+ }
15
+ /**
16
+ * Liest beide Nutzlast-Formen (siehe [ReceiptItemPayloadRead]). Reihenfolge
17
+ * wie im Dart-Vorbild: v2 vor v1, Cent-Angabe vor Euro-Angabe (exakt vor
18
+ * gerundet); die Euro-Angabe wird genau einmal auf Cent gerundet.
19
+ */
20
+ export function fromReceiptItemPayload(payload) {
21
+ const cents = ersteZahl(payload.unitPriceCents, payload.priceOneCents);
22
+ const euro = ersteZahl(payload.priceOne);
23
+ const menge = ersteZahl(payload.quantity, payload.amount);
24
+ const satz = ersteZahl(payload.vatRate, payload.vat);
25
+ return {
26
+ name: payload.name ?? '',
27
+ // Die Menge kommt herein, wie sie in der Nutzlast steht — auch eine
28
+ // gebrochene. Sie abzuschneiden (das Dart-Vorbild tut es mit `toInt()`)
29
+ // waere hier falsch: dort erzwingt es das `int`-Modell der Sprache, hier
30
+ // gaebe es lautlos einen anderen Betrag als den signierten. Am HTTP-API
31
+ // haengt auch fremde Software, und das Backend prueft bei den Positionen
32
+ // allein `unitPriceCents` auf Ganzzahligkeit — ein solcher Beleg ist also
33
+ // ausstellbar. Er muss sich dann anzeigen und drucken lassen, wie er
34
+ // signiert wurde. Streng ist stattdessen der Schreibpfad (siehe
35
+ // [pruefeMenge]): aus diesem Paket geht keine gebrochene Menge hinaus.
36
+ quantity: menge ?? 0,
37
+ // Fehlt der Steuersatz voellig, gibt es keinen rohen Wert zum Erhalten;
38
+ // dann gilt wie im Dart-Vorbild 0 % (das Backend prueft `vat` als Pflicht,
39
+ // der Fall entsteht also nur bei einer kaputten Nutzlast).
40
+ vat: satz != null ? readVatRateByRate(satz) : VatRate.vat0,
41
+ priceCents: cents != null ? Math.round(cents) : euro != null ? Math.round(euro * 100) : 0,
42
+ };
43
+ }
44
+ /** Erster brauchbarer Zahlenwert der Reihe; `null`/`undefined`/NaN zaehlen nicht. */
45
+ function ersteZahl(...werte) {
46
+ for (const wert of werte) {
47
+ if (typeof wert === 'number' && Number.isFinite(wert)) {
48
+ return wert;
49
+ }
50
+ }
51
+ return undefined;
52
+ }
53
+ /**
54
+ * Zeilensumme in Cent. Bei einer selbst erzeugten Position ist sie exakt:
55
+ * ganze Menge mal ganze Cent. Bei einem fremd erzeugten Beleg mit gebrochener
56
+ * Menge ist sie folgerichtig gebrochen — das ist der signierte Betrag, und ihn
57
+ * zu runden hiesse, einen anderen zu drucken.
58
+ */
59
+ export function receiptItemTotalCents(item) {
60
+ return item.priceCents * item.quantity;
61
+ }
62
+ /**
63
+ * Ist die Position an das Backend sendbar? Zwilling von `KasseneckItem.isValid`
64
+ * im Flutter-Vorbild: ein Name muss da sein und die Menge positiv **und ganz**.
65
+ * Der Preis darf negativ sein — genau das ist eine Stornoposition.
66
+ *
67
+ * Zur Ganzzahligkeit siehe [pruefeMenge]: im Dart-Vorbild ist `quantity` ein
68
+ * `int`, hier traegt der Typ das nicht, also muss es die Laufzeit tun.
69
+ */
70
+ export function receiptItemIsValid(item) {
71
+ return item.name.length > 0 && Number.isInteger(item.quantity) && item.quantity > 0;
72
+ }
73
+ /**
74
+ * Wirft, wenn die Menge keine ganze Zahl ist.
75
+ *
76
+ * Der Grund ist keine Formstrenge, sondern die Belegwahrheit: Das Backend
77
+ * prueft **nur** `unitPriceCents` auf Ganzzahligkeit (`checkItemsIsValid` in
78
+ * functions/index.js), eine gebrochene Menge kaeme also durch und wuerde
79
+ * mitsigniert. Der gedruckte Beleg wiese dann einen anderen Betrag aus als der
80
+ * signierte, und ein Storno darauf traegt eine Menge, die es nie gab. Deshalb
81
+ * faellt die Menge hier, vor dem Senden, und nicht spaeter still.
82
+ *
83
+ * Der Lesepfad tut das ausdruecklich **nicht** (siehe
84
+ * [fromReceiptItemPayload]): ein fremd erzeugter Beleg muss sich anzeigen
85
+ * lassen, wie er signiert wurde.
86
+ *
87
+ * `Number.isInteger` faengt Bruchteile, NaN und Unendlich in einem.
88
+ */
89
+ function pruefeMenge(quantity) {
90
+ if (!Number.isInteger(quantity)) {
91
+ throw new Error(`Menge: "${quantity}" ist keine ganze Zahl`);
92
+ }
93
+ }
94
+ /**
95
+ * Stornoposition zu dieser Position — Zwilling von `KasseneckItem.negative`:
96
+ * gleicher Name, gleiche Menge, gleicher Steuersatz, **negierter** Einzelpreis.
97
+ * Die Menge bleibt positiv; das Vorzeichen sitzt ausschliesslich im Preis.
98
+ */
99
+ export function negateReceiptItem(item) {
100
+ return { ...item, priceCents: -item.priceCents };
101
+ }
@@ -0,0 +1,92 @@
1
+ import { KeckPaymentMethod, ReceiptType } from '../enums/index.js';
2
+ /**
3
+ * Belegzeile einer Liste — die Form, die `listMyReceipts` liefert
4
+ * (`projectReceiptForCustomer` in functions/index.js).
5
+ *
6
+ * **Das ist kein [Receipt].** Die Liste traegt bewusst nur, was eine Uebersicht
7
+ * braucht: keine Positionen, keine Gutscheine, keine Signatur, keinen QR-Code.
8
+ * Wer einen Beleg nachdrucken oder stornieren will, holt ihn ueber
9
+ * `getReceipt`/`getReceiptWithCompany` einzeln — dort steht der vollstaendige,
10
+ * signierte Beleg.
11
+ *
12
+ * `total` kommt vom Backend in **Euro** (auf zwei Stellen gerundet, `round2`).
13
+ * Dieses Paket rechnet ausnahmslos in ganzen Cent, deshalb wird der Betrag
14
+ * genau hier, an der Antwortgrenze, einmal umgerechnet — wie beim
15
+ * Hobex-Beleg.
16
+ *
17
+ * `receiptType` und `paymentMethod` sind wie ueberall beim Lesen entweder der
18
+ * bekannte Enum-Eintrag oder der rohe Nutzlast-Schluessel (siehe
19
+ * enum-payload.ts): eine Liste darf nicht daran scheitern, dass ein einzelner
20
+ * Beleg eine Zahlungsart traegt, die dieses Paket noch nicht kennt.
21
+ */
22
+ /** Anlass eines Nullbelegs (Backend: cashregister-lifecycle ZERO_KINDS). */
23
+ export declare const ZERO_KINDS: readonly ["monthly", "annual", "annual_replacement", "outage_end", "final", "manual"];
24
+ export type ZeroKind = (typeof ZERO_KINDS)[number];
25
+ export declare function istZeroKind(w: unknown): w is ZeroKind;
26
+ export interface ReceiptSummary {
27
+ receiptId: string;
28
+ /** Fortlaufender Belegzaehler der Kasse; fehlt bei Alt-Belegen. */
29
+ counter?: number;
30
+ receiptType: ReceiptType | string;
31
+ /** Roher Belegzeitstempel; Deutung ueber `parseServerTimeStamp`. */
32
+ timeStamp: string;
33
+ /** Belegsumme in ganzen Cent. */
34
+ totalCents: number;
35
+ paymentMethod: KeckPaymentMethod | string;
36
+ /** `'success'`/`'failed'` der FinanzOnline-Uebermittlung, sofern bekannt. */
37
+ transmissionStatus?: string;
38
+ /** Zeitstempel der Uebermittlung, roh wie vom Finanzamt geliefert. */
39
+ transmissionTime?: string;
40
+ /**
41
+ * Wurde der Beleg mit funktionierender Signatureinheit ausgestellt? Das
42
+ * Backend meldet hier `signatureSuccess !== false`, also `true`, solange
43
+ * nichts Gegenteiliges vermerkt ist.
44
+ */
45
+ signatureOk: boolean;
46
+ /** Nur fuer Kassen-Benutzer geliefert: Positionen kurz (Name, Menge). */
47
+ items: Array<{
48
+ name: string;
49
+ quantity: number;
50
+ }>;
51
+ /** Bediener am Beleg, wenn bekannt. */
52
+ operator?: {
53
+ uid: string | null;
54
+ name: string;
55
+ };
56
+ /** Nur am Storno-Beleg: das Original. */
57
+ cancellationOf?: {
58
+ receiptId: string | null;
59
+ };
60
+ cancellationReason?: string;
61
+ /** offen | teil | voll -- Storno-Stand des Originals. */
62
+ stornoStand: 'offen' | 'teil' | 'voll';
63
+ /** Nur am Nullbeleg, nur fuer Kassen-Benutzer: Anlass (monthly, annual, annual_replacement, outage_end, final, manual). */
64
+ zeroKind?: ZeroKind;
65
+ }
66
+ export interface ReceiptSummaryPayload {
67
+ receiptId?: string | null;
68
+ counter?: number | null;
69
+ receiptType?: string | null;
70
+ timeStamp?: string | null;
71
+ /** Belegsumme in **Euro** (siehe Klassenkommentar). */
72
+ total?: number | null;
73
+ paymentMethod?: string | null;
74
+ transmission_status?: string | null;
75
+ ts_transmission?: string | null;
76
+ signature_ok?: boolean | null;
77
+ items?: Array<{
78
+ name?: string | null;
79
+ quantity?: number | null;
80
+ }> | null;
81
+ operator?: {
82
+ uid?: string | null;
83
+ name?: string | null;
84
+ } | null;
85
+ cancellationOf?: {
86
+ receiptId?: string | null;
87
+ } | null;
88
+ cancellationReason?: string | null;
89
+ stornoStand?: string | null;
90
+ zeroKind?: string | null;
91
+ }
92
+ export declare function fromReceiptSummaryPayload(payload: ReceiptSummaryPayload): ReceiptSummary;
@@ -0,0 +1,49 @@
1
+ import { KeckPaymentMethod, ReceiptType } from '../enums/index.js';
2
+ import { euroToCents } from '../money.js';
3
+ import { readEnumKey } from './enum-payload.js';
4
+ /**
5
+ * Belegzeile einer Liste — die Form, die `listMyReceipts` liefert
6
+ * (`projectReceiptForCustomer` in functions/index.js).
7
+ *
8
+ * **Das ist kein [Receipt].** Die Liste traegt bewusst nur, was eine Uebersicht
9
+ * braucht: keine Positionen, keine Gutscheine, keine Signatur, keinen QR-Code.
10
+ * Wer einen Beleg nachdrucken oder stornieren will, holt ihn ueber
11
+ * `getReceipt`/`getReceiptWithCompany` einzeln — dort steht der vollstaendige,
12
+ * signierte Beleg.
13
+ *
14
+ * `total` kommt vom Backend in **Euro** (auf zwei Stellen gerundet, `round2`).
15
+ * Dieses Paket rechnet ausnahmslos in ganzen Cent, deshalb wird der Betrag
16
+ * genau hier, an der Antwortgrenze, einmal umgerechnet — wie beim
17
+ * Hobex-Beleg.
18
+ *
19
+ * `receiptType` und `paymentMethod` sind wie ueberall beim Lesen entweder der
20
+ * bekannte Enum-Eintrag oder der rohe Nutzlast-Schluessel (siehe
21
+ * enum-payload.ts): eine Liste darf nicht daran scheitern, dass ein einzelner
22
+ * Beleg eine Zahlungsart traegt, die dieses Paket noch nicht kennt.
23
+ */
24
+ /** Anlass eines Nullbelegs (Backend: cashregister-lifecycle ZERO_KINDS). */
25
+ export const ZERO_KINDS = ['monthly', 'annual', 'annual_replacement', 'outage_end', 'final', 'manual'];
26
+ export function istZeroKind(w) {
27
+ return typeof w === 'string' && ZERO_KINDS.includes(w);
28
+ }
29
+ export function fromReceiptSummaryPayload(payload) {
30
+ return {
31
+ receiptId: payload.receiptId ?? '',
32
+ ...(typeof payload.counter === 'number' ? { counter: payload.counter } : {}),
33
+ receiptType: readEnumKey(ReceiptType, payload.receiptType ?? ''),
34
+ timeStamp: payload.timeStamp ?? '',
35
+ totalCents: euroToCents(payload.total),
36
+ paymentMethod: readEnumKey(KeckPaymentMethod, payload.paymentMethod ?? ''),
37
+ ...(payload.transmission_status ? { transmissionStatus: payload.transmission_status } : {}),
38
+ ...(payload.ts_transmission ? { transmissionTime: payload.ts_transmission } : {}),
39
+ // Nur ein ausdrueckliches `false` heisst "ausgefallen" — genau wie im
40
+ // Backend, das hier `signatureSuccess !== false` sendet.
41
+ signatureOk: payload.signature_ok !== false,
42
+ items: Array.isArray(payload.items) ? payload.items.map((i) => ({ name: i?.name ?? '', quantity: typeof i?.quantity === 'number' ? i.quantity : 0 })) : [],
43
+ ...(payload.operator ? { operator: { uid: payload.operator.uid ?? null, name: payload.operator.name ?? '' } } : {}),
44
+ ...(payload.cancellationOf ? { cancellationOf: { receiptId: payload.cancellationOf.receiptId ?? null } } : {}),
45
+ ...(payload.cancellationReason ? { cancellationReason: payload.cancellationReason } : {}),
46
+ stornoStand: payload.stornoStand === 'teil' || payload.stornoStand === 'voll' ? payload.stornoStand : 'offen',
47
+ ...(istZeroKind(payload.zeroKind) ? { zeroKind: payload.zeroKind } : {}),
48
+ };
49
+ }
@@ -0,0 +1,108 @@
1
+ import { ReceiptType, KeckPaymentMethod, CreditCardProvider } from '../enums/index.js';
2
+ import { type ReceiptItem, type ReceiptItemPayload, type ReceiptItemPayloadRead } from './receipt-item.js';
3
+ import { type Voucher, type VoucherPayload } from './voucher.js';
4
+ import type { Cancellation, CancellationOf, CancellationReason } from './cancellation.js';
5
+ import { type ZeroKind } from './receipt-summary.js';
6
+ /**
7
+ * Beleg — Zwilling der Beleg-Nutzlast von `KasseneckReceipt` in
8
+ * kasseneck_api/lib/models/kasseneck_receipt.dart (nur der signatur-/
9
+ * positionsrelevante Teil, den `toReceiptJson()`/die `receipt`-Map von
10
+ * `fromJson()` traegt — nicht die Firmen-/Druckdaten wie Firma, Adresse oder
11
+ * Fusszeilen: die betreffen ausschliesslich das Beleg-Rendering und gehoeren
12
+ * nicht zum RKSV-Kernbeleg. Sie stehen als eigenes Modell daneben, siehe
13
+ * `ReceiptCompany` in ./receipt-company.ts).
14
+ *
15
+ * `timeStamp` bleibt bewusst der rohe Zeitstempel-String aus der Nutzlast;
16
+ * `parseServerTimeStamp` (`../vienna-time.js`) deutet ihn auf Wunsch in einen
17
+ * echten Zeitpunkt um (uneinheitliches Server-Format, siehe dort).
18
+ *
19
+ * `paymentMethod`/`receiptType`/`creditCardProvider` sind beim Lesen entweder
20
+ * der bekannte Enum-Eintrag oder — bei einem der Nutzlast unbekannten
21
+ * Schluessel — der rohe String (siehe `enum-payload.ts`, `readEnumKey`).
22
+ */
23
+ export interface Receipt {
24
+ receiptId: string;
25
+ cashregisterId: string;
26
+ timeStamp: string;
27
+ items: ReceiptItem[];
28
+ vouchers: Voucher[];
29
+ paymentMethod: KeckPaymentMethod | string;
30
+ turnoverCounterAES256ICM: string;
31
+ signaturePreviousReceipt: string;
32
+ certificateSerialNumber: string;
33
+ receiptType: ReceiptType | string;
34
+ sig: string;
35
+ qr: string;
36
+ fullReceiptId: string;
37
+ creditCardProvider?: CreditCardProvider | string;
38
+ cardPaymentId?: string;
39
+ cardPaymentData?: Record<string, unknown>;
40
+ customerDetails: string[];
41
+ legalMessage: string[];
42
+ signatureSuccess?: boolean;
43
+ customProjectId?: string;
44
+ /** Nur am Storno-Beleg: das stornierte Original. */
45
+ cancellationOf?: CancellationOf;
46
+ /** Nur am Storno-Beleg: Grund-Code aus [CANCELLATION_REASONS]. */
47
+ cancellationReason?: CancellationReason | string;
48
+ /** Nur am Original: alle (Teil-)Stornos, Quelle der Restmengen. */
49
+ cancellations?: Cancellation[];
50
+ /** Nur an Nullbelegen: Anlass (monthly, annual, annual_replacement, outage_end, final, manual). */
51
+ zeroKind?: ZeroKind;
52
+ }
53
+ export interface ReceiptPayload {
54
+ qr: string;
55
+ sig: string;
56
+ certificateSerialNumber: string;
57
+ signaturePreviousReceipt: string;
58
+ turnoverCounterAES256ICM: string;
59
+ paymentMethod: string;
60
+ items: ReceiptItemPayload[];
61
+ vouchers: VoucherPayload[] | null;
62
+ timeStamp: string;
63
+ cashregisterId: string;
64
+ receiptType: string;
65
+ receiptId: string;
66
+ fullReceiptId: string;
67
+ creditCardProvider: string | null;
68
+ cardPaymentId: string | null;
69
+ cardPaymentData: Record<string, unknown> | null;
70
+ customerDetails: string;
71
+ legalMessage: string;
72
+ signatureSuccess: boolean | null;
73
+ customProjectId: string | null;
74
+ }
75
+ /**
76
+ * Nutzlast-Form, die dieses Paket **liest**. Unterscheidet sich von
77
+ * [ReceiptPayload] bei den Positionen: ein gespeicherter Beleg traegt sie in
78
+ * der v1-Form, die das Backend ablegt (siehe [ReceiptItemPayloadRead]).
79
+ * Nullbelege haben ueberhaupt keine Positionen.
80
+ */
81
+ export interface ReceiptPayloadRead extends Omit<ReceiptPayload, 'items' | 'vouchers'> {
82
+ items?: ReceiptItemPayloadRead[] | null;
83
+ vouchers?: VoucherPayload[] | null;
84
+ cancellationOf?: CancellationOf | null;
85
+ cancellationReason?: string | null;
86
+ zeroKind?: string | null;
87
+ cancellations?: Cancellation[] | null;
88
+ }
89
+ /**
90
+ * Schreibt die Nutzlast in der **neuen** Form — sie **normalisiert, statt zu
91
+ * spiegeln**: ein Beleg, der in der v1-Positionsform gelesen wurde, geht hier
92
+ * in der v2-Form wieder hinaus (wie im Flutter-Vorbild, dessen `toJson` v2
93
+ * schreibt und dessen `fromJson` beide Formen liest). Nutzlast rein -> Beleg
94
+ * -> Nutzlast raus ist deshalb kein Rundtrip, wenn die Eingabe v1 war.
95
+ *
96
+ * Fuer dieses Paket ohne Folgen: Belege gehen ausschliesslich ueber
97
+ * `createReceipt` an den Server, das seine Nutzlast selbst baut.
98
+ */
99
+ export declare function toReceiptPayload(receipt: Receipt): ReceiptPayload;
100
+ export declare function fromReceiptPayload(payload: ReceiptPayloadRead): Receipt;
101
+ /**
102
+ * Zwischensumme in **Cent** — Positionen plus verkaufte Wertgutscheine minus
103
+ * eingeloeste Promotionsgutscheine. Wertgutschein-Einloesungen wirken erst auf
104
+ * [receiptSumCents], nicht hier (siehe Dart-Vorbild `subSumCents`/`sumCents`).
105
+ */
106
+ export declare function receiptSubSumCents(receipt: Receipt): number;
107
+ /** Gesamtsumme in **Cent** — Zwischensumme minus eingeloeste Wertgutscheine. */
108
+ export declare function receiptSumCents(receipt: Receipt): number;
@@ -0,0 +1,113 @@
1
+ import { ReceiptType, KeckPaymentMethod, CreditCardProvider, VoucherAction, VoucherType } from '../enums/index.js';
2
+ import { readEnumKey, requireEnumKey } from './enum-payload.js';
3
+ import { toReceiptItemPayload, fromReceiptItemPayload, receiptItemTotalCents, } from './receipt-item.js';
4
+ import { toVoucherPayload, fromVoucherPayload } from './voucher.js';
5
+ import { istZeroKind } from './receipt-summary.js';
6
+ /**
7
+ * Schreibt die Nutzlast in der **neuen** Form — sie **normalisiert, statt zu
8
+ * spiegeln**: ein Beleg, der in der v1-Positionsform gelesen wurde, geht hier
9
+ * in der v2-Form wieder hinaus (wie im Flutter-Vorbild, dessen `toJson` v2
10
+ * schreibt und dessen `fromJson` beide Formen liest). Nutzlast rein -> Beleg
11
+ * -> Nutzlast raus ist deshalb kein Rundtrip, wenn die Eingabe v1 war.
12
+ *
13
+ * Fuer dieses Paket ohne Folgen: Belege gehen ausschliesslich ueber
14
+ * `createReceipt` an den Server, das seine Nutzlast selbst baut.
15
+ */
16
+ export function toReceiptPayload(receipt) {
17
+ // Schreibpfad bleibt streng: ReceiptType/KeckPaymentMethod sind bekannt am
18
+ // Objekt-Charakter erkennbar (defineEnum-Eintraege); ein roher String muss
19
+ // erst durch den Lookup, sonst wirft er.
20
+ const paymentMethod = typeof receipt.paymentMethod === 'object' ? receipt.paymentMethod : requireEnumKey(KeckPaymentMethod, receipt.paymentMethod, 'Zahlungsart');
21
+ const receiptType = typeof receipt.receiptType === 'object' ? receipt.receiptType : requireEnumKey(ReceiptType, receipt.receiptType, 'Belegtyp');
22
+ return {
23
+ qr: receipt.qr,
24
+ sig: receipt.sig,
25
+ certificateSerialNumber: receipt.certificateSerialNumber,
26
+ signaturePreviousReceipt: receipt.signaturePreviousReceipt,
27
+ turnoverCounterAES256ICM: receipt.turnoverCounterAES256ICM,
28
+ paymentMethod: paymentMethod.value,
29
+ items: receipt.items.map(toReceiptItemPayload),
30
+ vouchers: receipt.vouchers.map(toVoucherPayload),
31
+ timeStamp: receipt.timeStamp,
32
+ cashregisterId: receipt.cashregisterId,
33
+ receiptType: receiptType.value,
34
+ receiptId: receipt.receiptId,
35
+ fullReceiptId: receipt.fullReceiptId,
36
+ // CreditCardProvider ist ein flacher String-Enum (kein Objekt-Charakter) —
37
+ // der Lookup entscheidet hier ausnahmslos, bekannt oder nicht.
38
+ creditCardProvider: receipt.creditCardProvider != null ? requireEnumKey(CreditCardProvider, receipt.creditCardProvider, 'Kartenanbieter') : null,
39
+ cardPaymentId: receipt.cardPaymentId ?? null,
40
+ cardPaymentData: receipt.cardPaymentData ?? null,
41
+ customerDetails: receipt.customerDetails.join('\n'),
42
+ legalMessage: receipt.legalMessage.join('\n'),
43
+ signatureSuccess: receipt.signatureSuccess ?? null,
44
+ customProjectId: receipt.customProjectId ?? null,
45
+ };
46
+ }
47
+ // Nullbelege haben keine Positionen -> items kann fehlen/null sein (siehe Dart-Vorbild).
48
+ const leereZeile = (text) => (text ? text.split('\n') : []);
49
+ export function fromReceiptPayload(payload) {
50
+ return {
51
+ receiptId: payload.receiptId,
52
+ cashregisterId: payload.cashregisterId,
53
+ timeStamp: payload.timeStamp,
54
+ items: (payload.items ?? []).map(fromReceiptItemPayload),
55
+ vouchers: (payload.vouchers ?? []).map(fromVoucherPayload),
56
+ paymentMethod: readEnumKey(KeckPaymentMethod, payload.paymentMethod),
57
+ turnoverCounterAES256ICM: payload.turnoverCounterAES256ICM,
58
+ signaturePreviousReceipt: payload.signaturePreviousReceipt,
59
+ certificateSerialNumber: payload.certificateSerialNumber,
60
+ receiptType: readEnumKey(ReceiptType, payload.receiptType),
61
+ sig: payload.sig,
62
+ qr: payload.qr,
63
+ fullReceiptId: payload.fullReceiptId ?? '',
64
+ creditCardProvider: payload.creditCardProvider != null ? readEnumKey(CreditCardProvider, payload.creditCardProvider) : undefined,
65
+ cardPaymentId: payload.cardPaymentId ?? undefined,
66
+ cardPaymentData: payload.cardPaymentData ?? undefined,
67
+ customerDetails: leereZeile(payload.customerDetails),
68
+ legalMessage: leereZeile(payload.legalMessage),
69
+ signatureSuccess: payload.signatureSuccess ?? undefined,
70
+ customProjectId: payload.customProjectId ?? undefined,
71
+ ...(payload.cancellationOf ? { cancellationOf: { receiptId: payload.cancellationOf.receiptId, fullReceiptId: payload.cancellationOf.fullReceiptId ?? null } } : {}),
72
+ ...(payload.cancellationReason ? { cancellationReason: payload.cancellationReason } : {}),
73
+ ...(istZeroKind(payload.zeroKind) ? { zeroKind: payload.zeroKind } : {}),
74
+ ...(payload.cancellations ? { cancellations: payload.cancellations.map(leseStorno) } : {}),
75
+ };
76
+ }
77
+ function leseStorno(eintrag) {
78
+ return {
79
+ ...(eintrag.receiptId !== undefined ? { receiptId: eintrag.receiptId } : {}),
80
+ ...(eintrag.pending === true ? { pending: true } : {}),
81
+ at: Number(eintrag.at ?? 0),
82
+ by: eintrag.by ?? null,
83
+ note: eintrag.note ?? null,
84
+ items: (eintrag.items ?? []).map((p) => ({ index: Number(p.index), quantity: Number(p.quantity) })),
85
+ };
86
+ }
87
+ /**
88
+ * Zwischensumme in **Cent** — Positionen plus verkaufte Wertgutscheine minus
89
+ * eingeloeste Promotionsgutscheine. Wertgutschein-Einloesungen wirken erst auf
90
+ * [receiptSumCents], nicht hier (siehe Dart-Vorbild `subSumCents`/`sumCents`).
91
+ */
92
+ export function receiptSubSumCents(receipt) {
93
+ let cents = receipt.items.reduce((acc, item) => acc + receiptItemTotalCents(item), 0);
94
+ for (const voucher of receipt.vouchers) {
95
+ if (voucher.action === VoucherAction.redeem && voucher.type === VoucherType.promo) {
96
+ cents -= voucher.valueCents ?? 0;
97
+ }
98
+ if (voucher.action === VoucherAction.sell && voucher.type === VoucherType.value) {
99
+ cents += voucher.valueCents ?? 0;
100
+ }
101
+ }
102
+ return cents;
103
+ }
104
+ /** Gesamtsumme in **Cent** — Zwischensumme minus eingeloeste Wertgutscheine. */
105
+ export function receiptSumCents(receipt) {
106
+ let cents = receiptSubSumCents(receipt);
107
+ for (const voucher of receipt.vouchers) {
108
+ if (voucher.action === VoucherAction.redeem && voucher.type === VoucherType.value) {
109
+ cents -= voucher.valueCents ?? 0;
110
+ }
111
+ }
112
+ return cents;
113
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Berichtsmonat — Zwilling von `ReportMonth` in
3
+ * kasseneck_api/lib/models/report_month.dart.
4
+ *
5
+ * Hat im Dart-Vorbild bewusst **keine** JSON-Nutzlast (kein `fromJson`/
6
+ * `toJson`) — es ist ein reiner Kalender-Werttyp fuer Monats-Arithmetik und
7
+ * Anzeige, kein Beleg-/Backend-Feld. `month` ist die Monatszahl 1-12
8
+ * (entspricht `KeckMonth.id` im Flutter-Paket) statt eines eigenen Enums —
9
+ * ein eigenes `KeckMonth`-Enum wuerde hier nur fuer diesen einen Werttyp
10
+ * Maschinerie aufbauen, die niemand sonst braucht.
11
+ */
12
+ export interface ReportMonth {
13
+ month: number;
14
+ year: number;
15
+ }
16
+ /**
17
+ * Berichtsmonat eines Zeitpunkts — eingeordnet nach **Wiener** Zeit, nicht
18
+ * nach der Zeitzone des ausfuehrenden Rechners.
19
+ *
20
+ * Der Geschaeftsmonat ist ein oesterreichischer Kalenderwert: ein Beleg vom
21
+ * 1. Maerz 00:30 Wiener Zeit gehoert in den Maerz, auch wenn derselbe
22
+ * Zeitpunkt in UTC noch im Februar liegt. Die eingebauten
23
+ * `getMonth()`/`getFullYear()` wuerden ihn auf einer UTC-Maschine in den
24
+ * Februar legen und den Monatsbericht auf den falschen Monat schicken.
25
+ */
26
+ export declare function reportMonthFromDate(date: Date): ReportMonth;
27
+ export declare function previousReportMonth(rm: ReportMonth): ReportMonth;
28
+ export declare function nextReportMonth(rm: ReportMonth): ReportMonth;
29
+ /** Schluessel-Format wie `ReportMonth.toString()` im Flutter-Paket, z. B. `"march_2026"`. */
30
+ export declare function reportMonthKey(rm: ReportMonth): string;
31
+ /** Deutsches Anzeige-Format wie `ReportMonth.readable` im Flutter-Paket, z. B. `"März 2026"`. */
32
+ export declare function reportMonthReadable(rm: ReportMonth): string;
@@ -0,0 +1,58 @@
1
+ import { toViennaWallClock } from '../vienna-time.js';
2
+ // Reihenfolge wie `KeckMonth.values` im Flutter-Paket (Index 0 = Januar).
3
+ const MONTH_KEYS = [
4
+ 'january',
5
+ 'february',
6
+ 'march',
7
+ 'april',
8
+ 'may',
9
+ 'june',
10
+ 'july',
11
+ 'august',
12
+ 'september',
13
+ 'october',
14
+ 'november',
15
+ 'december',
16
+ ];
17
+ const MONTH_NAMES_DE = [
18
+ 'Januar',
19
+ 'Februar',
20
+ 'März',
21
+ 'April',
22
+ 'Mai',
23
+ 'Juni',
24
+ 'Juli',
25
+ 'August',
26
+ 'September',
27
+ 'Oktober',
28
+ 'November',
29
+ 'Dezember',
30
+ ];
31
+ /**
32
+ * Berichtsmonat eines Zeitpunkts — eingeordnet nach **Wiener** Zeit, nicht
33
+ * nach der Zeitzone des ausfuehrenden Rechners.
34
+ *
35
+ * Der Geschaeftsmonat ist ein oesterreichischer Kalenderwert: ein Beleg vom
36
+ * 1. Maerz 00:30 Wiener Zeit gehoert in den Maerz, auch wenn derselbe
37
+ * Zeitpunkt in UTC noch im Februar liegt. Die eingebauten
38
+ * `getMonth()`/`getFullYear()` wuerden ihn auf einer UTC-Maschine in den
39
+ * Februar legen und den Monatsbericht auf den falschen Monat schicken.
40
+ */
41
+ export function reportMonthFromDate(date) {
42
+ const wanduhr = toViennaWallClock(date);
43
+ return { month: wanduhr.month, year: wanduhr.year };
44
+ }
45
+ export function previousReportMonth(rm) {
46
+ return rm.month === 1 ? { month: 12, year: rm.year - 1 } : { month: rm.month - 1, year: rm.year };
47
+ }
48
+ export function nextReportMonth(rm) {
49
+ return rm.month === 12 ? { month: 1, year: rm.year + 1 } : { month: rm.month + 1, year: rm.year };
50
+ }
51
+ /** Schluessel-Format wie `ReportMonth.toString()` im Flutter-Paket, z. B. `"march_2026"`. */
52
+ export function reportMonthKey(rm) {
53
+ return `${MONTH_KEYS[rm.month - 1]}_${rm.year}`;
54
+ }
55
+ /** Deutsches Anzeige-Format wie `ReportMonth.readable` im Flutter-Paket, z. B. `"März 2026"`. */
56
+ export function reportMonthReadable(rm) {
57
+ return `${MONTH_NAMES_DE[rm.month - 1]} ${rm.year}`;
58
+ }