@kreiseck/kasseneck-api 1.13.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 +23 -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 +114 -0
  32. package/dist/cjs/pos/texte.js +64 -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 +114 -0
  78. package/dist/esm/pos/texte.js +63 -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 +118 -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
@@ -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 {
@@ -1669,6 +1670,9 @@ declare const BESCHRIFTUNGEN_ROH: {
1669
1670
  readonly 'drawer.reason_shift_close': {
1670
1671
  readonly text: "Schichtabschluss";
1671
1672
  };
1673
+ readonly 'drawer.reason_voucher_payout': {
1674
+ readonly text: "Gutschein-Auszahlung";
1675
+ };
1672
1676
  readonly 'shift.resend': {
1673
1677
  readonly text: "Erneut senden";
1674
1678
  };
@@ -1766,6 +1770,79 @@ declare const BESCHRIFTUNGEN_ROH: {
1766
1770
  readonly text: "Gutschein ····-{suffix}";
1767
1771
  readonly placeholders: readonly ["suffix"];
1768
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
+ };
1769
1846
  readonly 'voucher.covers_items': {
1770
1847
  readonly text: "Deckt: {items}";
1771
1848
  readonly placeholders: readonly ["items"];
@@ -1988,6 +2065,35 @@ declare const BESCHRIFTUNGEN_ROH: {
1988
2065
  readonly text: "{amount} auszahlen";
1989
2066
  readonly placeholders: readonly ["amount"];
1990
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
+ };
1991
2097
  };
1992
2098
  export type LabelKey = keyof typeof BESCHRIFTUNGEN_ROH;
1993
2099
  export declare const LABELS: Record<LabelKey, TextEntry>;
@@ -2002,6 +2108,14 @@ export declare const RETURN_DISPOSITION_LABELS: {
2002
2108
  readonly defective: "stock.return_defective";
2003
2109
  readonly disposed: "stock.return_disposed";
2004
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;
2005
2119
  /** Die Beschriftung zum Schluessel, Platzhalter ersetzt; fehlt ein Wert, wirft es wie `messageText`. */
2006
2120
  export declare function labelText(key: LabelKey, values?: Record<string, string | number>): string;
2007
2121
  /** Der Satz zum Schluessel, Platzhalter ersetzt. Fehlt ein Wert, wirft es — ein `{status}` am Tresen waere schlimmer. */
@@ -28,6 +28,7 @@ exports.messageOutcome = messageOutcome;
28
28
  exports.receiptEmailErrorMessage = receiptEmailErrorMessage;
29
29
  exports.cancellationPaymentErrorMessage = cancellationPaymentErrorMessage;
30
30
  exports.voucherErrorMessage = voucherErrorMessage;
31
+ exports.receiptOutputLabel = receiptOutputLabel;
31
32
  exports.labelText = labelText;
32
33
  exports.messageText = messageText;
33
34
  exports.messageAppliesTo = messageAppliesTo;
@@ -878,6 +879,7 @@ const BESCHRIFTUNGEN_ROH = {
878
879
  'drawer.reason_cash_movement': { text: 'Kassenbewegung' },
879
880
  'drawer.reason_shift_open': { text: 'Schichtbeginn' },
880
881
  'drawer.reason_shift_close': { text: 'Schichtabschluss' },
882
+ 'drawer.reason_voucher_payout': { text: 'Gutschein-Auszahlung' },
881
883
  'shift.resend': { text: 'Erneut senden' },
882
884
  'shift.next': { text: 'Weiter' },
883
885
  'shift.print_close': { text: 'Schichtabschluss drucken' },
@@ -910,6 +912,30 @@ const BESCHRIFTUNGEN_ROH = {
910
912
  'voucher.service': { text: 'Leistungsgutschein' },
911
913
  'voucher.promotion': { text: 'Aktionsgutschein' },
912
914
  'voucher.payment_line': { text: 'Gutschein ····-{suffix}', placeholders: ['suffix'] },
915
+ // Kassen-Navigation, Beleg-Fertig-Seite, Mengen (Paket-Nachzug Gutscheine).
916
+ 'quantity.at_most': { text: 'höchstens {count}', placeholders: ['count'] },
917
+ 'quantity.at_least': { text: 'mindestens {count}', placeholders: ['count'] },
918
+ 'receipts.number_hint': { text: 'Nummer' },
919
+ 'receipts.clear_number': { text: 'Nummer löschen' },
920
+ 'receipts.open': { text: 'Öffnen' },
921
+ 'receipt.creating': { text: 'Beleg wird erstellt …' },
922
+ 'receipt_done.sale_title': { text: 'Verkauf abgeschlossen' },
923
+ 'receipt_done.paid_by_voucher': { text: 'mit Gutschein bezahlt' },
924
+ 'receipt_done.payout_title': { text: 'Auszahlung abgeschlossen' },
925
+ 'receipt_done.paid_out': { text: '{method} ausgezahlt', placeholders: ['method'] },
926
+ 'voucher.code_mask': { text: '····-{suffix}', placeholders: ['suffix'] },
927
+ 'cart.close': { text: 'Warenkorb schließen' },
928
+ 'nav.register': { text: 'Kasse' },
929
+ 'nav.receipts': { text: 'Belege' },
930
+ 'nav.vouchers': { text: 'Gutscheine' },
931
+ 'nav.open_drawer': { text: 'Kassenlade öffnen' },
932
+ 'nav.stocktake': { text: 'Inventur' },
933
+ 'nav.settings': { text: 'Einstellungen' },
934
+ 'nav.settings_locked': { text: 'nur mit Chef-Anmeldung' },
935
+ 'nav.logout': { text: 'Abmelden' },
936
+ 'nav.logging_out': { text: 'Wird abgemeldet …' },
937
+ 'nav.fullscreen': { text: 'Vollbild' },
938
+ 'nav.fullscreen_exit': { text: 'Vollbild verlassen' },
913
939
  'voucher.covers_items': { text: 'Deckt: {items}', placeholders: ['items'] },
914
940
  'voucher.code_shown_once': { text: 'Code nur jetzt sichtbar: {code}', placeholders: ['code'] },
915
941
  'voucher.not_in_split': { text: 'Gutscheine gehen beim getrennten Kassieren nicht.' },
@@ -986,6 +1012,18 @@ const BESCHRIFTUNGEN_ROH = {
986
1012
  'shift.pay_outs': { text: 'Auszahlungen' },
987
1013
  'cash_movement.pay_in_amount': { text: '{amount} einzahlen', placeholders: ['amount'] },
988
1014
  'cash_movement.pay_out_amount': { text: '{amount} auszahlen', placeholders: ['amount'] },
1015
+ // Belegdetail: Zeile „Ausgaben“ (eingeklappt mit Anzahl), aufgeklappt je Eintrag die Art
1016
+ // (`receipt.output_<kind>`, Arten wie RECEIPT_OUTPUT_KINDS), dazu „fehlgeschlagen“ bei Ergebnis `failed`.
1017
+ // `{count}` beim Abruf ist die Zahl der Abrufe in dieser Stunde.
1018
+ 'receipt.outputs_title': { text: 'Ausgaben' },
1019
+ 'receipt.outputs_count': { text: '{count} Ausgaben', placeholders: ['count'] },
1020
+ 'receipt.output_print': { text: 'Erstdruck' },
1021
+ 'receipt.output_reprint': { text: 'Duplikat' },
1022
+ 'receipt.output_email': { text: 'E-Mail' },
1023
+ 'receipt.output_link_shared': { text: 'Link geteilt' },
1024
+ 'receipt.output_pdf_shared': { text: 'PDF geteilt' },
1025
+ 'receipt.output_opened': { text: 'Link geöffnet ({count}×)', placeholders: ['count'] },
1026
+ 'receipt.output_failed': { text: 'fehlgeschlagen' },
989
1027
  };
990
1028
  exports.LABELS = BESCHRIFTUNGEN_ROH;
991
1029
  /**
@@ -999,6 +1037,32 @@ exports.RETURN_DISPOSITION_LABELS = {
999
1037
  defective: 'stock.return_defective',
1000
1038
  disposed: 'stock.return_disposed',
1001
1039
  };
1040
+ /** Art einer Ausgabe -> Beschriftung (`receipt.output_<kind>`). */
1041
+ const AUSGABE_BESCHRIFTUNG = {
1042
+ print: 'receipt.output_print',
1043
+ reprint: 'receipt.output_reprint',
1044
+ email: 'receipt.output_email',
1045
+ link_shared: 'receipt.output_link_shared',
1046
+ pdf_shared: 'receipt.output_pdf_shared',
1047
+ opened: 'receipt.output_opened',
1048
+ };
1049
+ /**
1050
+ * Die Beschriftung der Art einer Ausgabe (Belegdetail, Zeile „Ausgaben“), nie
1051
+ * eine Ausnahme: `null` bei einer Art, die dieses Paket nicht kennt (neuerer
1052
+ * Server); `opened` ohne gueltige Anzahl (ganze Zahl ab 1) zaehlt als ein
1053
+ * Abruf. Nur die Art: „fehlgeschlagen“ (`receipt.output_failed`) setzt die
1054
+ * Kasse selbst dazu, wenn `result` `failed` ist.
1055
+ */
1056
+ function receiptOutputLabel(output) {
1057
+ const art = output?.kind;
1058
+ if (typeof art !== 'string' || !Object.prototype.hasOwnProperty.call(AUSGABE_BESCHRIFTUNG, art))
1059
+ return null;
1060
+ const key = AUSGABE_BESCHRIFTUNG[art];
1061
+ if (art !== 'opened')
1062
+ return labelText(key);
1063
+ const anzahl = output.count;
1064
+ return labelText(key, { count: typeof anzahl === 'number' && Number.isSafeInteger(anzahl) && anzahl >= 1 ? anzahl : 1 });
1065
+ }
1002
1066
  /** Die Beschriftung zum Schluessel, Platzhalter ersetzt; fehlt ein Wert, wirft es wie `messageText`. */
1003
1067
  function labelText(key, values = {}) {
1004
1068
  return ersetze(`labelText(${key})`, exports.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;
@@ -110,6 +110,12 @@ function rechne(items, vouchers, receiptType, options) {
110
110
  if (plan.mitPlan && dueCents + plan.auszahlungCents < 0) {
111
111
  throw new ReceiptDueError('invalid_voucher', 'die Gutscheine uebersteigen die Summe des Belegs.', 'voucher_exceeds_total');
112
112
  }
113
+ // Ein Gutschein deckt nie das Trinkgeld (Personal wie Inhaber): der Zahlbetrag nach den Gutscheinen
114
+ // muss die Trinkgeldzeilen tragen. Storno ausgenommen (dort gibt es keinen Plan).
115
+ const trinkgeld = (0, gutschein_plan_js_1.trinkgeldCents)(kunde);
116
+ if (plan.mitPlan && art !== 'cancellation' && trinkgeld > 0 && dueCents + plan.auszahlungCents < trinkgeld) {
117
+ throw new ReceiptDueError('invalid_voucher', 'die Gutscheine decken das Trinkgeld.', 'voucher_exceeds_total');
118
+ }
113
119
  return {
114
120
  ergebnis: {
115
121
  dueCents,
@@ -133,7 +139,8 @@ function rechne(items, vouchers, receiptType, options) {
133
139
  * Hoechstbetrag zum Vorbelegen einer Einloesung an der Kasse, in Cent, nie
134
140
  * negativ: der groesste Betrag, den der Server fuer diesen Gutschein annimmt.
135
141
  *
136
- * Obergrenze: Saldo, offener Betrag; bei Einzweck die deckbaren Positionen im
142
+ * Obergrenze: Saldo, offener Betrag ohne Trinkgeld (ein Gutschein deckt nie
143
+ * das Trinkgeld, Personal wie Inhaber); bei Einzweck die deckbaren Positionen im
137
144
  * Topf seines Satzes abzueglich der schon gewaehlten Einloesungen dort. Befreit
138
145
  * verkauft bzw. als Kleinunternehmer verteilt der Server anteilig auf alle
139
146
  * Saetze (`kuTeile`); dann begrenzt jeder Topf: sein Anteil plus die schon
@@ -145,7 +152,8 @@ function rechne(items, vouchers, receiptType, options) {
145
152
  * Bisektion ueber [1, Grenze] und prueft danach 16 Cent aufwaerts: am Rand
146
153
  * des groessten Rests ist die Annahme nicht monoton. Leistung (wird ueber
147
154
  * Positionen eingeloest), Aktion (Rabatt rechnet der Server) und jeder nicht
148
- * aktive Gutschein: 0.
155
+ * aktive Gutschein: 0. Wirft nie [ReceiptDueError]: ist der Beleg ohne den
156
+ * Gutschein nicht rechenbar (etwa `tip_without_goods`), ist das Ergebnis 0.
149
157
  */
150
158
  function voucherRedeemMaxCents(items, voucher, before = {}) {
151
159
  if (voucher.status !== 'active')
@@ -155,9 +163,18 @@ function voucherRedeemMaxCents(items, voucher, before = {}) {
155
163
  const saldo = Number.isInteger(voucher.balanceCents) ? voucher.balanceCents : 0;
156
164
  const options = before.options ?? {};
157
165
  const vorher = before.vouchers ?? [];
158
- const r = rechne(items, vorher, 'standard', options);
159
- // Rundung je Topf: hoechstens ein halber Cent je Topf ueber dem offenen Betrag.
160
- let oben = Math.min(saldo, r.ergebnis.dueCents + r.auszahlungCents + 6, HOECHSTBETRAG_CENTS);
166
+ let r;
167
+ try {
168
+ r = rechne(items, vorher, 'standard', options);
169
+ }
170
+ catch (fehler) {
171
+ // Nicht rechenbar (etwa Trinkgeld ohne Ware): nichts vorbelegen, die Kasse meldet es beim Zahlbetrag.
172
+ if (fehler instanceof ReceiptDueError)
173
+ return 0;
174
+ throw fehler;
175
+ }
176
+ // Rundung je Topf: hoechstens ein halber Cent je Topf ueber dem offenen Betrag. Das Trinkgeld deckt nie ein Gutschein.
177
+ let oben = Math.min(saldo, r.ergebnis.dueCents + r.auszahlungCents - (0, gutschein_plan_js_1.trinkgeldCents)(r.kunde) + 6, HOECHSTBETRAG_CENTS);
161
178
  if (voucher.type === 'single_purpose') {
162
179
  const deckbar = r.kunde.filter(gutschein_plan_js_1.istDeckbar);
163
180
  const topfBasis = (topf) => (0, gutschein_plan_js_1.centSumme)(deckbar.filter((it) => (0, gutschein_plan_js_1.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;
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.markAsDuplicate = markAsDuplicate;
4
+ const errors_js_1 = require("../client/errors.js");
5
+ const vienna_time_js_1 = require("../vienna-time.js");
6
+ /** Beschriftung der Duplikat-Zeile; derselbe Text im Dart-Zwilling. */
7
+ const DUPLIKAT_AM = 'Duplikat am:';
8
+ /**
9
+ * Spaltenbreiten in Zwoelfteln. 5:7 setzt Beschriftung (12 Zeichen) und Zeit
10
+ * (19 Zeichen) auf 32 und 48 Zeichen ohne Umbruch in eine Zeile, den Wert am
11
+ * rechten Rand wie bei `Datum:`: 13 + 19 bzw. 20 + 28 Zeichen. Die Breiten
12
+ * von `Beleg-ID:` (6:6) und `Datum:` (4:8) reichen auf 32 Zeichen nicht.
13
+ */
14
+ const LINKS = 5;
15
+ const RECHTS = 7;
16
+ /** Eigene Kopie einer Zeile: wer am Duplikat dreht, dreht nie am Erstdruck. */
17
+ function kopie(zeile) {
18
+ return zeile.kind === 'columns' ? { ...zeile, columns: zeile.columns.map((c) => ({ ...c })) } : { ...zeile };
19
+ }
20
+ const istZeile = (z, beschriftung) => z.kind === 'columns' && z.columns[0]?.text === beschriftung;
21
+ /** Zeitpunkt als `TT.MM.JJJJ HH:MM:SS` in Wiener Zeit; Bruchteile fallen weg. */
22
+ function wienerZeit(zeitpunkt) {
23
+ const t = (0, vienna_time_js_1.toViennaWallClock)(zeitpunkt);
24
+ const zwei = (n) => String(n).padStart(2, '0');
25
+ return `${zwei(t.day)}.${zwei(t.month)}.${t.year} ${zwei(t.hour)}:${zwei(t.minute)}:${zwei(t.second)}`;
26
+ }
27
+ /**
28
+ * Kennzeichnet einen Nachdruck als **Belegduplikat**. Registrierkassen-Erlass
29
+ * BMF-AV Nr. 2/2026, Abschnitt 4.5.6: „Ein Belegduplikat ist als solches zu
30
+ * bezeichnen, nicht nochmals zu signieren, nicht neuerlich im
31
+ * Datenerfassungsprotokoll aufzunehmen und darf zu keiner Veränderung des
32
+ * Umsatzzählers führen.“ Signatur, DEP und Zähler bleiben ohnehin unberührt,
33
+ * weil ein Nachdruck den gespeicherten Beleg druckt; diese Funktion liefert
34
+ * die Bezeichnung.
35
+ *
36
+ * Die Kasse ruft sie bei **jedem** Nachdruck und bei „Kopie drucken“ mit dem
37
+ * Zeitpunkt des Drucks auf, nie beim Erstdruck und nie fuer Mail, Link oder
38
+ * PDF, und gibt das Ergebnis an denselben Druckweg (`escPosLayoutBytes`,
39
+ * `eposPrintXml`, `receiptSheet`, React-Ansicht).
40
+ *
41
+ * Neu ist genau eine Zeile im Kennungsblock, direkt unter `Beleg-ID:`, in
42
+ * der Spaltenform von `Datum:` (nicht fett, Wert rechtsbuendig):
43
+ *
44
+ * ```
45
+ * Beleg-ID: AT0-KASSE1-42
46
+ * Duplikat am: 24.10.2026 14:10:05
47
+ * ```
48
+ *
49
+ * `printedAt` ist ein Zeitpunkt; gedruckt wird er in Wiener Zeit
50
+ * (Sommerzeit nach EU-Regel), nie in der Zeitzone des Rechners. Ohne
51
+ * Spaltenzeile `Beleg-ID:` (Schicht-Bons) steht die Zeile ganz oben. Alles
52
+ * andere bleibt Zeile fuer Zeile wie beim Erstdruck.
53
+ *
54
+ * Reine Funktion: die Eingabe bleibt unangetastet, das Ergebnis ist eine
55
+ * eigene Kopie. Traegt das Layout schon eine Zeile `Duplikat am:`, bekommt
56
+ * nur sie die neue Zeit (der letzte Nachdruck gilt); es bleibt bei einer
57
+ * Zeile. Ein unbrauchbarer Zeitpunkt wirft `KasseneckValidationError`
58
+ * (`scope: 'request'`).
59
+ */
60
+ function markAsDuplicate(layout, printedAt) {
61
+ if (!(printedAt instanceof Date) || Number.isNaN(printedAt.getTime())) {
62
+ throw new errors_js_1.KasseneckValidationError('markAsDuplicate', 'printedAt: kein gueltiger Zeitpunkt (Date)', 'request');
63
+ }
64
+ const neu = {
65
+ kind: 'columns',
66
+ columns: [
67
+ { text: DUPLIKAT_AM, width: LINKS, align: 'left' },
68
+ { text: wienerZeit(printedAt), width: RECHTS, align: 'right' },
69
+ ],
70
+ };
71
+ const vorhanden = layout.lines.findIndex((z) => istZeile(z, DUPLIKAT_AM));
72
+ const lines = layout.lines.filter((z) => !istZeile(z, DUPLIKAT_AM)).map(kopie);
73
+ const stelle = vorhanden >= 0 ? vorhanden : lines.findIndex((z) => istZeile(z, 'Beleg-ID:')) + 1;
74
+ lines.splice(stelle, 0, neu);
75
+ return { ...layout, lines };
76
+ }
@@ -89,6 +89,8 @@ type TopfName = 'amountRateStandard' | 'amountRateReduced1' | 'amountRateReduced
89
89
  export declare function topfFuerSatz(vat: number): TopfName;
90
90
  /** Position, die ein Gutschein decken darf: weder Trinkgeld noch Gutscheinzeile. */
91
91
  export declare function istDeckbar(p: Innen): boolean;
92
+ /** Summe der Trinkgeldzeilen (Personal und Inhaber) in Cent, wie `centSumme(kunde.filter(istTip))` im Backend. */
93
+ export declare function trinkgeldCents(kunde: readonly Innen[]): number;
92
94
  /** Wie beleg-toepfe: Euro in Positionsreihenfolge aufsummieren, erst die Summe auf Cent runden. */
93
95
  export declare function centSumme(liste: readonly Innen[]): number;
94
96
  /** Die Saetze, auf die `kuTeile` verteilt: je Satz `centSumme` der deckbaren Positionen, nur positive. */
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VOUCHER_ZERO_RATE_BUCKET_FROM = void 0;
4
4
  exports.topfFuerSatz = topfFuerSatz;
5
5
  exports.istDeckbar = istDeckbar;
6
+ exports.trinkgeldCents = trinkgeldCents;
6
7
  exports.centSumme = centSumme;
7
8
  exports.kuSaetze = kuSaetze;
8
9
  exports.planeGutscheine = planeGutscheine;
@@ -37,6 +38,10 @@ function istGutscheinZeile(p) {
37
38
  function istDeckbar(p) {
38
39
  return p.tip == null && p.kind !== 'tip' && !istGutscheinZeile(p);
39
40
  }
41
+ /** Summe der Trinkgeldzeilen (Personal und Inhaber) in Cent, wie `centSumme(kunde.filter(istTip))` im Backend. */
42
+ function trinkgeldCents(kunde) {
43
+ return centSumme(kunde.filter((p) => p.tip != null || p.kind === 'tip'));
44
+ }
40
45
  /** Wie beleg-toepfe: Euro in Positionsreihenfolge aufsummieren, erst die Summe auf Cent runden. */
41
46
  function centSumme(liste) {
42
47
  return Math.round(liste.reduce((s, it) => s + it.priceOne * it.amount, 0) * 100);
@@ -1,4 +1,5 @@
1
1
  export { type LayoutAlign, type LayoutColumn, type LayoutTextLine, type LayoutColumnsLine, type LayoutRuleLine, type LayoutSpaceLine, type LayoutQrLine, type LayoutLine, type ReceiptLayout, type BuildReceiptLayoutOptions, buildReceiptLayout, receiptSignatureFailed, receiptSignatureIsTest, receiptIsZero, receiptAmountsAreZero, receiptIsSmallBusinessConsistent, receiptZdaText, CURRENT_LAYOUT_RULESET, type LayoutBannerLine, type LayoutBannerTone, type LayoutRuleset, SMALL_BUSINESS_NOTICE, formatCents, } from './layout.js';
2
+ export { markAsDuplicate } from './duplikat.js';
2
3
  export { type EscPosLayoutOptions, type EscPosLayoutResult, type QrPrintMode, type PrintLogo, assertLogoRaster, escPosLayoutBytes, escPosLayoutResult, } from './layout-escpos.js';
3
4
  export { type GridLine, type GridLineKind, type ReceiptGrid, type RenderReceiptGridOptions, renderReceiptGrid, gridColumnWidths, gridToText, CHARS_PER_PAPER_SIZE, } from './grid.js';
4
5
  export { type EposPrintXmlOptions, type EposPrintResult, type EposDirectOptions, type EposResponse, EposConnectionError, eposPrintXml, eposPrintXmlResult, eposXmlEscape, eposImageXml, eposServiceUrl, eposSoapEnvelope, eposParseResponse, eposDirectPrint, eposDirectStatus } from './epos.js';
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isReceiptDueError = exports.RECEIPT_DUE_ERROR_REASONS = exports.ReceiptDueError = exports.receiptDueBreakdown = exports.receiptDueCents = exports.codeTableReferenceImage = exports.codeTableTestSheetBytes = exports.codeTableTestSheet = exports.CODE_TABLE_TEST_SHEET_CHARS = exports.brandMarkImage = exports.BRAND_MARK_PATHS = exports.BRAND_MARK_RASTERS = exports.rasterizeLogo = exports.receiptSheet = exports.qrSheetWidthFraction = exports.logoRasterSize = exports.isLogoPixelSizeAllowed = exports.logoDimensions = exports.paperSizeForChars = exports.DOTS_PER_LINE = exports.DOTS_PER_CHAR = exports.LOGO_MAX_PIXELS = exports.SHEET_LOGO_SIZES = exports.eposDirectStatus = exports.eposDirectPrint = exports.eposParseResponse = exports.eposSoapEnvelope = exports.eposServiceUrl = exports.eposImageXml = exports.eposXmlEscape = exports.eposPrintXmlResult = exports.eposPrintXml = exports.EposConnectionError = exports.CHARS_PER_PAPER_SIZE = exports.gridToText = exports.gridColumnWidths = exports.renderReceiptGrid = exports.escPosLayoutResult = exports.escPosLayoutBytes = exports.assertLogoRaster = exports.formatCents = exports.SMALL_BUSINESS_NOTICE = exports.CURRENT_LAYOUT_RULESET = exports.receiptZdaText = exports.receiptIsSmallBusinessConsistent = exports.receiptAmountsAreZero = exports.receiptIsZero = exports.receiptSignatureIsTest = exports.receiptSignatureFailed = exports.buildReceiptLayout = void 0;
4
- exports.VOUCHER_ZERO_RATE_BUCKET_FROM = exports.voucherRedeemMaxCents = void 0;
3
+ exports.RECEIPT_DUE_ERROR_REASONS = exports.ReceiptDueError = exports.receiptDueBreakdown = exports.receiptDueCents = exports.codeTableReferenceImage = exports.codeTableTestSheetBytes = exports.codeTableTestSheet = exports.CODE_TABLE_TEST_SHEET_CHARS = exports.brandMarkImage = exports.BRAND_MARK_PATHS = exports.BRAND_MARK_RASTERS = exports.rasterizeLogo = exports.receiptSheet = exports.qrSheetWidthFraction = exports.logoRasterSize = exports.isLogoPixelSizeAllowed = exports.logoDimensions = exports.paperSizeForChars = exports.DOTS_PER_LINE = exports.DOTS_PER_CHAR = exports.LOGO_MAX_PIXELS = exports.SHEET_LOGO_SIZES = exports.eposDirectStatus = exports.eposDirectPrint = exports.eposParseResponse = exports.eposSoapEnvelope = exports.eposServiceUrl = exports.eposImageXml = exports.eposXmlEscape = exports.eposPrintXmlResult = exports.eposPrintXml = exports.EposConnectionError = exports.CHARS_PER_PAPER_SIZE = exports.gridToText = exports.gridColumnWidths = exports.renderReceiptGrid = exports.escPosLayoutResult = exports.escPosLayoutBytes = exports.assertLogoRaster = exports.markAsDuplicate = exports.formatCents = exports.SMALL_BUSINESS_NOTICE = exports.CURRENT_LAYOUT_RULESET = exports.receiptZdaText = exports.receiptIsSmallBusinessConsistent = exports.receiptAmountsAreZero = exports.receiptIsZero = exports.receiptSignatureIsTest = exports.receiptSignatureFailed = exports.buildReceiptLayout = void 0;
4
+ exports.VOUCHER_ZERO_RATE_BUCKET_FROM = exports.voucherRedeemMaxCents = exports.isReceiptDueError = void 0;
5
5
  var layout_js_1 = require("./layout.js");
6
6
  Object.defineProperty(exports, "buildReceiptLayout", { enumerable: true, get: function () { return layout_js_1.buildReceiptLayout; } });
7
7
  Object.defineProperty(exports, "receiptSignatureFailed", { enumerable: true, get: function () { return layout_js_1.receiptSignatureFailed; } });
@@ -13,6 +13,8 @@ Object.defineProperty(exports, "receiptZdaText", { enumerable: true, get: functi
13
13
  Object.defineProperty(exports, "CURRENT_LAYOUT_RULESET", { enumerable: true, get: function () { return layout_js_1.CURRENT_LAYOUT_RULESET; } });
14
14
  Object.defineProperty(exports, "SMALL_BUSINESS_NOTICE", { enumerable: true, get: function () { return layout_js_1.SMALL_BUSINESS_NOTICE; } });
15
15
  Object.defineProperty(exports, "formatCents", { enumerable: true, get: function () { return layout_js_1.formatCents; } });
16
+ var duplikat_js_1 = require("./duplikat.js");
17
+ Object.defineProperty(exports, "markAsDuplicate", { enumerable: true, get: function () { return duplikat_js_1.markAsDuplicate; } });
16
18
  var layout_escpos_js_1 = require("./layout-escpos.js");
17
19
  Object.defineProperty(exports, "assertLogoRaster", { enumerable: true, get: function () { return layout_escpos_js_1.assertLogoRaster; } });
18
20
  Object.defineProperty(exports, "escPosLayoutBytes", { enumerable: true, get: function () { return layout_escpos_js_1.escPosLayoutBytes; } });