@kreiseck/kasseneck-api 1.12.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (419) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +1 -0
  3. package/dist/cjs/client/api.d.ts +3 -1
  4. package/dist/cjs/client/api.js +1 -0
  5. package/dist/cjs/client/aufrufe.d.ts +5 -5
  6. package/dist/cjs/client/aufrufe.js +7 -2
  7. package/dist/cjs/client/index.d.ts +1 -1
  8. package/dist/cjs/client/index.js +2 -1
  9. package/dist/cjs/client/receipts.d.ts +85 -2
  10. package/dist/cjs/client/receipts.js +164 -5
  11. package/dist/cjs/enums/voucher-type.d.ts +1 -1
  12. package/dist/cjs/enums/voucher-type.js +1 -1
  13. package/dist/cjs/index.d.ts +2 -2
  14. package/dist/cjs/index.js +15 -3
  15. package/dist/cjs/invoice/typen.d.ts +1 -1
  16. package/dist/cjs/models/index.d.ts +2 -1
  17. package/dist/cjs/models/index.js +12 -1
  18. package/dist/cjs/models/receipt-output.d.ts +79 -0
  19. package/dist/cjs/models/receipt-output.js +143 -0
  20. package/dist/cjs/models/receipt.d.ts +2 -2
  21. package/dist/cjs/models/receipt.js +2 -2
  22. package/dist/cjs/models/voucher.d.ts +24 -2
  23. package/dist/cjs/models/voucher.js +2 -2
  24. package/dist/cjs/partner/typen.d.ts +1 -1
  25. package/dist/cjs/pos/index.d.ts +2 -1
  26. package/dist/cjs/pos/index.js +6 -1
  27. package/dist/cjs/pos/schicht-typen.d.ts +2 -2
  28. package/dist/cjs/pos/schicht-typen.js +2 -2
  29. package/dist/cjs/pos/settings.d.ts +1 -1
  30. package/dist/cjs/pos/settings.js +5 -0
  31. package/dist/cjs/pos/texte.d.ts +187 -0
  32. package/dist/cjs/pos/texte.js +88 -0
  33. package/dist/cjs/receipt/due.d.ts +4 -2
  34. package/dist/cjs/receipt/due.js +22 -5
  35. package/dist/cjs/receipt/duplikat.d.ts +35 -0
  36. package/dist/cjs/receipt/duplikat.js +76 -0
  37. package/dist/cjs/receipt/gutschein-plan.d.ts +2 -0
  38. package/dist/cjs/receipt/gutschein-plan.js +5 -0
  39. package/dist/cjs/receipt/index.d.ts +1 -0
  40. package/dist/cjs/receipt/index.js +4 -2
  41. package/dist/cjs/receipt/layout.js +44 -21
  42. package/dist/cjs/register/pairing.d.ts +6 -2
  43. package/dist/cjs/register/pairing.js +1 -1
  44. package/dist/cjs/stored/bon-layout.js +3 -4
  45. package/dist/cjs/stored/vokabular.d.ts +1 -1
  46. package/dist/cjs/stored/vokabular.js +34 -2
  47. package/dist/cjs/version.d.ts +1 -1
  48. package/dist/cjs/version.js +1 -1
  49. package/dist/esm/client/api.d.ts +3 -1
  50. package/dist/esm/client/api.js +2 -1
  51. package/dist/esm/client/aufrufe.d.ts +5 -5
  52. package/dist/esm/client/aufrufe.js +7 -2
  53. package/dist/esm/client/index.d.ts +1 -1
  54. package/dist/esm/client/index.js +1 -1
  55. package/dist/esm/client/receipts.d.ts +85 -2
  56. package/dist/esm/client/receipts.js +164 -6
  57. package/dist/esm/enums/voucher-type.d.ts +1 -1
  58. package/dist/esm/enums/voucher-type.js +1 -1
  59. package/dist/esm/index.d.ts +2 -2
  60. package/dist/esm/index.js +2 -2
  61. package/dist/esm/invoice/typen.d.ts +1 -1
  62. package/dist/esm/models/index.d.ts +2 -1
  63. package/dist/esm/models/index.js +1 -0
  64. package/dist/esm/models/receipt-output.d.ts +79 -0
  65. package/dist/esm/models/receipt-output.js +135 -0
  66. package/dist/esm/models/receipt.d.ts +2 -2
  67. package/dist/esm/models/receipt.js +2 -2
  68. package/dist/esm/models/voucher.d.ts +24 -2
  69. package/dist/esm/models/voucher.js +2 -2
  70. package/dist/esm/partner/typen.d.ts +1 -1
  71. package/dist/esm/pos/index.d.ts +2 -1
  72. package/dist/esm/pos/index.js +3 -1
  73. package/dist/esm/pos/schicht-typen.d.ts +2 -2
  74. package/dist/esm/pos/schicht-typen.js +2 -2
  75. package/dist/esm/pos/settings.d.ts +1 -1
  76. package/dist/esm/pos/settings.js +5 -0
  77. package/dist/esm/pos/texte.d.ts +187 -0
  78. package/dist/esm/pos/texte.js +87 -0
  79. package/dist/esm/receipt/due.d.ts +4 -2
  80. package/dist/esm/receipt/due.js +23 -6
  81. package/dist/esm/receipt/duplikat.d.ts +35 -0
  82. package/dist/esm/receipt/duplikat.js +73 -0
  83. package/dist/esm/receipt/gutschein-plan.d.ts +2 -0
  84. package/dist/esm/receipt/gutschein-plan.js +4 -0
  85. package/dist/esm/receipt/index.d.ts +1 -0
  86. package/dist/esm/receipt/index.js +1 -0
  87. package/dist/esm/receipt/layout.js +44 -21
  88. package/dist/esm/register/pairing.d.ts +6 -2
  89. package/dist/esm/register/pairing.js +1 -1
  90. package/dist/esm/stored/bon-layout.js +3 -4
  91. package/dist/esm/stored/vokabular.d.ts +1 -1
  92. package/dist/esm/stored/vokabular.js +34 -2
  93. package/dist/esm/version.d.ts +1 -1
  94. package/dist/esm/version.js +1 -1
  95. package/fixtures/code-table-receipts.json +1 -1
  96. package/fixtures/duplicate-cases.json +5616 -0
  97. package/fixtures/expected/cancellation-discount.grid32.txt +1 -1
  98. package/fixtures/expected/cancellation-discount.grid48.txt +1 -1
  99. package/fixtures/expected/cancellation-discount.lines.json +1 -1
  100. package/fixtures/expected/cancellation-discount.sheet32.json +1 -1
  101. package/fixtures/expected/cancellation-discount.sheet48.json +1 -1
  102. package/fixtures/expected/cancellation-full.grid32.txt +1 -1
  103. package/fixtures/expected/cancellation-full.grid48.txt +1 -1
  104. package/fixtures/expected/cancellation-full.lines.json +1 -1
  105. package/fixtures/expected/cancellation-full.sheet32.json +1 -1
  106. package/fixtures/expected/cancellation-full.sheet48.json +1 -1
  107. package/fixtures/expected/cancellation-partial.grid32.txt +1 -1
  108. package/fixtures/expected/cancellation-partial.grid48.txt +1 -1
  109. package/fixtures/expected/cancellation-partial.lines.json +1 -1
  110. package/fixtures/expected/cancellation-partial.sheet32.json +1 -1
  111. package/fixtures/expected/cancellation-partial.sheet48.json +1 -1
  112. package/fixtures/expected/cancellation-split-full.grid32.txt +1 -1
  113. package/fixtures/expected/cancellation-split-full.grid48.txt +1 -1
  114. package/fixtures/expected/cancellation-split-full.lines.json +1 -1
  115. package/fixtures/expected/cancellation-split-full.sheet32.json +1 -1
  116. package/fixtures/expected/cancellation-split-full.sheet48.json +1 -1
  117. package/fixtures/expected/cancellation-split-partial.grid32.txt +1 -1
  118. package/fixtures/expected/cancellation-split-partial.grid48.txt +1 -1
  119. package/fixtures/expected/cancellation-split-partial.lines.json +1 -1
  120. package/fixtures/expected/cancellation-split-partial.sheet32.json +1 -1
  121. package/fixtures/expected/cancellation-split-partial.sheet48.json +1 -1
  122. package/fixtures/expected/card-custom.grid32.txt +1 -1
  123. package/fixtures/expected/card-custom.grid48.txt +1 -1
  124. package/fixtures/expected/card-custom.lines.json +1 -1
  125. package/fixtures/expected/card-custom.sheet32.json +1 -1
  126. package/fixtures/expected/card-custom.sheet48.json +1 -1
  127. package/fixtures/expected/card-gptom-ios.grid32.txt +1 -1
  128. package/fixtures/expected/card-gptom-ios.grid48.txt +1 -1
  129. package/fixtures/expected/card-gptom-ios.lines.json +1 -1
  130. package/fixtures/expected/card-gptom-ios.sheet32.json +1 -1
  131. package/fixtures/expected/card-gptom-ios.sheet48.json +1 -1
  132. package/fixtures/expected/card-gptom.grid32.txt +1 -1
  133. package/fixtures/expected/card-gptom.grid48.txt +1 -1
  134. package/fixtures/expected/card-gptom.lines.json +1 -1
  135. package/fixtures/expected/card-gptom.sheet32.json +1 -1
  136. package/fixtures/expected/card-gptom.sheet48.json +1 -1
  137. package/fixtures/expected/card-hobex-cloud.grid32.txt +1 -1
  138. package/fixtures/expected/card-hobex-cloud.grid48.txt +1 -1
  139. package/fixtures/expected/card-hobex-cloud.lines.json +1 -1
  140. package/fixtures/expected/card-hobex-cloud.sheet32.json +1 -1
  141. package/fixtures/expected/card-hobex-cloud.sheet48.json +1 -1
  142. package/fixtures/expected/card-hobex-hps.grid32.txt +1 -1
  143. package/fixtures/expected/card-hobex-hps.grid48.txt +1 -1
  144. package/fixtures/expected/card-hobex-hps.lines.json +1 -1
  145. package/fixtures/expected/card-hobex-hps.sheet32.json +1 -1
  146. package/fixtures/expected/card-hobex-hps.sheet48.json +1 -1
  147. package/fixtures/expected/card-mypos.grid32.txt +1 -1
  148. package/fixtures/expected/card-mypos.grid48.txt +1 -1
  149. package/fixtures/expected/card-mypos.lines.json +1 -1
  150. package/fixtures/expected/card-mypos.sheet32.json +1 -1
  151. package/fixtures/expected/card-mypos.sheet48.json +1 -1
  152. package/fixtures/expected/card-stripe-eps.grid32.txt +1 -1
  153. package/fixtures/expected/card-stripe-eps.grid48.txt +1 -1
  154. package/fixtures/expected/card-stripe-eps.lines.json +1 -1
  155. package/fixtures/expected/card-stripe-eps.sheet32.json +1 -1
  156. package/fixtures/expected/card-stripe-eps.sheet48.json +1 -1
  157. package/fixtures/expected/card-stripe.grid32.txt +1 -1
  158. package/fixtures/expected/card-stripe.grid48.txt +1 -1
  159. package/fixtures/expected/card-stripe.lines.json +1 -1
  160. package/fixtures/expected/card-stripe.sheet32.json +1 -1
  161. package/fixtures/expected/card-stripe.sheet48.json +1 -1
  162. package/fixtures/expected/card-sumup.grid32.txt +1 -1
  163. package/fixtures/expected/card-sumup.grid48.txt +1 -1
  164. package/fixtures/expected/card-sumup.lines.json +1 -1
  165. package/fixtures/expected/card-sumup.sheet32.json +1 -1
  166. package/fixtures/expected/card-sumup.sheet48.json +1 -1
  167. package/fixtures/expected/code-table-receipt.long-item-name.iso8859_15.hex +1 -1
  168. package/fixtures/expected/code-table-receipt.long-item-name.pc437.hex +1 -1
  169. package/fixtures/expected/code-table-receipt.long-item-name.pc850.hex +1 -1
  170. package/fixtures/expected/code-table-receipt.long-item-name.pc858.hex +1 -1
  171. package/fixtures/expected/code-table-receipt.long-item-name.replacement.hex +1 -1
  172. package/fixtures/expected/code-table-receipt.long-item-name.wpc1252.hex +1 -1
  173. package/fixtures/expected/code-table-receipt.sale-cash.iso8859_15.hex +1 -1
  174. package/fixtures/expected/code-table-receipt.sale-cash.pc437.hex +1 -1
  175. package/fixtures/expected/code-table-receipt.sale-cash.pc850.hex +1 -1
  176. package/fixtures/expected/code-table-receipt.sale-cash.pc858.hex +1 -1
  177. package/fixtures/expected/code-table-receipt.sale-cash.replacement.hex +1 -1
  178. package/fixtures/expected/code-table-receipt.sale-cash.wpc1252.hex +1 -1
  179. package/fixtures/expected/code-table-receipt.special-characters.iso8859_15.hex +1 -1
  180. package/fixtures/expected/code-table-receipt.special-characters.pc437.hex +1 -1
  181. package/fixtures/expected/code-table-receipt.special-characters.pc850.hex +1 -1
  182. package/fixtures/expected/code-table-receipt.special-characters.pc858.hex +1 -1
  183. package/fixtures/expected/code-table-receipt.special-characters.replacement.hex +1 -1
  184. package/fixtures/expected/code-table-receipt.special-characters.wpc1252.hex +1 -1
  185. package/fixtures/expected/code-table-receipt.test-cashregister-sale.iso8859_15.hex +1 -1
  186. package/fixtures/expected/code-table-receipt.test-cashregister-sale.pc437.hex +1 -1
  187. package/fixtures/expected/code-table-receipt.test-cashregister-sale.pc850.hex +1 -1
  188. package/fixtures/expected/code-table-receipt.test-cashregister-sale.pc858.hex +1 -1
  189. package/fixtures/expected/code-table-receipt.test-cashregister-sale.replacement.hex +1 -1
  190. package/fixtures/expected/code-table-receipt.test-cashregister-sale.wpc1252.hex +1 -1
  191. package/fixtures/expected/discount-lines.grid32.txt +1 -1
  192. package/fixtures/expected/discount-lines.grid48.txt +1 -1
  193. package/fixtures/expected/discount-lines.lines.json +1 -1
  194. package/fixtures/expected/discount-lines.sheet32.json +1 -1
  195. package/fixtures/expected/discount-lines.sheet48.json +1 -1
  196. package/fixtures/expected/discount-owner-tip.grid32.txt +1 -1
  197. package/fixtures/expected/discount-owner-tip.grid48.txt +1 -1
  198. package/fixtures/expected/discount-owner-tip.lines.json +1 -1
  199. package/fixtures/expected/discount-owner-tip.sheet32.json +1 -1
  200. package/fixtures/expected/discount-owner-tip.sheet48.json +1 -1
  201. package/fixtures/expected/discount-simple.grid32.txt +1 -1
  202. package/fixtures/expected/discount-simple.grid48.txt +1 -1
  203. package/fixtures/expected/discount-simple.lines.json +1 -1
  204. package/fixtures/expected/discount-simple.sheet32.json +1 -1
  205. package/fixtures/expected/discount-simple.sheet48.json +1 -1
  206. package/fixtures/expected/discount-tip.grid32.txt +1 -1
  207. package/fixtures/expected/discount-tip.grid48.txt +1 -1
  208. package/fixtures/expected/discount-tip.lines.json +1 -1
  209. package/fixtures/expected/discount-tip.sheet32.json +1 -1
  210. package/fixtures/expected/discount-tip.sheet48.json +1 -1
  211. package/fixtures/expected/discount-value-voucher.grid32.txt +1 -1
  212. package/fixtures/expected/discount-value-voucher.grid48.txt +1 -1
  213. package/fixtures/expected/discount-value-voucher.lines.json +1 -1
  214. package/fixtures/expected/discount-value-voucher.sheet32.json +1 -1
  215. package/fixtures/expected/discount-value-voucher.sheet48.json +1 -1
  216. package/fixtures/expected/duplicate.cancellation-full.hex +44 -0
  217. package/fixtures/expected/duplicate.cancellation-partial.hex +33 -0
  218. package/fixtures/expected/duplicate.sale-cash-mm58.hex +28 -0
  219. package/fixtures/expected/duplicate.sale-cash-twice.hex +35 -0
  220. package/fixtures/expected/duplicate.sale-cash.hex +35 -0
  221. package/fixtures/expected/duplicate.shift-close.hex +43 -0
  222. package/fixtures/expected/duplicate.summer-time-last-second.hex +28 -0
  223. package/fixtures/expected/duplicate.summer-time-start.hex +35 -0
  224. package/fixtures/expected/duplicate.test-cashregister-sale-logo.hex +189 -0
  225. package/fixtures/expected/duplicate.voucher-multi-purpose-redeem.hex +37 -0
  226. package/fixtures/expected/duplicate.voucher-service-redeem-logo.hex +119 -0
  227. package/fixtures/expected/duplicate.winter-time-first-second.hex +28 -0
  228. package/fixtures/expected/duplicate.zero-start.hex +40 -0
  229. package/fixtures/expected/long-item-name.grid32.txt +1 -1
  230. package/fixtures/expected/long-item-name.grid48.txt +1 -1
  231. package/fixtures/expected/long-item-name.lines.json +1 -1
  232. package/fixtures/expected/long-item-name.sheet32.json +1 -1
  233. package/fixtures/expected/long-item-name.sheet48.json +1 -1
  234. package/fixtures/expected/sale-card.grid32.txt +1 -1
  235. package/fixtures/expected/sale-card.grid48.txt +1 -1
  236. package/fixtures/expected/sale-card.lines.json +1 -1
  237. package/fixtures/expected/sale-card.sheet32.json +1 -1
  238. package/fixtures/expected/sale-card.sheet48.json +1 -1
  239. package/fixtures/expected/sale-cash.grid32.txt +1 -1
  240. package/fixtures/expected/sale-cash.grid48.txt +1 -1
  241. package/fixtures/expected/sale-cash.lines.json +1 -1
  242. package/fixtures/expected/sale-cash.sheet32.json +1 -1
  243. package/fixtures/expected/sale-cash.sheet48.json +1 -1
  244. package/fixtures/expected/sale-small-business.grid32.txt +1 -1
  245. package/fixtures/expected/sale-small-business.grid48.txt +1 -1
  246. package/fixtures/expected/sale-small-business.lines.json +1 -1
  247. package/fixtures/expected/sale-small-business.sheet32.json +1 -1
  248. package/fixtures/expected/sale-small-business.sheet48.json +1 -1
  249. package/fixtures/expected/signature-outage-sale.grid32.txt +1 -1
  250. package/fixtures/expected/signature-outage-sale.grid48.txt +1 -1
  251. package/fixtures/expected/signature-outage-sale.lines.json +1 -1
  252. package/fixtures/expected/signature-outage-sale.sheet32.json +1 -1
  253. package/fixtures/expected/signature-outage-sale.sheet48.json +1 -1
  254. package/fixtures/expected/split-card-card-cash.grid32.txt +1 -1
  255. package/fixtures/expected/split-card-card-cash.grid48.txt +1 -1
  256. package/fixtures/expected/split-card-card-cash.lines.json +1 -1
  257. package/fixtures/expected/split-card-card-cash.sheet32.json +1 -1
  258. package/fixtures/expected/split-card-card-cash.sheet48.json +1 -1
  259. package/fixtures/expected/split-cash-change.grid32.txt +1 -1
  260. package/fixtures/expected/split-cash-change.grid48.txt +1 -1
  261. package/fixtures/expected/split-cash-change.lines.json +1 -1
  262. package/fixtures/expected/split-cash-change.sheet32.json +1 -1
  263. package/fixtures/expected/split-cash-change.sheet48.json +1 -1
  264. package/fixtures/expected/split-long-amount.grid32.txt +1 -1
  265. package/fixtures/expected/split-long-amount.grid48.txt +1 -1
  266. package/fixtures/expected/split-long-amount.lines.json +1 -1
  267. package/fixtures/expected/split-long-amount.sheet32.json +1 -1
  268. package/fixtures/expected/split-long-amount.sheet48.json +1 -1
  269. package/fixtures/expected/split-one-card-tip.grid32.txt +1 -1
  270. package/fixtures/expected/split-one-card-tip.grid48.txt +1 -1
  271. package/fixtures/expected/split-one-card-tip.lines.json +1 -1
  272. package/fixtures/expected/split-one-card-tip.sheet32.json +1 -1
  273. package/fixtures/expected/split-one-card-tip.sheet48.json +1 -1
  274. package/fixtures/expected/split-table-round-tip.grid32.txt +1 -1
  275. package/fixtures/expected/split-table-round-tip.grid48.txt +1 -1
  276. package/fixtures/expected/split-table-round-tip.lines.json +1 -1
  277. package/fixtures/expected/split-table-round-tip.sheet32.json +1 -1
  278. package/fixtures/expected/split-table-round-tip.sheet48.json +1 -1
  279. package/fixtures/expected/split-tip-card.grid32.txt +1 -1
  280. package/fixtures/expected/split-tip-card.grid48.txt +1 -1
  281. package/fixtures/expected/split-tip-card.lines.json +1 -1
  282. package/fixtures/expected/split-tip-card.sheet32.json +1 -1
  283. package/fixtures/expected/split-tip-card.sheet48.json +1 -1
  284. package/fixtures/expected/split-two-cards-same-provider.grid32.txt +1 -1
  285. package/fixtures/expected/split-two-cards-same-provider.grid48.txt +1 -1
  286. package/fixtures/expected/split-two-cards-same-provider.lines.json +1 -1
  287. package/fixtures/expected/split-two-cards-same-provider.sheet32.json +1 -1
  288. package/fixtures/expected/split-two-cards-same-provider.sheet48.json +1 -1
  289. package/fixtures/expected/test-cashregister-sale.grid32.txt +1 -1
  290. package/fixtures/expected/test-cashregister-sale.grid48.txt +1 -1
  291. package/fixtures/expected/test-cashregister-sale.lines.json +1 -1
  292. package/fixtures/expected/test-cashregister-sale.sheet32.json +1 -1
  293. package/fixtures/expected/test-cashregister-sale.sheet48.json +1 -1
  294. package/fixtures/expected/test-signature-sale.grid32.txt +1 -1
  295. package/fixtures/expected/test-signature-sale.grid48.txt +1 -1
  296. package/fixtures/expected/test-signature-sale.lines.json +1 -1
  297. package/fixtures/expected/test-signature-sale.sheet32.json +1 -1
  298. package/fixtures/expected/test-signature-sale.sheet48.json +1 -1
  299. package/fixtures/expected/training.grid32.txt +1 -1
  300. package/fixtures/expected/training.grid48.txt +1 -1
  301. package/fixtures/expected/training.lines.json +1 -1
  302. package/fixtures/expected/training.sheet32.json +1 -1
  303. package/fixtures/expected/training.sheet48.json +1 -1
  304. package/fixtures/expected/voucher-multi-purpose-sale.grid32.txt +1 -2
  305. package/fixtures/expected/voucher-multi-purpose-sale.grid48.txt +1 -1
  306. package/fixtures/expected/voucher-multi-purpose-sale.lines.json +1 -1
  307. package/fixtures/expected/voucher-multi-purpose-sale.sheet32.json +1 -7
  308. package/fixtures/expected/voucher-multi-purpose-sale.sheet48.json +1 -1
  309. package/fixtures/expected/voucher-single-purpose-redeem-exempt.grid32.txt +1 -1
  310. package/fixtures/expected/voucher-single-purpose-redeem-exempt.grid48.txt +1 -1
  311. package/fixtures/expected/voucher-single-purpose-redeem-exempt.lines.json +1 -1
  312. package/fixtures/expected/voucher-single-purpose-redeem-exempt.sheet32.json +1 -1
  313. package/fixtures/expected/voucher-single-purpose-redeem-exempt.sheet48.json +1 -1
  314. package/fixtures/expected/voucher-single-purpose-redeem.grid32.txt +1 -1
  315. package/fixtures/expected/voucher-single-purpose-redeem.grid48.txt +1 -1
  316. package/fixtures/expected/voucher-single-purpose-redeem.lines.json +1 -1
  317. package/fixtures/expected/voucher-single-purpose-redeem.sheet32.json +1 -1
  318. package/fixtures/expected/voucher-single-purpose-redeem.sheet48.json +1 -1
  319. package/fixtures/expected/voucher-single-purpose-sale.grid32.txt +2 -3
  320. package/fixtures/expected/voucher-single-purpose-sale.grid48.txt +2 -2
  321. package/fixtures/expected/voucher-single-purpose-sale.lines.json +2 -2
  322. package/fixtures/expected/voucher-single-purpose-sale.sheet32.json +2 -8
  323. package/fixtures/expected/voucher-single-purpose-sale.sheet48.json +2 -2
  324. package/fixtures/expected/zero-annual.grid32.txt +1 -1
  325. package/fixtures/expected/zero-annual.grid48.txt +1 -1
  326. package/fixtures/expected/zero-annual.lines.json +1 -1
  327. package/fixtures/expected/zero-annual.sheet32.json +1 -1
  328. package/fixtures/expected/zero-annual.sheet48.json +1 -1
  329. package/fixtures/expected/zero-final.grid32.txt +1 -1
  330. package/fixtures/expected/zero-final.grid48.txt +1 -1
  331. package/fixtures/expected/zero-final.lines.json +1 -1
  332. package/fixtures/expected/zero-final.sheet32.json +1 -1
  333. package/fixtures/expected/zero-final.sheet48.json +1 -1
  334. package/fixtures/expected/zero-manual.grid32.txt +1 -1
  335. package/fixtures/expected/zero-manual.grid48.txt +1 -1
  336. package/fixtures/expected/zero-manual.lines.json +1 -1
  337. package/fixtures/expected/zero-manual.sheet32.json +1 -1
  338. package/fixtures/expected/zero-manual.sheet48.json +1 -1
  339. package/fixtures/expected/zero-monthly.grid32.txt +1 -1
  340. package/fixtures/expected/zero-monthly.grid48.txt +1 -1
  341. package/fixtures/expected/zero-monthly.lines.json +1 -1
  342. package/fixtures/expected/zero-monthly.sheet32.json +1 -1
  343. package/fixtures/expected/zero-monthly.sheet48.json +1 -1
  344. package/fixtures/expected/zero-outage-end.grid32.txt +1 -1
  345. package/fixtures/expected/zero-outage-end.grid48.txt +1 -1
  346. package/fixtures/expected/zero-outage-end.lines.json +1 -1
  347. package/fixtures/expected/zero-outage-end.sheet32.json +1 -1
  348. package/fixtures/expected/zero-outage-end.sheet48.json +1 -1
  349. package/fixtures/expected/zero-start.grid32.txt +1 -1
  350. package/fixtures/expected/zero-start.grid48.txt +1 -1
  351. package/fixtures/expected/zero-start.lines.json +1 -1
  352. package/fixtures/expected/zero-start.sheet32.json +1 -1
  353. package/fixtures/expected/zero-start.sheet48.json +1 -1
  354. package/fixtures/hobex-hps-codes.json +1 -1
  355. package/fixtures/invoice-api.schema.json +1 -1
  356. package/fixtures/invoice-texts.json +1 -1
  357. package/fixtures/manifest.json +260 -260
  358. package/fixtures/pos-texts.json +205 -1
  359. package/fixtures/receipt-due-voucher-generated.json +1 -1
  360. package/fixtures/receipt-outputs-cases.json +2778 -0
  361. package/fixtures/receipts/cancellation-discount.json +1 -1
  362. package/fixtures/receipts/cancellation-full.json +1 -1
  363. package/fixtures/receipts/cancellation-partial.json +1 -1
  364. package/fixtures/receipts/cancellation-split-full.json +1 -1
  365. package/fixtures/receipts/cancellation-split-partial.json +1 -1
  366. package/fixtures/receipts/card-custom.json +1 -1
  367. package/fixtures/receipts/card-gptom-ios.json +1 -1
  368. package/fixtures/receipts/card-gptom.json +1 -1
  369. package/fixtures/receipts/card-hobex-cloud.json +1 -1
  370. package/fixtures/receipts/card-hobex-hps.json +1 -1
  371. package/fixtures/receipts/card-mypos.json +1 -1
  372. package/fixtures/receipts/card-stripe-eps.json +1 -1
  373. package/fixtures/receipts/card-stripe.json +1 -1
  374. package/fixtures/receipts/card-sumup.json +1 -1
  375. package/fixtures/receipts/discount-lines.json +1 -1
  376. package/fixtures/receipts/discount-owner-tip.json +1 -1
  377. package/fixtures/receipts/discount-simple.json +1 -1
  378. package/fixtures/receipts/discount-tip.json +1 -1
  379. package/fixtures/receipts/discount-value-voucher.json +1 -1
  380. package/fixtures/receipts/long-item-name.json +1 -1
  381. package/fixtures/receipts/sale-card.json +1 -1
  382. package/fixtures/receipts/sale-cash.json +1 -1
  383. package/fixtures/receipts/sale-small-business.json +1 -1
  384. package/fixtures/receipts/signature-outage-sale.json +1 -1
  385. package/fixtures/receipts/split-card-card-cash.json +1 -1
  386. package/fixtures/receipts/split-cash-change.json +1 -1
  387. package/fixtures/receipts/split-long-amount.json +1 -1
  388. package/fixtures/receipts/split-one-card-tip.json +1 -1
  389. package/fixtures/receipts/split-table-round-tip.json +1 -1
  390. package/fixtures/receipts/split-tip-card.json +1 -1
  391. package/fixtures/receipts/split-two-cards-same-provider.json +1 -1
  392. package/fixtures/receipts/test-cashregister-sale.json +1 -1
  393. package/fixtures/receipts/test-signature-sale.json +1 -1
  394. package/fixtures/receipts/training.json +1 -1
  395. package/fixtures/receipts/zero-annual.json +1 -1
  396. package/fixtures/receipts/zero-final.json +1 -1
  397. package/fixtures/receipts/zero-manual.json +1 -1
  398. package/fixtures/receipts/zero-monthly.json +1 -1
  399. package/fixtures/receipts/zero-outage-end.json +1 -1
  400. package/fixtures/receipts/zero-start.json +1 -1
  401. package/fixtures/surface.json +25 -5
  402. package/fixtures/v3/README.md +10 -3
  403. package/fixtures/v3/antworten/belege.json +623 -125
  404. package/fixtures/v3/antworten/belegmail.json +2 -2
  405. package/fixtures/v3/antworten/kasse-belege.json +622 -122
  406. package/fixtures/v3/antworten/kasse.json +407 -31
  407. package/fixtures/v3/antworten/lager.json +1 -1
  408. package/fixtures/v3/antworten/rechnungen.json +4 -4
  409. package/fixtures/v3/antworten/storno.json +211 -3
  410. package/fixtures/v3/stored/belege.json +2 -2
  411. package/fixtures/v3/stored/kasse.json +114 -4
  412. package/fixtures/v3/stored/rechnungen.json +17 -17
  413. package/fixtures/v3/v3-vokabular.json +224 -19
  414. package/fixtures/v3/zahlbetrag-faelle.json +1070 -4
  415. package/package.json +3 -1
  416. package/dist/cjs/stored/gutscheine.d.ts +0 -3
  417. package/dist/cjs/stored/gutscheine.js +0 -60
  418. package/dist/esm/stored/gutscheine.d.ts +0 -3
  419. package/dist/esm/stored/gutscheine.js +0 -56
