@kreiseck/kasseneck-api 1.11.1 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +2 -1
  3. package/dist/cjs/client/aufrufe.d.ts +4 -4
  4. package/dist/cjs/client/aufrufe.js +15 -0
  5. package/dist/cjs/client/receipts.d.ts +5 -0
  6. package/dist/cjs/client/receipts.js +65 -6
  7. package/dist/cjs/enums/voucher-action.d.ts +2 -0
  8. package/dist/cjs/enums/voucher-action.js +2 -0
  9. package/dist/cjs/enums/voucher-type.d.ts +10 -0
  10. package/dist/cjs/enums/voucher-type.js +10 -0
  11. package/dist/cjs/index.d.ts +3 -3
  12. package/dist/cjs/index.js +8 -3
  13. package/dist/cjs/models/index.d.ts +2 -2
  14. package/dist/cjs/models/index.js +6 -2
  15. package/dist/cjs/models/receipt-errors.d.ts +1 -1
  16. package/dist/cjs/models/receipt-errors.js +2 -0
  17. package/dist/cjs/models/receipt-item.d.ts +11 -3
  18. package/dist/cjs/models/receipt-item.js +22 -1
  19. package/dist/cjs/models/receipt.d.ts +13 -1
  20. package/dist/cjs/models/receipt.js +18 -2
  21. package/dist/cjs/models/voucher.d.ts +57 -4
  22. package/dist/cjs/models/voucher.js +111 -3
  23. package/dist/cjs/partner/fehler.d.ts +1 -1
  24. package/dist/cjs/partner/fehler.js +2 -0
  25. package/dist/cjs/partner/index.d.ts +1 -1
  26. package/dist/cjs/partner/typen.d.ts +7 -1
  27. package/dist/cjs/partner/typen.js +3 -0
  28. package/dist/cjs/pos/client.d.ts +2 -1
  29. package/dist/cjs/pos/client.js +3 -1
  30. package/dist/cjs/pos/gutschein.d.ts +90 -0
  31. package/dist/cjs/pos/gutschein.js +164 -0
  32. package/dist/cjs/pos/index.d.ts +3 -2
  33. package/dist/cjs/pos/index.js +13 -2
  34. package/dist/cjs/pos/settings.d.ts +3 -0
  35. package/dist/cjs/pos/settings.js +12 -10
  36. package/dist/cjs/pos/texte.d.ts +229 -0
  37. package/dist/cjs/pos/texte.js +96 -1
  38. package/dist/cjs/react/index.js +8 -2
  39. package/dist/cjs/receipt/due.d.ts +83 -2
  40. package/dist/cjs/receipt/due.js +202 -36
  41. package/dist/cjs/receipt/grid.js +13 -1
  42. package/dist/cjs/receipt/gutschein-plan.d.ts +104 -0
  43. package/dist/cjs/receipt/gutschein-plan.js +360 -0
  44. package/dist/cjs/receipt/index.d.ts +1 -1
  45. package/dist/cjs/receipt/index.js +3 -0
  46. package/dist/cjs/receipt/layout.js +175 -8
  47. package/dist/cjs/register/pairing.d.ts +21 -1
  48. package/dist/cjs/register/pairing.js +17 -0
  49. package/dist/cjs/stored/bon-layout.d.ts +8 -0
  50. package/dist/cjs/stored/bon-layout.js +23 -0
  51. package/dist/cjs/stored/draht.d.ts +3 -1
  52. package/dist/cjs/stored/draht.js +53 -6
  53. package/dist/cjs/stored/einstellungen.js +2 -1
  54. package/dist/cjs/stored/gutscheine.d.ts +3 -0
  55. package/dist/cjs/stored/gutscheine.js +60 -0
  56. package/dist/cjs/stored/index.js +2 -17
  57. package/dist/cjs/stored/vokabular.d.ts +6 -4
  58. package/dist/cjs/stored/vokabular.js +48 -2
  59. package/dist/cjs/version.d.ts +1 -1
  60. package/dist/cjs/version.js +1 -1
  61. package/dist/esm/client/aufrufe.d.ts +4 -4
  62. package/dist/esm/client/aufrufe.js +15 -0
  63. package/dist/esm/client/receipts.d.ts +5 -0
  64. package/dist/esm/client/receipts.js +66 -8
  65. package/dist/esm/enums/voucher-action.d.ts +2 -0
  66. package/dist/esm/enums/voucher-action.js +2 -0
  67. package/dist/esm/enums/voucher-type.d.ts +10 -0
  68. package/dist/esm/enums/voucher-type.js +10 -0
  69. package/dist/esm/index.d.ts +3 -3
  70. package/dist/esm/index.js +3 -3
  71. package/dist/esm/models/index.d.ts +2 -2
  72. package/dist/esm/models/index.js +2 -2
  73. package/dist/esm/models/receipt-errors.d.ts +1 -1
  74. package/dist/esm/models/receipt-errors.js +2 -0
  75. package/dist/esm/models/receipt-item.d.ts +11 -3
  76. package/dist/esm/models/receipt-item.js +20 -1
  77. package/dist/esm/models/receipt.d.ts +13 -1
  78. package/dist/esm/models/receipt.js +18 -2
  79. package/dist/esm/models/voucher.d.ts +57 -4
  80. package/dist/esm/models/voucher.js +108 -3
  81. package/dist/esm/partner/fehler.d.ts +1 -1
  82. package/dist/esm/partner/fehler.js +2 -0
  83. package/dist/esm/partner/index.d.ts +1 -1
  84. package/dist/esm/partner/typen.d.ts +7 -1
  85. package/dist/esm/partner/typen.js +3 -0
  86. package/dist/esm/pos/client.d.ts +2 -1
  87. package/dist/esm/pos/client.js +3 -1
  88. package/dist/esm/pos/gutschein.d.ts +90 -0
  89. package/dist/esm/pos/gutschein.js +158 -0
  90. package/dist/esm/pos/index.d.ts +3 -2
  91. package/dist/esm/pos/index.js +4 -2
  92. package/dist/esm/pos/settings.d.ts +3 -0
  93. package/dist/esm/pos/settings.js +2 -0
  94. package/dist/esm/pos/texte.d.ts +229 -0
  95. package/dist/esm/pos/texte.js +94 -0
  96. package/dist/esm/react/index.js +8 -2
  97. package/dist/esm/receipt/due.d.ts +83 -2
  98. package/dist/esm/receipt/due.js +198 -34
  99. package/dist/esm/receipt/grid.js +13 -1
  100. package/dist/esm/receipt/gutschein-plan.d.ts +104 -0
  101. package/dist/esm/receipt/gutschein-plan.js +352 -0
  102. package/dist/esm/receipt/index.d.ts +1 -1
  103. package/dist/esm/receipt/index.js +1 -1
  104. package/dist/esm/receipt/layout.js +175 -8
  105. package/dist/esm/register/pairing.d.ts +21 -1
  106. package/dist/esm/register/pairing.js +16 -0
  107. package/dist/esm/stored/bon-layout.d.ts +8 -0
  108. package/dist/esm/stored/bon-layout.js +20 -0
  109. package/dist/esm/stored/draht.d.ts +3 -1
  110. package/dist/esm/stored/draht.js +52 -6
  111. package/dist/esm/stored/einstellungen.js +3 -2
  112. package/dist/esm/stored/gutscheine.d.ts +3 -0
  113. package/dist/esm/stored/gutscheine.js +56 -0
  114. package/dist/esm/stored/index.js +2 -17
  115. package/dist/esm/stored/vokabular.d.ts +6 -4
  116. package/dist/esm/stored/vokabular.js +48 -2
  117. package/dist/esm/version.d.ts +1 -1
  118. package/dist/esm/version.js +1 -1
  119. package/fixtures/expected/voucher-cancellation.grid32.txt +30 -0
  120. package/fixtures/expected/voucher-cancellation.grid48.txt +29 -0
  121. package/fixtures/expected/voucher-cancellation.lines.json +252 -0
  122. package/fixtures/expected/voucher-cancellation.sheet32.json +206 -0
  123. package/fixtures/expected/voucher-cancellation.sheet48.json +200 -0
  124. package/fixtures/expected/voucher-multi-purpose-redeem.grid32.txt +25 -0
  125. package/fixtures/expected/voucher-multi-purpose-redeem.grid48.txt +25 -0
  126. package/fixtures/expected/voucher-multi-purpose-redeem.lines.json +259 -0
  127. package/fixtures/expected/voucher-multi-purpose-redeem.sheet32.json +176 -0
  128. package/fixtures/expected/voucher-multi-purpose-redeem.sheet48.json +176 -0
  129. package/fixtures/expected/voucher-multi-purpose-sale.grid32.txt +24 -0
  130. package/fixtures/expected/voucher-multi-purpose-sale.grid48.txt +23 -0
  131. package/fixtures/expected/voucher-multi-purpose-sale.lines.json +216 -0
  132. package/fixtures/expected/voucher-multi-purpose-sale.sheet32.json +170 -0
  133. package/fixtures/expected/voucher-multi-purpose-sale.sheet48.json +164 -0
  134. package/fixtures/expected/voucher-payout.grid32.txt +23 -0
  135. package/fixtures/expected/voucher-payout.grid48.txt +22 -0
  136. package/fixtures/expected/voucher-payout.lines.json +216 -0
  137. package/fixtures/expected/voucher-payout.sheet32.json +164 -0
  138. package/fixtures/expected/voucher-payout.sheet48.json +158 -0
  139. package/fixtures/expected/voucher-service-redeem.grid32.txt +26 -0
  140. package/fixtures/expected/voucher-service-redeem.grid48.txt +25 -0
  141. package/fixtures/expected/voucher-service-redeem.lines.json +261 -0
  142. package/fixtures/expected/voucher-service-redeem.sheet32.json +182 -0
  143. package/fixtures/expected/voucher-service-redeem.sheet48.json +176 -0
  144. package/fixtures/expected/voucher-single-purpose-redeem-exempt.grid32.txt +30 -0
  145. package/fixtures/expected/voucher-single-purpose-redeem-exempt.grid48.txt +29 -0
  146. package/fixtures/expected/voucher-single-purpose-redeem-exempt.lines.json +331 -0
  147. package/fixtures/expected/voucher-single-purpose-redeem-exempt.sheet32.json +206 -0
  148. package/fixtures/expected/voucher-single-purpose-redeem-exempt.sheet48.json +200 -0
  149. package/fixtures/expected/voucher-single-purpose-redeem.grid32.txt +25 -0
  150. package/fixtures/expected/voucher-single-purpose-redeem.grid48.txt +24 -0
  151. package/fixtures/expected/voucher-single-purpose-redeem.lines.json +246 -0
  152. package/fixtures/expected/voucher-single-purpose-redeem.sheet32.json +176 -0
  153. package/fixtures/expected/voucher-single-purpose-redeem.sheet48.json +170 -0
  154. package/fixtures/expected/voucher-single-purpose-sale.grid32.txt +26 -0
  155. package/fixtures/expected/voucher-single-purpose-sale.grid48.txt +24 -0
  156. package/fixtures/expected/voucher-single-purpose-sale.lines.json +225 -0
  157. package/fixtures/expected/voucher-single-purpose-sale.sheet32.json +182 -0
  158. package/fixtures/expected/voucher-single-purpose-sale.sheet48.json +170 -0
  159. package/fixtures/hobex-hps-codes.json +1 -1
  160. package/fixtures/invoice-api.schema.json +1 -1
  161. package/fixtures/invoice-texts.json +1 -1
  162. package/fixtures/manifest.json +64 -0
  163. package/fixtures/pos-texts.json +257 -1
  164. package/fixtures/receipt-due-generated.json +1 -1
  165. package/fixtures/receipt-due-voucher-generated.json +494 -0
  166. package/fixtures/receipts/voucher-cancellation.json +76 -0
  167. package/fixtures/receipts/voucher-multi-purpose-redeem.json +62 -0
  168. package/fixtures/receipts/voucher-multi-purpose-sale.json +63 -0
  169. package/fixtures/receipts/voucher-payout.json +65 -0
  170. package/fixtures/receipts/voucher-service-redeem.json +82 -0
  171. package/fixtures/receipts/voucher-single-purpose-redeem-exempt.json +86 -0
  172. package/fixtures/receipts/voucher-single-purpose-redeem.json +71 -0
  173. package/fixtures/receipts/voucher-single-purpose-sale.json +88 -0
  174. package/fixtures/surface.json +35 -5
  175. package/fixtures/v3/antworten/belege.json +3405 -3
  176. package/fixtures/v3/antworten/belegmail.json +5 -2
  177. package/fixtures/v3/antworten/kasse-belege.json +3423 -3
  178. package/fixtures/v3/antworten/kasse.json +621 -14
  179. package/fixtures/v3/antworten/lager.json +1 -1
  180. package/fixtures/v3/antworten/rechnungen.json +5 -2
  181. package/fixtures/v3/antworten/storno.json +214 -3
  182. package/fixtures/v3/stored/belege.json +5 -2
  183. package/fixtures/v3/stored/kasse.json +225 -4
  184. package/fixtures/v3/stored/rechnungen.json +5 -2
  185. package/fixtures/v3/v3-vokabular.json +1375 -23
  186. package/fixtures/v3/zahlbetrag-faelle.json +293 -3
  187. package/package.json +4 -1