@@ -45,8 +45,8 @@ export function toVoucherPayload(voucher) {
45
45
  }
46
46
  /**
47
47
  * Ist der Gutschein an das Backend sendbar? Zwilling von `KeckVoucher.isValid`
48
- * im Flutter-Vorbild: Wert- und Promotionsgutscheine brauchen einen Wert,
49
- * Promotionsgutscheine duerfen nur eingeloest (nicht verkauft) werden, und ein
48
+ * im Flutter-Vorbild: Wert- und Aktionsgutscheine brauchen einen Wert,
49
+ * Aktionsgutscheine duerfen nur eingeloest (nicht verkauft) werden, und ein
50
50
  * gesetzter Wert muss positiv sein.
51
51
  */
52
52
  export function voucherIsValid(voucher) {
@@ -104,7 +104,7 @@ export interface BusinessAddress {
104
104
  city: string;
105
105
  }
106
106
  export interface BusinessTaxDetails {
107
- /** Steuernummer im Format `12-345/6789`; die Pruefziffer wird geprueft. */
107
+ /** Steuernummer im Format `91-123/4565`; die Pruefziffer wird geprueft. */
108
108
  taxNumber: string;
109
109
  smallBusiness: boolean;
110
110
  /**
@@ -22,5 +22,6 @@ export { VOUCHER_KINDS, VOUCHER_STATUSES, checkVoucher, reprintVoucherLabel, VOU
22
22
  export { type GetMyDrawerStateOptions, type OpenMyShiftOptions, type RecordMyCashMovementOptions, type DrawerOpeningEntry, type LogMyDrawerOpeningsOptions, type GetMyShiftReportOptions, type TipPayout, type CloseMyShiftOptions, type AfterCountOption, getMyDrawerState, openMyShift, recordMyCashMovement, logMyDrawerOpenings, getMyShiftReport, closeMyShift, sumDenominations, parseCentsAllowZero, newIdempotencyKey, shiftTipLines, durationText, type ShiftTipLine, type ShiftTipLineKey, } from './schicht.js';
23
23
  export { EUR_DENOMINATIONS, MOVEMENT_TYPES, MANUAL_MOVEMENT_TYPES, CASH_LOCATIONS, OPENING_REASONS, MANUAL_OPENING_REASONS, SHIFT_RECEIPT_KINDS, AFTER_COUNT_TYPES, type AfterCountType, type AfterCount, type EurDenomination, type MovementType, type ManualMovementType, type CashLocation, type OpeningReason, type ManualOpeningReason, type ShiftReceiptKind, type ShiftStatus, type ShiftActorRole, type Denominations, type ShiftActor, type DrawerInfo, type DrawerRights, type NonCashAmount, type ShiftTipTotals, type ShiftTip, type ShiftRunningTotals, type ShiftReconciliation, type Shift, type TipClaim, type DrawerOpening, type DrawerState, type CashMovement, type ShiftReceiptHeader, type ShiftReceiptMovement, type ShiftReceiptTip, type ShiftSummaryReceipt, type CashMovementReceipt, type ShiftReceipt, type OpenShiftResult, type CashMovementResult, type DrawerOpeningsResult, type ShiftReport, type CloseShiftResult, } from './schicht-typen.js';
24
24
  export { type ShiftReceiptLayoutOptions, shiftReceiptLayout, cashMovementLayout } from '../receipt/shift-sheet.js';
25
+ export { RECEIPT_OUTPUT_KINDS, RECEIPT_OUTPUT_RESULTS, type ReceiptOutputKind, type ReceiptOutputResult } from '../models/receipt-output.js';
25
26
  export { RETURN_DISPOSITIONS, isReturnDisposition, type ReturnDisposition } from '../models/cancellation.js';
26
- export { MESSAGES, ERROR_RULES, ERROR_CODE_RULES, ERROR_OUTCOME_RULES, CALLS_WITH_EFFECT, findErrorRule, messageOutcome, messageText, messageAppliesTo, RECEIPT_EMAIL_ERROR_MESSAGES, receiptEmailErrorMessage, CANCELLATION_PAYMENT_ERROR_MESSAGES, cancellationPaymentErrorMessage, VOUCHER_ERROR_MESSAGES, voucherErrorMessage, LABELS, labelText, RETURN_DISPOSITION_LABELS, type TextEntry, type MessageKey, type ErrorKind, type ErrorRule, type ErrorRuleDetail, type Surface, type ReceiptEmailMessageCode, type CancellationPaymentMessageCode, type LabelKey, } from './texte.js';
27
+ export { MESSAGES, ERROR_RULES, ERROR_CODE_RULES, ERROR_OUTCOME_RULES, CALLS_WITH_EFFECT, findErrorRule, messageOutcome, messageText, messageAppliesTo, RECEIPT_EMAIL_ERROR_MESSAGES, receiptEmailErrorMessage, CANCELLATION_PAYMENT_ERROR_MESSAGES, cancellationPaymentErrorMessage, VOUCHER_ERROR_MESSAGES, voucherErrorMessage, LABELS, labelText, RETURN_DISPOSITION_LABELS, receiptOutputLabel, type TextEntry, type MessageKey, type ErrorKind, type ErrorRule, type ErrorRuleDetail, type Surface, type ReceiptEmailMessageCode, type CancellationPaymentMessageCode, type LabelKey, } from './texte.js';
@@ -26,7 +26,9 @@ export { VOUCHER_KINDS, VOUCHER_STATUSES, checkVoucher, reprintVoucherLabel, VOU
26
26
  export { getMyDrawerState, openMyShift, recordMyCashMovement, logMyDrawerOpenings, getMyShiftReport, closeMyShift, sumDenominations, parseCentsAllowZero, newIdempotencyKey, shiftTipLines, durationText, } from './schicht.js';
27
27
  export { EUR_DENOMINATIONS, MOVEMENT_TYPES, MANUAL_MOVEMENT_TYPES, CASH_LOCATIONS, OPENING_REASONS, MANUAL_OPENING_REASONS, SHIFT_RECEIPT_KINDS, AFTER_COUNT_TYPES, } from './schicht-typen.js';
28
28
  export { shiftReceiptLayout, cashMovementLayout } from '../receipt/shift-sheet.js';
29
+ // Ausgaben eines Belegs (Belegdetail: Art und Ergebnis -> Beschriftung); dieselben Listen wie an der Wurzel.
30
+ export { RECEIPT_OUTPUT_KINDS, RECEIPT_OUTPUT_RESULTS } from '../models/receipt-output.js';
29
31
  // Rueckgabe-Wahl beim Storno (Kassen-Dialog); dieselbe Liste wie an der Wurzel.
30
32
  export { RETURN_DISPOSITIONS, isReturnDisposition } from '../models/cancellation.js';
31
33
  // Was die Kasse selbst sagt: ein Katalog fuer Browser-Kasse und App.
32
- export { MESSAGES, ERROR_RULES, ERROR_CODE_RULES, ERROR_OUTCOME_RULES, CALLS_WITH_EFFECT, findErrorRule, messageOutcome, messageText, messageAppliesTo, RECEIPT_EMAIL_ERROR_MESSAGES, receiptEmailErrorMessage, CANCELLATION_PAYMENT_ERROR_MESSAGES, cancellationPaymentErrorMessage, VOUCHER_ERROR_MESSAGES, voucherErrorMessage, LABELS, labelText, RETURN_DISPOSITION_LABELS, } from './texte.js';
34
+ export { MESSAGES, ERROR_RULES, ERROR_CODE_RULES, ERROR_OUTCOME_RULES, CALLS_WITH_EFFECT, findErrorRule, messageOutcome, messageText, messageAppliesTo, RECEIPT_EMAIL_ERROR_MESSAGES, receiptEmailErrorMessage, CANCELLATION_PAYMENT_ERROR_MESSAGES, cancellationPaymentErrorMessage, VOUCHER_ERROR_MESSAGES, voucherErrorMessage, LABELS, labelText, RETURN_DISPOSITION_LABELS, receiptOutputLabel, } from './texte.js';
@@ -37,10 +37,10 @@ export declare const CASH_LOCATIONS: readonly ["bank", "safe"];
37
37
  export type CashLocation = (typeof CASH_LOCATIONS)[number];
38
38
  /**
39
39
  * Warum die Lade aufging (Katalog `LADE_OEFFNUNG_GRUND`). `sale`,
40
- * `cash_movement`, `shift_open` und `shift_close` meldet die Kasse selbst beim
40
+ * `cash_movement`, `shift_open`, `shift_close` und `voucher_payout` meldet die Kasse selbst beim
41
41
  * jeweiligen Vorgang; von Hand waehlt der Kassier aus [MANUAL_OPENING_REASONS].
42
42
  */
43
- export declare const OPENING_REASONS: readonly ["sale", "cash_movement", "shift_open", "shift_close", "change", "check", "misoperation", "other"];
43
+ export declare const OPENING_REASONS: readonly ["sale", "cash_movement", "shift_open", "shift_close", "change", "check", "misoperation", "other", "voucher_payout"];
44
44
  export type OpeningReason = (typeof OPENING_REASONS)[number];
45
45
  /** Die Gruende des Knopfs „Lade“; `other` braucht einen Text (`note`). */
46
46
  export declare const MANUAL_OPENING_REASONS: readonly ["change", "check", "misoperation", "other"];
@@ -38,11 +38,11 @@ export const MANUAL_MOVEMENT_TYPES = Object.freeze([
38
38
  export const CASH_LOCATIONS = Object.freeze(['bank', 'safe']);
39
39
  /**
40
40
  * Warum die Lade aufging (Katalog `LADE_OEFFNUNG_GRUND`). `sale`,
41
- * `cash_movement`, `shift_open` und `shift_close` meldet die Kasse selbst beim
41
+ * `cash_movement`, `shift_open`, `shift_close` und `voucher_payout` meldet die Kasse selbst beim
42
42
  * jeweiligen Vorgang; von Hand waehlt der Kassier aus [MANUAL_OPENING_REASONS].
43
43
  */
44
44
  export const OPENING_REASONS = Object.freeze([
45
- 'sale', 'cash_movement', 'shift_open', 'shift_close', 'change', 'check', 'misoperation', 'other',
45
+ 'sale', 'cash_movement', 'shift_open', 'shift_close', 'change', 'check', 'misoperation', 'other', 'voucher_payout',
46
46
  ]);
47
47
  /** Die Gruende des Knopfs „Lade“; `other` braucht einen Text (`note`). */
48
48
  export const MANUAL_OPENING_REASONS = Object.freeze(['change', 'check', 'misoperation', 'other']);
@@ -199,7 +199,7 @@ export interface PosBusinessSettings {
199
199
  tipKeptByDefault?: boolean;
200
200
  }
201
201
  /** Aktionen der Kasse, die eine Taste bekommen koennen (Schluessel von `device.shortcuts`). */
202
- export declare const POS_SHORTCUT_ACTIONS: readonly ["checkout", "complete", "cancel", "customAmount", "cash", "card", "exactAmount", "receipts", "undoLast", "settings", "logout", "tip", "fullscreen", "clearTendered", "clearCart", "splitPayment"];
202
+ export declare const POS_SHORTCUT_ACTIONS: readonly ["checkout", "complete", "cancel", "customAmount", "cash", "card", "exactAmount", "receipts", "undoLast", "settings", "logout", "tip", "fullscreen", "clearTendered", "clearCart", "splitPayment", "shiftStatus", "openDrawer", "voucherPayout"];
203
203
  export type PosShortcutAction = typeof POS_SHORTCUT_ACTIONS[number];
204
204
  /** Tastenkarte: Aktion -> Tasten (`Mod+F`, `Enter`, `Escape`, `F5` ...; `Mod` = ⌘ auf dem Mac, Strg sonst). */
205
205
  export type PosShortcutMap = Record<PosShortcutAction, string[]>;
@@ -92,6 +92,7 @@ export const DONE_SCREEN_SECONDS = [0, 3, 5, 10, 15, 30, 60];
92
92
  export const POS_SHORTCUT_ACTIONS = [
93
93
  'checkout', 'complete', 'cancel', 'customAmount', 'cash', 'card', 'exactAmount', 'receipts', 'undoLast',
94
94
  'settings', 'logout', 'tip', 'fullscreen', 'clearTendered', 'clearCart', 'splitPayment',
95
+ 'shiftStatus', 'openDrawer', 'voucherPayout',
95
96
  ];
96
97
  export const POS_SHORTCUT_DEFAULTS = Object.freeze({
97
98
  checkout: ['Enter'], complete: ['Enter'], cancel: ['Escape'],
@@ -115,6 +116,10 @@ export const POS_SHORTCUT_DEFAULTS = Object.freeze({
115
116
  // Bewusst ohne Vorgabe: jede freie Mod-Taste ist in irgendeinem Browser
116
117
  // belegt oder am Geraet unerprobt. Der Chef vergibt sie, wenn er sie braucht.
117
118
  splitPayment: [],
119
+ // Ebenso ohne Vorgabe: Kassenstand, Kassenlade und Gutschein auszahlen. Der
120
+ // Server fuehrt sie nicht in seiner Vorgabekarte; fehlen sie in einer
121
+ // Antwort, heisst das „keine Taste“ (leere Liste), nie eine geratene Taste.
122
+ shiftStatus: [], openDrawer: [], voucherPayout: [],
118
123
  });
119
124
  /**
120
125
  * Aktionen, die sich eine Taste teilen duerfen (Backend `TASTEN_PAARE`): sie
@@ -20,6 +20,7 @@
20
20
  * `only`), die Platzhalter und die Arten der Fehlerregeln (Abschnitte
21
21
  * `placeholders` und `structure`).
22
22
  */
23
+ import type { ReceiptOutput } from '../models/receipt-output.js';
23
24
  import { type ErrorOutcome } from '../client/errors.js';
24
25
  export type Surface = 'web' | 'app';
25
26
  export interface TextEntry {
@@ -370,6 +371,52 @@ declare const MELDUNGEN_ROH: {
370
371
  readonly 'voucher_error.sale_off': {
371
372
  readonly text: "Gutscheine verkaufen geht hier noch nicht.";
372
373
  };
374
+ readonly 'voucher.reentry_needed': {
375
+ readonly text: "Die Karte ist belastet, der Beleg fehlt noch: zu jedem Gutschein den Code erneut eingeben, dann den Beleg abschließen.";
376
+ };
377
+ readonly 'voucher.reentry_mismatch': {
378
+ readonly text: "Mit diesen Gutscheinen ergibt der Beleg nicht mehr den belasteten Betrag – die Karte zurückbuchen.";
379
+ };
380
+ readonly 'voucher.not_this_voucher': {
381
+ readonly text: "Das ist nicht der Gutschein ····-{suffix}.";
382
+ readonly placeholders: readonly ["suffix"];
383
+ };
384
+ readonly 'voucher.reentry_no_permission': {
385
+ readonly text: "Die Karte ist belastet, der Beleg fehlt noch: den Gutschein-Code kann nur jemand mit dem Recht zum Einlösen nachtragen – sonst die Karte zurückbuchen.";
386
+ };
387
+ readonly 'voucher.already_covered': {
388
+ readonly text: "Diese Positionen deckt schon ein anderer Gutschein.";
389
+ };
390
+ readonly 'voucher.payout_reason_too_long': {
391
+ readonly text: "Der Grund hat höchstens 200 Zeichen.";
392
+ };
393
+ readonly 'voucher.payout_reason_missing': {
394
+ readonly text: "Für die Auszahlung fehlt der Grund.";
395
+ };
396
+ readonly 'voucher.payout_check_first': {
397
+ readonly text: "Die letzte Auszahlung ging unklar aus und kann schon gebucht sein. Erst unter „Belege“ die Liste neu laden und nachsehen, dann ist eine neue möglich.";
398
+ };
399
+ readonly 'voucher.sale_max_amount': {
400
+ readonly text: "Höchstens {amount} je Gutschein.";
401
+ readonly placeholders: readonly ["amount"];
402
+ };
403
+ readonly 'voucher.sale_not_at_terminal': {
404
+ readonly text: "Gutscheine mit Karte am Terminal zu verkaufen geht an dieser Kasse noch nicht – bar kassieren.";
405
+ };
406
+ readonly 'voucher.no_redeem_with_sale': {
407
+ readonly text: "Auf einem Beleg, der Gutscheine verkauft, lässt sich kein Gutschein einlösen.";
408
+ };
409
+ readonly 'voucher.code_not_on_receipt': {
410
+ readonly text: "Der Code steht nicht auf dem Bon – jetzt auf den Gutschein schreiben.";
411
+ };
412
+ readonly 'cancellation.voucher_sale_cancelled': {
413
+ readonly text: "Der Gutschein ····-{suffix} wird mitstorniert und gilt danach nicht mehr.";
414
+ readonly placeholders: readonly ["suffix"];
415
+ };
416
+ readonly 'cancellation.promo_valid_again': {
417
+ readonly text: "Der Aktionsgutschein ····-{suffix} gilt danach wieder.";
418
+ readonly placeholders: readonly ["suffix"];
419
+ };
373
420
  readonly 'split.setting_hint': {
374
421
  readonly text: "Ein Tisch zahlt in Teilen: jede Zahlung bar oder mit Karte, mit eigenem Trinkgeld – am Ende ein Beleg für alles.";
375
422
  };
@@ -1623,6 +1670,9 @@ declare const BESCHRIFTUNGEN_ROH: {
1623
1670
  readonly 'drawer.reason_shift_close': {
1624
1671
  readonly text: "Schichtabschluss";
1625
1672
  };
1673
+ readonly 'drawer.reason_voucher_payout': {
1674
+ readonly text: "Gutschein-Auszahlung";
1675
+ };
1626
1676
  readonly 'shift.resend': {
1627
1677
  readonly text: "Erneut senden";
1628
1678
  };
@@ -1720,6 +1770,79 @@ declare const BESCHRIFTUNGEN_ROH: {
1720
1770
  readonly text: "Gutschein ····-{suffix}";
1721
1771
  readonly placeholders: readonly ["suffix"];
1722
1772
  };
1773
+ readonly 'quantity.at_most': {
1774
+ readonly text: "höchstens {count}";
1775
+ readonly placeholders: readonly ["count"];
1776
+ };
1777
+ readonly 'quantity.at_least': {
1778
+ readonly text: "mindestens {count}";
1779
+ readonly placeholders: readonly ["count"];
1780
+ };
1781
+ readonly 'receipts.number_hint': {
1782
+ readonly text: "Nummer";
1783
+ };
1784
+ readonly 'receipts.clear_number': {
1785
+ readonly text: "Nummer löschen";
1786
+ };
1787
+ readonly 'receipts.open': {
1788
+ readonly text: "Öffnen";
1789
+ };
1790
+ readonly 'receipt.creating': {
1791
+ readonly text: "Beleg wird erstellt …";
1792
+ };
1793
+ readonly 'receipt_done.sale_title': {
1794
+ readonly text: "Verkauf abgeschlossen";
1795
+ };
1796
+ readonly 'receipt_done.paid_by_voucher': {
1797
+ readonly text: "mit Gutschein bezahlt";
1798
+ };
1799
+ readonly 'receipt_done.payout_title': {
1800
+ readonly text: "Auszahlung abgeschlossen";
1801
+ };
1802
+ readonly 'receipt_done.paid_out': {
1803
+ readonly text: "{method} ausgezahlt";
1804
+ readonly placeholders: readonly ["method"];
1805
+ };
1806
+ readonly 'voucher.code_mask': {
1807
+ readonly text: "····-{suffix}";
1808
+ readonly placeholders: readonly ["suffix"];
1809
+ };
1810
+ readonly 'cart.close': {
1811
+ readonly text: "Warenkorb schließen";
1812
+ };
1813
+ readonly 'nav.register': {
1814
+ readonly text: "Kasse";
1815
+ };
1816
+ readonly 'nav.receipts': {
1817
+ readonly text: "Belege";
1818
+ };
1819
+ readonly 'nav.vouchers': {
1820
+ readonly text: "Gutscheine";
1821
+ };
1822
+ readonly 'nav.open_drawer': {
1823
+ readonly text: "Kassenlade öffnen";
1824
+ };
1825
+ readonly 'nav.stocktake': {
1826
+ readonly text: "Inventur";
1827
+ };
1828
+ readonly 'nav.settings': {
1829
+ readonly text: "Einstellungen";
1830
+ };
1831
+ readonly 'nav.settings_locked': {
1832
+ readonly text: "nur mit Chef-Anmeldung";
1833
+ };
1834
+ readonly 'nav.logout': {
1835
+ readonly text: "Abmelden";
1836
+ };
1837
+ readonly 'nav.logging_out': {
1838
+ readonly text: "Wird abgemeldet …";
1839
+ };
1840
+ readonly 'nav.fullscreen': {
1841
+ readonly text: "Vollbild";
1842
+ };
1843
+ readonly 'nav.fullscreen_exit': {
1844
+ readonly text: "Vollbild verlassen";
1845
+ };
1723
1846
  readonly 'voucher.covers_items': {
1724
1847
  readonly text: "Deckt: {items}";
1725
1848
  readonly placeholders: readonly ["items"];
@@ -1746,6 +1869,33 @@ declare const BESCHRIFTUNGEN_ROH: {
1746
1869
  readonly text: "{amount} geht zurück auf den Gutschein";
1747
1870
  readonly placeholders: readonly ["amount"];
1748
1871
  };
1872
+ readonly 'voucher.apply': {
1873
+ readonly text: "Übernehmen";
1874
+ };
1875
+ readonly 'voucher.redeemable_until': {
1876
+ readonly text: "einlösbar bis {date}";
1877
+ readonly placeholders: readonly ["date"];
1878
+ };
1879
+ readonly 'voucher.remove_line': {
1880
+ readonly text: "{line} entfernen";
1881
+ readonly placeholders: readonly ["line"];
1882
+ };
1883
+ readonly 'voucher.reenter_code': {
1884
+ readonly text: "Code erneut eingeben";
1885
+ };
1886
+ readonly 'voucher.refundable_until': {
1887
+ readonly text: "rückzahlbar bis {date}";
1888
+ readonly placeholders: readonly ["date"];
1889
+ };
1890
+ readonly 'voucher.code_done': {
1891
+ readonly text: "Fertig";
1892
+ };
1893
+ readonly 'voucher.article': {
1894
+ readonly text: "Artikel";
1895
+ };
1896
+ readonly 'voucher.add': {
1897
+ readonly text: "Hinzufügen";
1898
+ };
1749
1899
  readonly 'shift.all_payments': {
1750
1900
  readonly text: "Alle Zahlungen dieser Schicht (bar + unbar)";
1751
1901
  };
@@ -1915,6 +2065,35 @@ declare const BESCHRIFTUNGEN_ROH: {
1915
2065
  readonly text: "{amount} auszahlen";
1916
2066
  readonly placeholders: readonly ["amount"];
1917
2067
  };
2068
+ readonly 'receipt.outputs_title': {
2069
+ readonly text: "Ausgaben";
2070
+ };
2071
+ readonly 'receipt.outputs_count': {
2072
+ readonly text: "{count} Ausgaben";
2073
+ readonly placeholders: readonly ["count"];
2074
+ };
2075
+ readonly 'receipt.output_print': {
2076
+ readonly text: "Erstdruck";
2077
+ };
2078
+ readonly 'receipt.output_reprint': {
2079
+ readonly text: "Duplikat";
2080
+ };
2081
+ readonly 'receipt.output_email': {
2082
+ readonly text: "E-Mail";
2083
+ };
2084
+ readonly 'receipt.output_link_shared': {
2085
+ readonly text: "Link geteilt";
2086
+ };
2087
+ readonly 'receipt.output_pdf_shared': {
2088
+ readonly text: "PDF geteilt";
2089
+ };
2090
+ readonly 'receipt.output_opened': {
2091
+ readonly text: "Link geöffnet ({count}×)";
2092
+ readonly placeholders: readonly ["count"];
2093
+ };
2094
+ readonly 'receipt.output_failed': {
2095
+ readonly text: "fehlgeschlagen";
2096
+ };
1918
2097
  };
1919
2098
  export type LabelKey = keyof typeof BESCHRIFTUNGEN_ROH;
1920
2099
  export declare const LABELS: Record<LabelKey, TextEntry>;
@@ -1929,6 +2108,14 @@ export declare const RETURN_DISPOSITION_LABELS: {
1929
2108
  readonly defective: "stock.return_defective";
1930
2109
  readonly disposed: "stock.return_disposed";
1931
2110
  };
2111
+ /**
2112
+ * Die Beschriftung der Art einer Ausgabe (Belegdetail, Zeile „Ausgaben“), nie
2113
+ * eine Ausnahme: `null` bei einer Art, die dieses Paket nicht kennt (neuerer
2114
+ * Server); `opened` ohne gueltige Anzahl (ganze Zahl ab 1) zaehlt als ein
2115
+ * Abruf. Nur die Art: „fehlgeschlagen“ (`receipt.output_failed`) setzt die
2116
+ * Kasse selbst dazu, wenn `result` `failed` ist.
2117
+ */
2118
+ export declare function receiptOutputLabel(output: ReceiptOutput): string | null;
1932
2119
  /** Die Beschriftung zum Schluessel, Platzhalter ersetzt; fehlt ein Wert, wirft es wie `messageText`. */
1933
2120
  export declare function labelText(key: LabelKey, values?: Record<string, string | number>): string;
1934
2121
  /** Der Satz zum Schluessel, Platzhalter ersetzt. Fehlt ein Wert, wirft es — ein `{status}` am Tresen waere schlimmer. */
@@ -195,6 +195,21 @@ const MELDUNGEN_ROH = {
195
195
  'voucher_error.settings_missing': { text: 'Die Gutschein-Einstellungen fehlen. Bitte die Kasse neu laden.' },
196
196
  'voucher_error.too_many_checks': { text: 'Zu viele Versuche. Bitte in einer Stunde wieder.' },
197
197
  'voucher_error.sale_off': { text: 'Gutscheine verkaufen geht hier noch nicht.' },
198
+ // Gutscheine an der Kasse, Stufe 3 (1.13.0): Sätze der Kasse selbst (nicht des Servers).
199
+ 'voucher.reentry_needed': { text: 'Die Karte ist belastet, der Beleg fehlt noch: zu jedem Gutschein den Code erneut eingeben, dann den Beleg abschließen.' },
200
+ 'voucher.reentry_mismatch': { text: 'Mit diesen Gutscheinen ergibt der Beleg nicht mehr den belasteten Betrag – die Karte zurückbuchen.' },
201
+ 'voucher.not_this_voucher': { text: 'Das ist nicht der Gutschein ····-{suffix}.', placeholders: ['suffix'] },
202
+ 'voucher.reentry_no_permission': { text: 'Die Karte ist belastet, der Beleg fehlt noch: den Gutschein-Code kann nur jemand mit dem Recht zum Einlösen nachtragen – sonst die Karte zurückbuchen.' },
203
+ 'voucher.already_covered': { text: 'Diese Positionen deckt schon ein anderer Gutschein.' },
204
+ 'voucher.payout_reason_too_long': { text: 'Der Grund hat höchstens 200 Zeichen.' },
205
+ 'voucher.payout_reason_missing': { text: 'Für die Auszahlung fehlt der Grund.' },
206
+ 'voucher.payout_check_first': { text: 'Die letzte Auszahlung ging unklar aus und kann schon gebucht sein. Erst unter „Belege“ die Liste neu laden und nachsehen, dann ist eine neue möglich.' },
207
+ 'voucher.sale_max_amount': { text: 'Höchstens {amount} je Gutschein.', placeholders: ['amount'] },
208
+ 'voucher.sale_not_at_terminal': { text: 'Gutscheine mit Karte am Terminal zu verkaufen geht an dieser Kasse noch nicht – bar kassieren.' },
209
+ 'voucher.no_redeem_with_sale': { text: 'Auf einem Beleg, der Gutscheine verkauft, lässt sich kein Gutschein einlösen.' },
210
+ 'voucher.code_not_on_receipt': { text: 'Der Code steht nicht auf dem Bon – jetzt auf den Gutschein schreiben.' },
211
+ 'cancellation.voucher_sale_cancelled': { text: 'Der Gutschein ····-{suffix} wird mitstorniert und gilt danach nicht mehr.', placeholders: ['suffix'] },
212
+ 'cancellation.promo_valid_again': { text: 'Der Aktionsgutschein ····-{suffix} gilt danach wieder.', placeholders: ['suffix'] },
198
213
  // --- Getrennt zahlen -----------------------------------------------------
199
214
  // Ein Tisch zahlt in Teilen, ein Beleg fuer alles. Das Teure ist eine schon
200
215
  // belastete Karte: jeder Satz, der sie betrifft, nennt den Betrag, und keiner
@@ -852,6 +867,7 @@ const BESCHRIFTUNGEN_ROH = {
852
867
  'drawer.reason_cash_movement': { text: 'Kassenbewegung' },
853
868
  'drawer.reason_shift_open': { text: 'Schichtbeginn' },
854
869
  'drawer.reason_shift_close': { text: 'Schichtabschluss' },
870
+ 'drawer.reason_voucher_payout': { text: 'Gutschein-Auszahlung' },
855
871
  'shift.resend': { text: 'Erneut senden' },
856
872
  'shift.next': { text: 'Weiter' },
857
873
  'shift.print_close': { text: 'Schichtabschluss drucken' },
@@ -884,6 +900,30 @@ const BESCHRIFTUNGEN_ROH = {
884
900
  'voucher.service': { text: 'Leistungsgutschein' },
885
901
  'voucher.promotion': { text: 'Aktionsgutschein' },
886
902
  'voucher.payment_line': { text: 'Gutschein ····-{suffix}', placeholders: ['suffix'] },
903
+ // Kassen-Navigation, Beleg-Fertig-Seite, Mengen (Paket-Nachzug Gutscheine).
904
+ 'quantity.at_most': { text: 'höchstens {count}', placeholders: ['count'] },
905
+ 'quantity.at_least': { text: 'mindestens {count}', placeholders: ['count'] },
906
+ 'receipts.number_hint': { text: 'Nummer' },
907
+ 'receipts.clear_number': { text: 'Nummer löschen' },
908
+ 'receipts.open': { text: 'Öffnen' },
909
+ 'receipt.creating': { text: 'Beleg wird erstellt …' },
910
+ 'receipt_done.sale_title': { text: 'Verkauf abgeschlossen' },
911
+ 'receipt_done.paid_by_voucher': { text: 'mit Gutschein bezahlt' },
912
+ 'receipt_done.payout_title': { text: 'Auszahlung abgeschlossen' },
913
+ 'receipt_done.paid_out': { text: '{method} ausgezahlt', placeholders: ['method'] },
914
+ 'voucher.code_mask': { text: '····-{suffix}', placeholders: ['suffix'] },
915
+ 'cart.close': { text: 'Warenkorb schließen' },
916
+ 'nav.register': { text: 'Kasse' },
917
+ 'nav.receipts': { text: 'Belege' },
918
+ 'nav.vouchers': { text: 'Gutscheine' },
919
+ 'nav.open_drawer': { text: 'Kassenlade öffnen' },
920
+ 'nav.stocktake': { text: 'Inventur' },
921
+ 'nav.settings': { text: 'Einstellungen' },
922
+ 'nav.settings_locked': { text: 'nur mit Chef-Anmeldung' },
923
+ 'nav.logout': { text: 'Abmelden' },
924
+ 'nav.logging_out': { text: 'Wird abgemeldet …' },
925
+ 'nav.fullscreen': { text: 'Vollbild' },
926
+ 'nav.fullscreen_exit': { text: 'Vollbild verlassen' },
887
927
  'voucher.covers_items': { text: 'Deckt: {items}', placeholders: ['items'] },
888
928
  'voucher.code_shown_once': { text: 'Code nur jetzt sichtbar: {code}', placeholders: ['code'] },
889
929
  'voucher.not_in_split': { text: 'Gutscheine gehen beim getrennten Kassieren nicht.' },
@@ -891,6 +931,15 @@ const BESCHRIFTUNGEN_ROH = {
891
931
  'voucher.add_article': { text: '{article} hinzufügen', placeholders: ['article'] },
892
932
  'voucher.payout_confirm': { text: '{amount} bar auszahlen?', placeholders: ['amount'] },
893
933
  'cancellation.voucher_back': { text: '{amount} geht zurück auf den Gutschein', placeholders: ['amount'] },
934
+ // Gutscheine an der Kasse, Stufe 3 (1.13.0)
935
+ 'voucher.apply': { text: 'Übernehmen' },
936
+ 'voucher.redeemable_until': { text: 'einlösbar bis {date}', placeholders: ['date'] },
937
+ 'voucher.remove_line': { text: '{line} entfernen', placeholders: ['line'] },
938
+ 'voucher.reenter_code': { text: 'Code erneut eingeben' },
939
+ 'voucher.refundable_until': { text: 'rückzahlbar bis {date}', placeholders: ['date'] },
940
+ 'voucher.code_done': { text: 'Fertig' },
941
+ 'voucher.article': { text: 'Artikel' },
942
+ 'voucher.add': { text: 'Hinzufügen' },
894
943
  'shift.all_payments': { text: 'Alle Zahlungen dieser Schicht (bar + unbar)' },
895
944
  'shift.receipt_count_one': { text: '1 Beleg' },
896
945
  'shift.receipt_count_other': { text: '{count} Belege', placeholders: ['count'] },
@@ -951,6 +1000,18 @@ const BESCHRIFTUNGEN_ROH = {
951
1000
  'shift.pay_outs': { text: 'Auszahlungen' },
952
1001
  'cash_movement.pay_in_amount': { text: '{amount} einzahlen', placeholders: ['amount'] },
953
1002
  'cash_movement.pay_out_amount': { text: '{amount} auszahlen', placeholders: ['amount'] },
1003
+ // Belegdetail: Zeile „Ausgaben“ (eingeklappt mit Anzahl), aufgeklappt je Eintrag die Art
1004
+ // (`receipt.output_<kind>`, Arten wie RECEIPT_OUTPUT_KINDS), dazu „fehlgeschlagen“ bei Ergebnis `failed`.
1005
+ // `{count}` beim Abruf ist die Zahl der Abrufe in dieser Stunde.
1006
+ 'receipt.outputs_title': { text: 'Ausgaben' },
1007
+ 'receipt.outputs_count': { text: '{count} Ausgaben', placeholders: ['count'] },
1008
+ 'receipt.output_print': { text: 'Erstdruck' },
1009
+ 'receipt.output_reprint': { text: 'Duplikat' },
1010
+ 'receipt.output_email': { text: 'E-Mail' },
1011
+ 'receipt.output_link_shared': { text: 'Link geteilt' },
1012
+ 'receipt.output_pdf_shared': { text: 'PDF geteilt' },
1013
+ 'receipt.output_opened': { text: 'Link geöffnet ({count}×)', placeholders: ['count'] },
1014
+ 'receipt.output_failed': { text: 'fehlgeschlagen' },
954
1015
  };
955
1016
  export const LABELS = BESCHRIFTUNGEN_ROH;
956
1017
  /**
@@ -964,6 +1025,32 @@ export const RETURN_DISPOSITION_LABELS = {
964
1025
  defective: 'stock.return_defective',
965
1026
  disposed: 'stock.return_disposed',
966
1027
  };
1028
+ /** Art einer Ausgabe -> Beschriftung (`receipt.output_<kind>`). */
1029
+ const AUSGABE_BESCHRIFTUNG = {
1030
+ print: 'receipt.output_print',
1031
+ reprint: 'receipt.output_reprint',
1032
+ email: 'receipt.output_email',
1033
+ link_shared: 'receipt.output_link_shared',
1034
+ pdf_shared: 'receipt.output_pdf_shared',
1035
+ opened: 'receipt.output_opened',
1036
+ };
1037
+ /**
1038
+ * Die Beschriftung der Art einer Ausgabe (Belegdetail, Zeile „Ausgaben“), nie
1039
+ * eine Ausnahme: `null` bei einer Art, die dieses Paket nicht kennt (neuerer
1040
+ * Server); `opened` ohne gueltige Anzahl (ganze Zahl ab 1) zaehlt als ein
1041
+ * Abruf. Nur die Art: „fehlgeschlagen“ (`receipt.output_failed`) setzt die
1042
+ * Kasse selbst dazu, wenn `result` `failed` ist.
1043
+ */
1044
+ export function receiptOutputLabel(output) {
1045
+ const art = output?.kind;
1046
+ if (typeof art !== 'string' || !Object.prototype.hasOwnProperty.call(AUSGABE_BESCHRIFTUNG, art))
1047
+ return null;
1048
+ const key = AUSGABE_BESCHRIFTUNG[art];
1049
+ if (art !== 'opened')
1050
+ return labelText(key);
1051
+ const anzahl = output.count;
1052
+ return labelText(key, { count: typeof anzahl === 'number' && Number.isSafeInteger(anzahl) && anzahl >= 1 ? anzahl : 1 });
1053
+ }
967
1054
  /** Die Beschriftung zum Schluessel, Platzhalter ersetzt; fehlt ein Wert, wirft es wie `messageText`. */
968
1055
  export function labelText(key, values = {}) {
969
1056
  return ersetze(`labelText(${key})`, LABELS[key].text, values);
@@ -183,7 +183,8 @@ export interface VoucherRedeemContext {
183
183
  * Hoechstbetrag zum Vorbelegen einer Einloesung an der Kasse, in Cent, nie
184
184
  * negativ: der groesste Betrag, den der Server fuer diesen Gutschein annimmt.
185
185
  *
186
- * Obergrenze: Saldo, offener Betrag; bei Einzweck die deckbaren Positionen im
186
+ * Obergrenze: Saldo, offener Betrag ohne Trinkgeld (ein Gutschein deckt nie
187
+ * das Trinkgeld, Personal wie Inhaber); bei Einzweck die deckbaren Positionen im
187
188
  * Topf seines Satzes abzueglich der schon gewaehlten Einloesungen dort. Befreit
188
189
  * verkauft bzw. als Kleinunternehmer verteilt der Server anteilig auf alle
189
190
  * Saetze (`kuTeile`); dann begrenzt jeder Topf: sein Anteil plus die schon
@@ -195,6 +196,7 @@ export interface VoucherRedeemContext {
195
196
  * Bisektion ueber [1, Grenze] und prueft danach 16 Cent aufwaerts: am Rand
196
197
  * des groessten Rests ist die Annahme nicht monoton. Leistung (wird ueber
197
198
  * Positionen eingeloest), Aktion (Rabatt rechnet der Server) und jeder nicht
198
- * aktive Gutschein: 0.
199
+ * aktive Gutschein: 0. Wirft nie [ReceiptDueError]: ist der Beleg ohne den
200
+ * Gutschein nicht rechenbar (etwa `tip_without_goods`), ist das Ergebnis 0.
199
201
  */
200
202
  export declare function voucherRedeemMaxCents(items: readonly ReceiptItem[], voucher: VoucherCheck, before?: VoucherRedeemContext): number;
@@ -1,7 +1,7 @@
1
1
  import { ReceiptType, VoucherAction, VoucherType } from '../enums/index.js';
2
2
  import { VoucherCode } from '@kreiseck/validator';
3
3
  import { toViennaWallClock } from '../vienna-time.js';
4
- import { centSumme, istDeckbar, kuSaetze, planeGutscheine, topfFuerSatz, } from './gutschein-plan.js';
4
+ import { centSumme, istDeckbar, kuSaetze, planeGutscheine, topfFuerSatz, trinkgeldCents, } from './gutschein-plan.js';
5
5
  export { VOUCHER_ZERO_RATE_BUCKET_FROM } from './gutschein-plan.js';
6
6
  /**
7
7
  * Warum sich der Zahlbetrag nicht rechnen laesst. Fest wie ein Backend-Code;
@@ -101,6 +101,12 @@ function rechne(items, vouchers, receiptType, options) {
101
101
  if (plan.mitPlan && dueCents + plan.auszahlungCents < 0) {
102
102
  throw new ReceiptDueError('invalid_voucher', 'die Gutscheine uebersteigen die Summe des Belegs.', 'voucher_exceeds_total');
103
103
  }
104
+ // Ein Gutschein deckt nie das Trinkgeld (Personal wie Inhaber): der Zahlbetrag nach den Gutscheinen
105
+ // muss die Trinkgeldzeilen tragen. Storno ausgenommen (dort gibt es keinen Plan).
106
+ const trinkgeld = trinkgeldCents(kunde);
107
+ if (plan.mitPlan && art !== 'cancellation' && trinkgeld > 0 && dueCents + plan.auszahlungCents < trinkgeld) {
108
+ throw new ReceiptDueError('invalid_voucher', 'die Gutscheine decken das Trinkgeld.', 'voucher_exceeds_total');
109
+ }
104
110
  return {
105
111
  ergebnis: {
106
112
  dueCents,
@@ -124,7 +130,8 @@ function rechne(items, vouchers, receiptType, options) {
124
130
  * Hoechstbetrag zum Vorbelegen einer Einloesung an der Kasse, in Cent, nie
125
131
  * negativ: der groesste Betrag, den der Server fuer diesen Gutschein annimmt.
126
132
  *
127
- * Obergrenze: Saldo, offener Betrag; bei Einzweck die deckbaren Positionen im
133
+ * Obergrenze: Saldo, offener Betrag ohne Trinkgeld (ein Gutschein deckt nie
134
+ * das Trinkgeld, Personal wie Inhaber); bei Einzweck die deckbaren Positionen im
128
135
  * Topf seines Satzes abzueglich der schon gewaehlten Einloesungen dort. Befreit
129
136
  * verkauft bzw. als Kleinunternehmer verteilt der Server anteilig auf alle
130
137
  * Saetze (`kuTeile`); dann begrenzt jeder Topf: sein Anteil plus die schon
@@ -136,7 +143,8 @@ function rechne(items, vouchers, receiptType, options) {
136
143
  * Bisektion ueber [1, Grenze] und prueft danach 16 Cent aufwaerts: am Rand
137
144
  * des groessten Rests ist die Annahme nicht monoton. Leistung (wird ueber
138
145
  * Positionen eingeloest), Aktion (Rabatt rechnet der Server) und jeder nicht
139
- * aktive Gutschein: 0.
146
+ * aktive Gutschein: 0. Wirft nie [ReceiptDueError]: ist der Beleg ohne den
147
+ * Gutschein nicht rechenbar (etwa `tip_without_goods`), ist das Ergebnis 0.
140
148
  */
141
149
  export function voucherRedeemMaxCents(items, voucher, before = {}) {
142
150
  if (voucher.status !== 'active')
@@ -146,9 +154,18 @@ export function voucherRedeemMaxCents(items, voucher, before = {}) {
146
154
  const saldo = Number.isInteger(voucher.balanceCents) ? voucher.balanceCents : 0;
147
155
  const options = before.options ?? {};
148
156
  const vorher = before.vouchers ?? [];
149
- const r = rechne(items, vorher, 'standard', options);
150
- // Rundung je Topf: hoechstens ein halber Cent je Topf ueber dem offenen Betrag.
151
- let oben = Math.min(saldo, r.ergebnis.dueCents + r.auszahlungCents + 6, HOECHSTBETRAG_CENTS);
157
+ let r;
158
+ try {
159
+ r = rechne(items, vorher, 'standard', options);
160
+ }
161
+ catch (fehler) {
162
+ // Nicht rechenbar (etwa Trinkgeld ohne Ware): nichts vorbelegen, die Kasse meldet es beim Zahlbetrag.
163
+ if (fehler instanceof ReceiptDueError)
164
+ return 0;
165
+ throw fehler;
166
+ }
167
+ // Rundung je Topf: hoechstens ein halber Cent je Topf ueber dem offenen Betrag. Das Trinkgeld deckt nie ein Gutschein.
168
+ let oben = Math.min(saldo, r.ergebnis.dueCents + r.auszahlungCents - trinkgeldCents(r.kunde) + 6, HOECHSTBETRAG_CENTS);
152
169
  if (voucher.type === 'single_purpose') {
153
170
  const deckbar = r.kunde.filter(istDeckbar);
154
171
  const topfBasis = (topf) => centSumme(deckbar.filter((it) => topfFuerSatz(it.vat) === topf));
@@ -0,0 +1,35 @@
1
+ import type { ReceiptLayout } from './layout.js';
2
+ /**
3
+ * Kennzeichnet einen Nachdruck als **Belegduplikat**. Registrierkassen-Erlass
4
+ * BMF-AV Nr. 2/2026, Abschnitt 4.5.6: „Ein Belegduplikat ist als solches zu
5
+ * bezeichnen, nicht nochmals zu signieren, nicht neuerlich im
6
+ * Datenerfassungsprotokoll aufzunehmen und darf zu keiner Veränderung des
7
+ * Umsatzzählers führen.“ Signatur, DEP und Zähler bleiben ohnehin unberührt,
8
+ * weil ein Nachdruck den gespeicherten Beleg druckt; diese Funktion liefert
9
+ * die Bezeichnung.
10
+ *
11
+ * Die Kasse ruft sie bei **jedem** Nachdruck und bei „Kopie drucken“ mit dem
12
+ * Zeitpunkt des Drucks auf, nie beim Erstdruck und nie fuer Mail, Link oder
13
+ * PDF, und gibt das Ergebnis an denselben Druckweg (`escPosLayoutBytes`,
14
+ * `eposPrintXml`, `receiptSheet`, React-Ansicht).
15
+ *
16
+ * Neu ist genau eine Zeile im Kennungsblock, direkt unter `Beleg-ID:`, in
17
+ * der Spaltenform von `Datum:` (nicht fett, Wert rechtsbuendig):
18
+ *
19
+ * ```
20
+ * Beleg-ID: AT0-KASSE1-42
21
+ * Duplikat am: 24.10.2026 14:10:05
22
+ * ```
23
+ *
24
+ * `printedAt` ist ein Zeitpunkt; gedruckt wird er in Wiener Zeit
25
+ * (Sommerzeit nach EU-Regel), nie in der Zeitzone des Rechners. Ohne
26
+ * Spaltenzeile `Beleg-ID:` (Schicht-Bons) steht die Zeile ganz oben. Alles
27
+ * andere bleibt Zeile fuer Zeile wie beim Erstdruck.
28
+ *
29
+ * Reine Funktion: die Eingabe bleibt unangetastet, das Ergebnis ist eine
30
+ * eigene Kopie. Traegt das Layout schon eine Zeile `Duplikat am:`, bekommt
31
+ * nur sie die neue Zeit (der letzte Nachdruck gilt); es bleibt bei einer
32
+ * Zeile. Ein unbrauchbarer Zeitpunkt wirft `KasseneckValidationError`
33
+ * (`scope: 'request'`).
34
+ */
35
+ export declare function markAsDuplicate(layout: ReceiptLayout, printedAt: Date): ReceiptLayout;