@@ -9,6 +9,18 @@ export function isTipItem(item) {
9
9
  export function isDiscountItem(item) {
10
10
  return item != null && item.kind === 'discount';
11
11
  }
12
+ /**
13
+ * Gutschein-Position (Server, neue Gutscheinform)? `voucher` ist eine
14
+ * Einloesung oder ein Verkauf mit Umsatzsteuer-Wirkung, siehe
15
+ * [isVoucherFloatItem] fuer den durchlaufenden Posten.
16
+ */
17
+ export function isVoucherItem(item) {
18
+ return item != null && item.kind === 'voucher';
19
+ }
20
+ /** Gutschein-Position als durchlaufender Posten (Mehrzweck: Verkauf, Auszahlung)? */
21
+ export function isVoucherFloatItem(item) {
22
+ return item != null && item.kind === 'voucher_float';
23
+ }
12
24
  export function toReceiptItemPayload(item) {
13
25
  // Schreibpfad bleibt streng: ein unaufgeloester (unbekannter) Steuersatz
14
26
  // darf nicht unbesehen wieder hinausgehen.
@@ -37,6 +49,11 @@ export function toReceiptItemPayload(item) {
37
49
  // am Bon wieder als gewoehnliche Warenzeile mit "1 x" an.
38
50
  if (item.kind === 'discount')
39
51
  nutzlast.kind = 'discount';
52
+ // Gutschein-Positionen (vom Server) reisen mit: der Cache der Kasse schreibt
53
+ // gelesene Belege wieder, und ein Wunsch an den Server traegt sie nie
54
+ // (createReceipt weist sie als voucher_invalid ab).
55
+ if (item.kind === 'voucher' || item.kind === 'voucher_float')
56
+ nutzlast.kind = item.kind;
40
57
  // Artikel-Verweis reist mit (Erloesgruppen im Bericht); leere Werte nicht.
41
58
  if (item.articleId != null && item.articleId !== '')
42
59
  nutzlast.articleId = item.articleId;
@@ -81,7 +98,9 @@ export function fromReceiptItemPayload(payload) {
81
98
  }
82
99
  : payload.kind === 'discount'
83
100
  ? { kind: 'discount' }
84
- : {}),
101
+ : payload.kind === 'voucher' || payload.kind === 'voucher_float'
102
+ ? { kind: payload.kind }
103
+ : {}),
85
104
  // Artikel-Verweis erhalten (Storno-Spiegelung schreibt ihn wieder mit).
86
105
  ...(typeof payload.articleId === 'string' && payload.articleId !== '' ? { articleId: payload.articleId } : {}),
87
106
  // Lager: Bezug und Rueckgabe-Wahl einer Storno-Zeile (nur gelesen; ein
@@ -162,10 +162,22 @@ export declare function receiptValueVoucherSign(receipt: Receipt): 1 | -1;
162
162
  * mindert nichts: den Rabatt nimmt der Server dort ueber Ausgleichspositionen
163
163
  * (`kind: 'discount'`) zurueck, und belegToepfe verteilt einen Promo-Eintrag
164
164
  * nur auf eine positive Topfsumme, die ein Storno nie hat.
165
+ *
166
+ * Gutscheine der neuen Form (Spec 2026-10-14): ihr Betrag steht als Position
167
+ * (`kind: 'voucher'` bei Einzweck/Leistung, `'voucher_float'` im 0-%-Topf) und
168
+ * zaehlt hier schon mit den Positionen. Ein Eintrag mit `zeroRateBucket`
169
+ * (Server: `imNullTopf`, Mehrzweck-Verkauf ab dem Stichtag, Auszahlung) zaehlt
170
+ * darum nicht noch einmal -- sonst stuende der Betrag doppelt am Bon
171
+ * (Vorfall 16.10.2026: Verkauf ueber 30 € mit „Gesamt 60,00“). Eintraege der
172
+ * Arten `single_purpose`/`service` tragen keinen Fluss (wie
173
+ * gutschein-beleg.zahlbetrag, das nur `value`/`promo` an den Fluss gibt).
165
174
  */
166
175
  export declare function receiptSubSumCents(receipt: Receipt): number;
167
176
  /**
168
177
  * Gesamtsumme in **Cent** — Zwischensumme minus eingeloeste Wertgutscheine
169
- * (am Storno-Beleg plus, siehe [receiptValueVoucherSign]).
178
+ * (am Storno-Beleg plus, siehe [receiptValueVoucherSign]). Zwilling von
179
+ * zahlungen-core.wertgutscheinFlussCents: eine Auszahlung (`payout`) eines
180
+ * Wertgutscheins ohne `zeroRateBucket` mindert wie eine Einloesung; mit
181
+ * `zeroRateBucket` steht sie als Position und zaehlt nur dort.
170
182
  */
171
183
  export declare function receiptSumCents(receipt: Receipt): number;
@@ -149,11 +149,22 @@ export function receiptValueVoucherSign(receipt) {
149
149
  * mindert nichts: den Rabatt nimmt der Server dort ueber Ausgleichspositionen
150
150
  * (`kind: 'discount'`) zurueck, und belegToepfe verteilt einen Promo-Eintrag
151
151
  * nur auf eine positive Topfsumme, die ein Storno nie hat.
152
+ *
153
+ * Gutscheine der neuen Form (Spec 2026-10-14): ihr Betrag steht als Position
154
+ * (`kind: 'voucher'` bei Einzweck/Leistung, `'voucher_float'` im 0-%-Topf) und
155
+ * zaehlt hier schon mit den Positionen. Ein Eintrag mit `zeroRateBucket`
156
+ * (Server: `imNullTopf`, Mehrzweck-Verkauf ab dem Stichtag, Auszahlung) zaehlt
157
+ * darum nicht noch einmal -- sonst stuende der Betrag doppelt am Bon
158
+ * (Vorfall 16.10.2026: Verkauf ueber 30 € mit „Gesamt 60,00“). Eintraege der
159
+ * Arten `single_purpose`/`service` tragen keinen Fluss (wie
160
+ * gutschein-beleg.zahlbetrag, das nur `value`/`promo` an den Fluss gibt).
152
161
  */
153
162
  export function receiptSubSumCents(receipt) {
154
163
  const vz = receiptValueVoucherSign(receipt);
155
164
  let cents = receipt.items.reduce((acc, item) => acc + receiptItemTotalCents(item), 0);
156
165
  for (const voucher of receipt.vouchers) {
166
+ if (voucher.zeroRateBucket === true)
167
+ continue;
157
168
  if (vz === 1 && voucher.action === VoucherAction.redeem && voucher.type === VoucherType.promo) {
158
169
  cents -= voucher.valueCents ?? 0;
159
170
  }
@@ -165,13 +176,18 @@ export function receiptSubSumCents(receipt) {
165
176
  }
166
177
  /**
167
178
  * Gesamtsumme in **Cent** — Zwischensumme minus eingeloeste Wertgutscheine
168
- * (am Storno-Beleg plus, siehe [receiptValueVoucherSign]).
179
+ * (am Storno-Beleg plus, siehe [receiptValueVoucherSign]). Zwilling von
180
+ * zahlungen-core.wertgutscheinFlussCents: eine Auszahlung (`payout`) eines
181
+ * Wertgutscheins ohne `zeroRateBucket` mindert wie eine Einloesung; mit
182
+ * `zeroRateBucket` steht sie als Position und zaehlt nur dort.
169
183
  */
170
184
  export function receiptSumCents(receipt) {
171
185
  const vz = receiptValueVoucherSign(receipt);
172
186
  let cents = receiptSubSumCents(receipt);
173
187
  for (const voucher of receipt.vouchers) {
174
- if (voucher.action === VoucherAction.redeem && voucher.type === VoucherType.value) {
188
+ if (voucher.zeroRateBucket === true || voucher.type !== VoucherType.value)
189
+ continue;
190
+ if (voucher.action === VoucherAction.redeem || voucher.action === VoucherAction.payout) {
175
191
  cents -= vz * (voucher.valueCents ?? 0);
176
192
  }
177
193
  }
@@ -16,11 +16,41 @@ export interface Voucher {
16
16
  action: VoucherAction | string;
17
17
  type: VoucherType | string;
18
18
  valueCents?: number;
19
+ /** Neue Form: Betrag in Cent (Verkauf, Einloesung, Auszahlung). */
20
+ amountCents?: number;
21
+ /** Neue Form, Leistungsgutschein: verkaufter Artikel. */
22
+ articleId?: string;
23
+ /** Neue Form, Leistungsgutschein: Menge (Verkauf) bzw. eingeloeste Menge. */
24
+ quantity?: number;
25
+ /** Neue Form, Leistungsgutschein einloesen: Indizes der Belegpositionen. */
26
+ positions?: number[];
27
+ /** Neue Form, Auszahlung: Grund, 1 bis 200 Zeichen. */
28
+ reason?: string;
29
+ voucherType?: string;
30
+ voucherId?: string;
31
+ /** Letzte vier Zeichen des Codes; der Klartext steht nie am Beleg. */
32
+ codeSuffix?: string;
33
+ vatRateBp?: number;
34
+ article?: VoucherArticle;
35
+ balanceAfterCents?: number;
36
+ remainingQuantityAfter?: number;
37
+ taxedWith?: string;
38
+ exempt?: boolean;
39
+ zeroRateBucket?: boolean;
40
+ }
41
+ /** Artikel eines Leistungsgutscheins, wie der Server ihn am Beleg festhaelt. */
42
+ export interface VoucherArticle {
43
+ id: string;
44
+ name: string;
45
+ vatRateBp: number;
46
+ priceCents: number;
19
47
  }
20
48
  /**
21
- * Nutzlast eines Gutscheins. Geschrieben wird nur `valueCents` (ganze Cent);
22
- * `value` (Euro) kommt nur beim Lesen vor: der Server legt es in seinen
23
- * Antworten daneben, gelesen wird es nur, wenn `valueCents` fehlt.
49
+ * Nutzlast eines Gutscheins. Altform: nur `valueCents` (ganze Cent); `value`
50
+ * (Euro) kommt nur beim Lesen vor: der Server legt es in seinen Antworten
51
+ * daneben, gelesen wird es nur, wenn `valueCents` fehlt. Neue Form: roh mit
52
+ * `amountCents` und den weiteren Feldern; gesetzte Feldern gehen hinaus,
53
+ * fehlende fehlen (kein `valueCents: null` an der neuen Form).
24
54
  * `name` und `code` gehen nur hinaus, wenn sie gesetzt sind.
25
55
  */
26
56
  export interface VoucherPayload {
@@ -29,8 +59,31 @@ export interface VoucherPayload {
29
59
  action: string;
30
60
  type: string;
31
61
  value?: number | null;
32
- valueCents: number | null;
62
+ valueCents?: number | null;
63
+ amountCents?: number;
64
+ articleId?: string;
65
+ quantity?: number;
66
+ positions?: number[];
67
+ reason?: string;
68
+ voucherType?: string;
69
+ voucherId?: string;
70
+ codeSuffix?: string;
71
+ vatRateBp?: number;
72
+ article?: VoucherArticle;
73
+ balanceAfterCents?: number;
74
+ remainingQuantityAfter?: number;
75
+ taxedWith?: string;
76
+ exempt?: boolean;
77
+ zeroRateBucket?: boolean;
33
78
  }
79
+ /** Arten der neuen Gutscheinform (die Altwerte sind `value` und `promo`). */
80
+ export declare const NEUE_GUTSCHEINARTEN: readonly string[];
81
+ /** Gehoert der Gutschein zur neuen Form (Art oder Aktion `payout`)? */
82
+ export declare function isNewFormVoucher(voucher: Pick<Voucher, 'type' | 'action'>): boolean;
83
+ /** Felder, die nur der Server setzt; an einem Wunsch sind sie `voucher_invalid`. */
84
+ export declare const GUTSCHEIN_SERVERFELDER: readonly ["voucherId", "codeSuffix", "zeroRateBucket", "voucherType"];
85
+ /** Welche Serverfelder tragt der Gutschein (leere Liste = keines)? */
86
+ export declare function voucherServerFields(voucher: Voucher): string[];
34
87
  export declare function toVoucherPayload(voucher: Voucher): VoucherPayload;
35
88
  /**
36
89
  * Ist der Gutschein an das Backend sendbar? Zwilling von `KeckVoucher.isValid`
@@ -1,13 +1,46 @@
1
1
  import { VoucherAction, VoucherType } from '../enums/index.js';
2
2
  import { euroToCents } from '../money.js';
3
3
  import { readEnumKey, requireEnumKey } from './enum-payload.js';
4
+ /** Arten der neuen Gutscheinform (die Altwerte sind `value` und `promo`). */
5
+ export const NEUE_GUTSCHEINARTEN = [
6
+ VoucherType.multi_purpose,
7
+ VoucherType.single_purpose,
8
+ VoucherType.service,
9
+ VoucherType.promotion,
10
+ ];
11
+ /** Gehoert der Gutschein zur neuen Form (Art oder Aktion `payout`)? */
12
+ export function isNewFormVoucher(voucher) {
13
+ return NEUE_GUTSCHEINARTEN.includes(voucher.type) || voucher.action === VoucherAction.payout;
14
+ }
15
+ /** Felder, die nur der Server setzt; an einem Wunsch sind sie `voucher_invalid`. */
16
+ export const GUTSCHEIN_SERVERFELDER = ['voucherId', 'codeSuffix', 'zeroRateBucket', 'voucherType'];
17
+ /** Welche Serverfelder tragt der Gutschein (leere Liste = keines)? */
18
+ export function voucherServerFields(voucher) {
19
+ return GUTSCHEIN_SERVERFELDER.filter((feld) => voucher[feld] != null);
20
+ }
21
+ const NEUE_FELDER = [
22
+ 'amountCents', 'articleId', 'quantity', 'positions', 'reason', 'voucherType', 'voucherId', 'codeSuffix',
23
+ 'vatRateBp', 'article', 'balanceAfterCents', 'remainingQuantityAfter', 'taxedWith', 'exempt', 'zeroRateBucket',
24
+ ];
4
25
  export function toVoucherPayload(voucher) {
26
+ const action = requireEnumKey(VoucherAction, voucher.action, 'Gutschein-Aktion');
27
+ const type = requireEnumKey(VoucherType, voucher.type, 'Gutscheinart');
28
+ // Felder der neuen Form gehen roh hinaus, soweit gesetzt (auch an einem
29
+ // gelesenen Altbeleg: dort fehlen sie, die Nutzlast bleibt byte-gleich).
30
+ const roh = voucher;
31
+ const neu = {};
32
+ for (const feld of NEUE_FELDER)
33
+ if (roh[feld] != null)
34
+ neu[feld] = roh[feld];
5
35
  return {
6
- action: requireEnumKey(VoucherAction, voucher.action, 'Gutschein-Aktion'),
7
- type: requireEnumKey(VoucherType, voucher.type, 'Gutscheinart'),
8
- valueCents: voucher.valueCents ?? null,
36
+ action,
37
+ type,
38
+ // Die neue Form kennt kein `valueCents`; nur ein gelesener Eintrag (die
39
+ // Auszahlung steht beim Server als Wert mit Cent) traegt es weiter.
40
+ ...(isNewFormVoucher(voucher) && voucher.valueCents == null ? {} : { valueCents: voucher.valueCents ?? null }),
9
41
  ...(voucher.code != null ? { code: voucher.code } : {}),
10
42
  ...(voucher.name != null ? { name: voucher.name } : {}),
43
+ ...neu,
11
44
  };
12
45
  }
13
46
  /**
@@ -17,6 +50,8 @@ export function toVoucherPayload(voucher) {
17
50
  * gesetzter Wert muss positiv sein.
18
51
  */
19
52
  export function voucherIsValid(voucher) {
53
+ if (isNewFormVoucher(voucher))
54
+ return newFormVoucherIsValid(voucher);
20
55
  if (voucher.type === VoucherType.value && voucher.valueCents == null) {
21
56
  return false;
22
57
  }
@@ -58,5 +93,75 @@ export function fromVoucherPayload(payload) {
58
93
  action: readEnumKey(VoucherAction, payload.action),
59
94
  type: readEnumKey(VoucherType, payload.type),
60
95
  valueCents,
96
+ ...lesenNeu(payload),
61
97
  };
62
98
  }
99
+ /** Felder der neuen Form beim Lesen: nur was dasteht (Altbelege bleiben schlank). */
100
+ function lesenNeu(payload) {
101
+ const roh = payload;
102
+ const neu = {};
103
+ for (const feld of NEUE_FELDER)
104
+ if (roh[feld] != null)
105
+ neu[feld] = roh[feld];
106
+ return neu;
107
+ }
108
+ /** Grenzen wie der Server (gutschein-beleg): Betrag 1 bis 1.000.000 Cent, Menge 1 bis 100. */
109
+ const MAX_BETRAG_CENTS = 1_000_000;
110
+ const MAX_STUECK = 100;
111
+ const MAX_GRUND = 200;
112
+ const istCent = (n) => typeof n === 'number' && Number.isInteger(n) && n >= 1 && n <= MAX_BETRAG_CENTS;
113
+ const istMenge = (n) => typeof n === 'number' && Number.isInteger(n) && n >= 1 && n <= MAX_STUECK;
114
+ const hatText = (t) => typeof t === 'string' && t.trim().length > 0;
115
+ /**
116
+ * Wunsch der neuen Form sendbar? Bildet die Regeln des Servers ab: Serverfelder
117
+ * nie, Betrag/Menge ganz und positiv, Code bei Einloesung und Auszahlung,
118
+ * Auszahlung nur Mehrzweck/Einzweck mit Grund (1 bis 200 Zeichen), Aktion nur
119
+ * einloesbar, Leistung braucht Artikel und Menge (Verkauf) bzw. Positionen
120
+ * (Einloesung). Felder, die zu einer anderen Aktion/Art gehoeren, sind
121
+ * ebenfalls nicht erlaubt (der Server wiese sie ab).
122
+ */
123
+ function newFormVoucherIsValid(v) {
124
+ if (voucherServerFields(v).length > 0)
125
+ return false;
126
+ const r = v;
127
+ for (const feld of ['vatRateBp', 'article', 'balanceAfterCents', 'remainingQuantityAfter', 'taxedWith', 'exempt']) {
128
+ if (r[feld] != null)
129
+ return false;
130
+ }
131
+ if (v.valueCents != null)
132
+ return false;
133
+ const allein = v.type === VoucherType.multi_purpose || v.type === VoucherType.single_purpose;
134
+ if (v.action === VoucherAction.payout) {
135
+ return allein && hatText(v.code) && istCent(v.amountCents) && hatText(v.reason) && v.reason.trim().length <= MAX_GRUND
136
+ && v.articleId == null && v.quantity == null && v.positions == null;
137
+ }
138
+ if (v.reason != null)
139
+ return false;
140
+ if (allein) {
141
+ if (v.articleId != null || v.quantity != null || v.positions != null)
142
+ return false;
143
+ if (v.action === VoucherAction.sell)
144
+ return istCent(v.amountCents);
145
+ if (v.action === VoucherAction.redeem)
146
+ return hatText(v.code) && istCent(v.amountCents);
147
+ return false;
148
+ }
149
+ if (v.type === VoucherType.service) {
150
+ if (v.amountCents != null)
151
+ return false;
152
+ if (v.action === VoucherAction.sell) {
153
+ return hatText(v.articleId) && istMenge(v.quantity) && v.positions == null;
154
+ }
155
+ if (v.action === VoucherAction.redeem) {
156
+ return hatText(v.code) && Array.isArray(v.positions) && v.positions.length > 0
157
+ && v.positions.every((i) => Number.isInteger(i) && i >= 0) && new Set(v.positions).size === v.positions.length && v.articleId == null && v.quantity == null;
158
+ }
159
+ return false;
160
+ }
161
+ if (v.type === VoucherType.promotion) {
162
+ return v.action === VoucherAction.redeem && hatText(v.code)
163
+ && v.amountCents == null && v.articleId == null && v.quantity == null && v.positions == null;
164
+ }
165
+ // Altart mit neuer Aktion (payout + value/promo): nicht sendbar.
166
+ return false;
167
+ }
@@ -61,7 +61,7 @@ import { KasseneckApiError } from '../client/errors.js';
61
61
  *
62
62
  * Reihenfolge und Bestand wie im Abzug des Backends.
63
63
  */
64
- export declare const PARTNER_ERROR_CODES: readonly ["validation", "rate_limited", "app_not_found", "app_not_accepted", "live_not_allowed", "customer_exists", "customer_conflict", "customer_limit", "access_not_allowed", "email_taken", "no_email", "tax_number_missing", "fon_missing", "signature_pending", "signature_missing", "signature_unknown", "signature_ambiguous", "signature_not_ready", "signature_limit", "signature_failed", "module_inactive", "cashregister_limit", "cashregister_not_found", "contracts_pending", "kind_not_allowed", "mode_not_allowed", "power_of_attorney_missing", "not_found", "no_version", "unknown_version", "text_changed", "already_accepted", "activation_failed", "webhook_limit", "webhook_inactive", "event_not_subscribed"];
64
+ export declare const PARTNER_ERROR_CODES: readonly ["validation", "rate_limited", "app_not_found", "app_not_accepted", "live_not_allowed", "customer_exists", "customer_conflict", "customer_limit", "access_not_allowed", "email_taken", "no_email", "tax_number_missing", "fon_missing", "signature_pending", "signature_missing", "signature_unknown", "signature_ambiguous", "signature_not_ready", "signature_limit", "signature_failed", "module_inactive", "cashregister_limit", "cashregister_not_found", "contracts_pending", "kind_not_allowed", "mode_not_allowed", "power_of_attorney_missing", "not_found", "no_version", "unknown_version", "text_changed", "already_accepted", "activation_failed", "activation_in_progress", "webhook_limit", "webhook_inactive", "event_not_subscribed"];
65
65
  /**
66
66
  * Die Codes, die nur im **Partner-Portal** entstehen — beim Pflegen der App,
67
67
  * der Schluessel, der Mitglieder und der Signaturkarten.
@@ -101,6 +101,7 @@ export const PARTNER_ERROR_CODES = [
101
101
  'text_changed',
102
102
  'already_accepted',
103
103
  'activation_failed',
104
+ 'activation_in_progress',
104
105
  // Webhooks
105
106
  'webhook_limit',
106
107
  'webhook_inactive',
@@ -208,6 +209,7 @@ const RAT = {
208
209
  text_changed: 'Der gezeigte Vertragstext hat sich seit dem Laden geaendert (data.textHash traegt die aktuell geltende Pruefsumme). Neu laden und danach erneut bestaetigen lassen.',
209
210
  already_accepted: 'Diese Fassung ist bereits bestaetigt (data.contractId). Nichts weiter zu tun.',
210
211
  activation_failed: 'Die Inbetriebnahme blieb an data.step haengen (ggf. data.rc). activateCashregister erneut aufrufen — jeder Schritt ist idempotent, der Lauf setzt an der Bruchstelle an.',
212
+ activation_in_progress: 'Die Inbetriebnahme dieser Kasse laeuft bereits. Kurz warten und den Stand abfragen, nicht erneut anstossen.',
211
213
  webhook_limit: 'Hoechstens 10 Webhook-Endpunkte je Partner. Einen ungenutzten loeschen.',
212
214
  webhook_inactive: 'Der Webhook steht auf active:false. Zuerst aktivieren, dann erneut proben.',
213
215
  event_not_subscribed: 'Der Endpunkt abonniert dieses Ereignis nicht — auch eine Probe bekommt nur, was in seiner events-Liste steht. events erweitern und erneut versuchen.',
@@ -28,6 +28,6 @@ export { getPartnerInfo, createPartnerCustomer, listPartnerCustomers, checkPartn
28
28
  export { createPartnerWebhook, listPartnerWebhooks, rotatePartnerWebhookSecret, updatePartnerWebhook, deletePartnerWebhook, sendPartnerWebhookTest, listPartnerWebhookDeliveries, parseWebhookEvent, isPartnerWebhookEvent, PARTNER_WEBHOOK_EVENTS, WEBHOOK_ENVELOPE_FIELDS, WEBHOOK_DELIVERY_STATUSES, type PartnerWebhookEvent, type PartnerWebhookEventType, type PartnerWebhook, type CreateWebhookOptions, type CreateWebhookResult, type DeleteWebhookResult, type WebhookApiVersion, type WebhookDeliveryStatus, type WebhookTestDelivery, type ContractAcceptedEventData, type SignatureFailedEventData, type CashregisterFailedEventData, type WebhookPatch, type WebhookList, type WebhookDelivery, type WebhookTestResult, type WebhookEventResult, } from './webhooks.js';
29
29
  export { verifyWebhookSignature, parseSignatureHeader, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_EVENT_HEADER, WEBHOOK_DELIVERY_HEADER, WEBHOOK_TOLERANCE_SEC, WEBHOOK_RETRY_PLAN_SEC, WEBHOOK_MAX_ATTEMPTS, WEBHOOK_TIMEOUT_MS, WEBHOOK_LIMIT, type VerifyWebhookOptions, type WebhookVerifyResult, type WebhookVerifyReason, } from './webhook-signatur.js';
30
30
  export { PARTNER_ENVS, LEGAL_FORMS, AUSTRIAN_STATES, CONTACT_ROLES, AVV_MODES, FEE_INTERVALS, CONTRACT_KINDS, CONTRACT_SOURCES, SIGNATURE_HISTORY_REASONS, SIGNATURE_ERROR_CODES, } from './typen.js';
31
- export type { PartnerEnv, PartnerScope, PartnerApp, PartnerInfo, LegalForm, AustrianState, ContactRole, AvvMode, FeeInterval, PartnerFee, SignatureHistoryReason, SignatureErrorCode, RequestSignatureOptions, CustomerSignature, ContractKind, ContractSource, ReportCustomerContractOptions, ReportCustomerContractResult, BusinessAddress, BusinessTaxDetails, BusinessContact, BusinessTaxAdvisor, Business, CreateCustomerOptions, CreateCustomerResult, PartnerCustomerStatus, PartnerCustomerSummary, AvvStatus, ContractStatus, PartnerCustomerFonStatus, ListCustomersOptions, PartnerCustomerList, PartnerCustomer, FonLinkResult, SignatureRequestStatus, SignatureHistoryEntry, SignatureRequest, RequestSignatureResult, CustomerSignatureStatus, CashregisterActivationStep, CustomerCashregisterStatus, CustomerCashregister, CreateCashregisterOptions, CreateCashregisterResult, ActivateCashregisterResult, CustomerCashregisterList, CustomerCashregisterCredential, CustomerCredentials, } from './typen.js';
31
+ export type { PartnerEnv, PartnerScope, PartnerApp, PartnerInfo, LegalForm, AustrianState, ContactRole, AvvMode, FeeInterval, PartnerFee, SignatureHistoryReason, SignatureFulfillment, SignatureErrorCode, RequestSignatureOptions, CustomerSignature, ContractKind, ContractSource, ReportCustomerContractOptions, ReportCustomerContractResult, BusinessAddress, BusinessTaxDetails, BusinessContact, BusinessTaxAdvisor, Business, CreateCustomerOptions, CreateCustomerResult, PartnerCustomerStatus, PartnerCustomerSummary, AvvStatus, ContractStatus, PartnerCustomerFonStatus, ListCustomersOptions, PartnerCustomerList, PartnerCustomer, FonLinkResult, SignatureRequestStatus, SignatureHistoryEntry, SignatureRequest, RequestSignatureResult, CustomerSignatureStatus, CashregisterActivationStep, CustomerCashregisterStatus, CustomerCashregister, CreateCashregisterOptions, CreateCashregisterResult, ActivateCashregisterResult, CustomerCashregisterList, CustomerCashregisterCredential, CustomerCredentials, } from './typen.js';
32
32
  /** `credentials:read` — nicht im Standardsatz, siehe typen.ts. */
33
33
  export { SCOPE_CREDENTIALS } from './typen.js';
@@ -382,7 +382,7 @@ export type SignatureRequestStatus = 'requested' | 'assigned' | 'registered' | '
382
382
  * Gruende in der Historie eines Signaturantrags. `card_entered` und
383
383
  * `finanzonline` hiessen unter `/v1` `karte_eingetragen` und `fon`.
384
384
  */
385
- export declare const SIGNATURE_HISTORY_REASONS: readonly ["api", "portal", "card_entered", "finanzonline", "automation_off", "test_environment", "no_stock"];
385
+ export declare const SIGNATURE_HISTORY_REASONS: readonly ["api", "portal", "card_entered", "finanzonline", "automation_off", "test_environment", "no_stock", "card_pool_activated", "activation_run", "finanzonline_completed"];
386
386
  /** Offen fuer spaeter ergaenzte Gruende, siehe [SIGNATURE_HISTORY_REASONS]. */
387
387
  export type SignatureHistoryReason = typeof SIGNATURE_HISTORY_REASONS[number] | (string & {});
388
388
  /**
@@ -400,6 +400,8 @@ export interface SignatureHistoryEntry {
400
400
  at: number;
401
401
  reason: SignatureHistoryReason | null;
402
402
  }
403
+ /** Erfuellungsweg eines Signaturantrags; offen fuer spaeter ergaenzte Werte. */
404
+ export type SignatureFulfillment = 'automatic' | 'manual' | (string & {});
403
405
  export interface SignatureRequest {
404
406
  requestId: string;
405
407
  status: SignatureRequestStatus;
@@ -408,6 +410,8 @@ export interface SignatureRequest {
408
410
  kind: string;
409
411
  vdaId: string | null;
410
412
  signatureId: string | null;
413
+ /** Wie der Antrag erfuellt wird: aus dem Kartenvorrat oder von Hand. */
414
+ fulfillment?: SignatureFulfillment;
411
415
  error: {
412
416
  code: SignatureErrorCode | null;
413
417
  message: string | null;
@@ -442,6 +446,8 @@ export interface CustomerSignature {
442
446
  status: SignatureRequestStatus | 'decommissioned';
443
447
  statusText: string;
444
448
  inProgress: boolean;
449
+ /** Wie der Antrag erfuellt wird: aus dem Kartenvorrat oder von Hand. */
450
+ fulfillment?: SignatureFulfillment;
445
451
  ready: boolean;
446
452
  kind: string;
447
453
  vdaId: string | null;
@@ -97,6 +97,9 @@ export const SIGNATURE_HISTORY_REASONS = [
97
97
  'automation_off',
98
98
  'test_environment',
99
99
  'no_stock',
100
+ 'card_pool_activated',
101
+ 'activation_run',
102
+ 'finanzonline_completed',
100
103
  ];
101
104
  /**
102
105
  * `error.code` eines Signaturantrags oder einer Signatur (`SignatureRequest`,
@@ -4,10 +4,11 @@ import { type PosSettings, type PosBusinessSettings, type PosDeviceSettings } fr
4
4
  export declare function getPosSettings(transport: InternerTransport, options?: {
5
5
  deviceId?: string;
6
6
  }): Promise<PosSettings>;
7
- /** `{business, device}` einer Antwort, gemischt mit den Standardwerten. */
7
+ /** `{business, device, vouchers}` einer Antwort, gemischt mit den Standardwerten. */
8
8
  export declare function posSettingsFromWire(data: {
9
9
  business?: unknown;
10
10
  device?: unknown;
11
+ vouchers?: unknown;
11
12
  } | null | undefined): PosSettings;
12
13
  /** Betriebsweite Einstellungen schreiben (Recht `layout`); liefert den gemischten Stand. */
13
14
  export declare function setMyPosSettings(transport: InternerTransport, business: Partial<PosBusinessSettings>): Promise<PosBusinessSettings>;
@@ -1,4 +1,5 @@
1
1
  import { KasseneckValidationError } from '../client/errors.js';
2
+ import { posVoucherSettingsFromWire } from './gutschein.js';
2
3
  import { POS_BUSINESS_DEFAULTS, POS_DEVICE_DEFAULTS, POS_BUSINESS_VALUES, POS_DEVICE_VALUES, POS_SHORTCUT_ACTIONS, POS_DEVICE_OPTIONAL_FIELDS, POS_BUSINESS_OPTIONAL_FIELDS, mergePosSettings, posShortcutConflict, _istAltwert0x, _optionalerWert, } from './settings.js';
3
4
  /*
4
5
  * Die Einstellungs-Aufrufe am Draht `/api/v3`: Parameter und Antwort heissen
@@ -27,9 +28,10 @@ export async function getPosSettings(transport, options = {}) {
27
28
  const daten = await transport('getKasseSettings', params);
28
29
  return posSettingsFromWire(daten);
29
30
  }
30
- /** `{business, device}` einer Antwort, gemischt mit den Standardwerten. */
31
+ /** `{business, device, vouchers}` einer Antwort, gemischt mit den Standardwerten. */
31
32
  export function posSettingsFromWire(data) {
32
33
  return {
34
+ vouchers: posVoucherSettingsFromWire(data?.vouchers),
33
35
  business: mergePosSettings(POS_BUSINESS_DEFAULTS, objekt(data?.business)),
34
36
  device: mergePosSettings(POS_DEVICE_DEFAULTS, objekt(data?.device)),
35
37
  };
@@ -0,0 +1,90 @@
1
+ import type { InternerTransport } from '../client/aufrufe.js';
2
+ /**
3
+ * Gutschein pruefen und Etikett nachdrucken an der Kasse (Backend
4
+ * gutschein-endpoints). Beide Aufrufe gibt es nur ueber den Kassenweg
5
+ * `/api/v3`.
6
+ *
7
+ * Der Klartext-Code lebt nur im Speicher des Aufrufs: er wird weder
8
+ * protokolliert noch in einer Fehlermeldung genannt. Die Kasse bekommt nach
9
+ * dem Pruefen nur die letzten vier Zeichen (`codeSuffix`) zurueck.
10
+ */
11
+ export type VoucherKind = 'multi_purpose' | 'single_purpose' | 'service' | 'promotion';
12
+ export type VoucherStatus = 'active' | 'used_up' | 'expired' | 'paid_out' | 'cancelled' | 'blocked';
13
+ export declare const VOUCHER_KINDS: readonly VoucherKind[];
14
+ export declare const VOUCHER_STATUSES: readonly VoucherStatus[];
15
+ /** Gueltigkeit eines Gutscheins; Daten als `YYYY-MM-DD` (Wiener Tag). Was der Server nicht nennt, fehlt. */
16
+ export interface VoucherValidity {
17
+ pattern: 'unlimited' | '1+3' | 'custom';
18
+ redeemableUntil?: string;
19
+ refundableUntil?: string;
20
+ validUntil?: string;
21
+ }
22
+ /** Der Artikel eines Dienstleistungsgutscheins. */
23
+ export interface VoucherArticle {
24
+ id: string;
25
+ name: string;
26
+ vatRateBp: number;
27
+ priceCents: number;
28
+ }
29
+ /**
30
+ * Stand eines Gutscheins nach dem Code-Eingeben. Felder, die zur Art nicht
31
+ * passen oder die der Server nicht sendet, fehlen im Modell (nie `null`).
32
+ */
33
+ export interface VoucherCheck {
34
+ type: VoucherKind;
35
+ status: VoucherStatus;
36
+ /** Die letzten vier Zeichen des Codes, fuer Anzeige und Beleg. */
37
+ codeSuffix: string;
38
+ balanceCents?: number;
39
+ faceValueCents?: number;
40
+ quantity?: number;
41
+ remainingQuantity?: number;
42
+ vatRateBp?: number;
43
+ article?: VoucherArticle;
44
+ discountCents?: number;
45
+ discountPercentBp?: number;
46
+ validity?: VoucherValidity;
47
+ /**
48
+ * Befreit verkauft (Kleinunternehmer beim Verkauf, Satz 0): eine Einloesung
49
+ * verteilt sich anteilig auf alle Saetze des Korbs, auch in einem
50
+ * inzwischen steuerpflichtigen Konto. Fehlt bei aelteren Servern.
51
+ */
52
+ exempt?: boolean;
53
+ }
54
+ /** Gutschein-Einstellungen der Kasse (Block `vouchers` aus `getKasseSettings`). */
55
+ export interface PosVoucherSettings {
56
+ sale: boolean;
57
+ valueVoucherType: 'multi_purpose' | 'single_purpose' | null;
58
+ vatRateBp: number | null;
59
+ }
60
+ /** Ohne Block `vouchers` (alter Server, Konto ohne Schalter): Verkaufen ist aus. */
61
+ export declare const VOUCHER_SETTINGS_DEFAULTS: Readonly<PosVoucherSettings>;
62
+ /**
63
+ * Block `vouchers` einer Einstellungs-Antwort, geschlossen im Zweifel: ist
64
+ * irgendein Feld unstimmig, gilt der ganze Block als nicht gelesen und
65
+ * Verkaufen bleibt aus (kein Wurf, sonst ginge das Laden aller Einstellungen
66
+ * verloren). Stimmig heisst: `sale` ein Wahrheitswert, die Art
67
+ * `multi_purpose`/`single_purpose`/`null`, der Satz eine ganze Zahl >= 0 oder
68
+ * `null`; Mehrzweck traegt keinen Satz, Einzweck braucht einen, und ein
69
+ * eingeschalteter Verkauf braucht eine Art. Ein ausgeschalteter Verkauf darf
70
+ * eine Art behalten.
71
+ */
72
+ export declare function posVoucherSettingsFromWire(block: unknown): PosVoucherSettings;
73
+ /**
74
+ * Gutschein am Code pruefen (Gutschein-Recht `voucherRedeem`). Der Code wird
75
+ * tolerant eingelesen (Gross/klein, Bindestriche, `O`/`0`, `I`/`L`/`1`) und
76
+ * vor dem Senden auf sein Pruefzeichen geprueft: ein Tippfehler geht nie ueber
77
+ * das Netz, sondern endet mit `KasseneckValidationError`. Fachliche Fehler
78
+ * kommen als `KasseneckApiError` mit dem Code des Servers
79
+ * (`voucher_not_found`, `too_many_voucher_checks`, `not_permitted` …).
80
+ */
81
+ export declare function checkVoucher(transport: InternerTransport, code: string): Promise<VoucherCheck>;
82
+ /**
83
+ * Etikett eines Gutscheins noch einmal drucken (Gutschein-Recht
84
+ * `voucherManage`). Antwort ist der Klartext-Code zum Drucken; er gehoert
85
+ * nur in den Speicher bis zum Druck. Aufrufer duerfen ihn nicht protokollieren,
86
+ * speichern oder in Meldungen nennen; Lesefehler dieser Antwort nennen ihn nie.
87
+ */
88
+ export declare function reprintVoucherLabel(transport: InternerTransport, id: string): Promise<{
89
+ code: string;
90
+ }>;