@kreiseck/kasseneck-api 0.13.2 → 0.15.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 (195) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/README.md +96 -5
  3. package/dist/cjs/client/aufrufe.d.ts +1 -1
  4. package/dist/cjs/client/aufrufe.js +11 -0
  5. package/dist/cjs/client/receipts.d.ts +7 -0
  6. package/dist/cjs/client/receipts.js +1 -0
  7. package/dist/cjs/kasse/drucker.d.ts +5 -0
  8. package/dist/cjs/kasse/drucker.js +9 -0
  9. package/dist/cjs/kasse/settings.js +5 -2
  10. package/dist/cjs/printing/escpos.d.ts +38 -4
  11. package/dist/cjs/printing/escpos.js +87 -15
  12. package/dist/cjs/printing/index.d.ts +2 -2
  13. package/dist/cjs/printing/index.js +5 -1
  14. package/dist/cjs/printing/qr-groesse.d.ts +26 -21
  15. package/dist/cjs/printing/qr-groesse.js +22 -8
  16. package/dist/cjs/react/index.d.ts +53 -0
  17. package/dist/cjs/react/index.js +81 -0
  18. package/dist/cjs/receipt/bild.d.ts +14 -0
  19. package/dist/cjs/receipt/bild.js +65 -0
  20. package/dist/cjs/receipt/blatt.d.ts +107 -0
  21. package/dist/cjs/receipt/blatt.js +137 -0
  22. package/dist/cjs/receipt/epos.d.ts +19 -8
  23. package/dist/cjs/receipt/epos.js +39 -20
  24. package/dist/cjs/receipt/grid.d.ts +1 -1
  25. package/dist/cjs/receipt/grid.js +9 -1
  26. package/dist/cjs/receipt/index.d.ts +4 -2
  27. package/dist/cjs/receipt/index.js +17 -1
  28. package/dist/cjs/receipt/layout-escpos.d.ts +31 -3
  29. package/dist/cjs/receipt/layout-escpos.js +58 -18
  30. package/dist/cjs/rechnung/api.d.ts +43 -0
  31. package/dist/cjs/rechnung/api.js +35 -0
  32. package/dist/cjs/rechnung/auth.d.ts +21 -0
  33. package/dist/cjs/rechnung/auth.js +36 -0
  34. package/dist/cjs/rechnung/endpunkte.d.ts +48 -0
  35. package/dist/cjs/rechnung/endpunkte.js +129 -0
  36. package/dist/cjs/rechnung/fehler.d.ts +21 -0
  37. package/dist/cjs/rechnung/fehler.js +44 -0
  38. package/dist/cjs/rechnung/index.d.ts +18 -0
  39. package/dist/cjs/rechnung/index.js +52 -0
  40. package/dist/cjs/rechnung/typen.d.ts +224 -0
  41. package/dist/cjs/rechnung/typen.js +9 -0
  42. package/dist/cjs/rechnung/vertrag.d.ts +98 -0
  43. package/dist/cjs/rechnung/vertrag.js +191 -0
  44. package/dist/esm/client/aufrufe.d.ts +1 -1
  45. package/dist/esm/client/aufrufe.js +11 -0
  46. package/dist/esm/client/receipts.d.ts +7 -0
  47. package/dist/esm/client/receipts.js +1 -0
  48. package/dist/esm/kasse/drucker.d.ts +5 -0
  49. package/dist/esm/kasse/drucker.js +9 -0
  50. package/dist/esm/kasse/settings.js +5 -2
  51. package/dist/esm/printing/escpos.d.ts +38 -4
  52. package/dist/esm/printing/escpos.js +84 -15
  53. package/dist/esm/printing/index.d.ts +2 -2
  54. package/dist/esm/printing/index.js +2 -2
  55. package/dist/esm/printing/qr-groesse.d.ts +26 -21
  56. package/dist/esm/printing/qr-groesse.js +21 -8
  57. package/dist/esm/react/index.d.ts +53 -0
  58. package/dist/esm/react/index.js +80 -1
  59. package/dist/esm/receipt/bild.d.ts +14 -0
  60. package/dist/esm/receipt/bild.js +62 -0
  61. package/dist/esm/receipt/blatt.d.ts +107 -0
  62. package/dist/esm/receipt/blatt.js +128 -0
  63. package/dist/esm/receipt/epos.d.ts +19 -8
  64. package/dist/esm/receipt/epos.js +40 -22
  65. package/dist/esm/receipt/grid.d.ts +1 -1
  66. package/dist/esm/receipt/grid.js +9 -1
  67. package/dist/esm/receipt/index.d.ts +4 -2
  68. package/dist/esm/receipt/index.js +4 -2
  69. package/dist/esm/receipt/layout-escpos.d.ts +31 -3
  70. package/dist/esm/receipt/layout-escpos.js +58 -20
  71. package/dist/esm/rechnung/api.d.ts +43 -0
  72. package/dist/esm/rechnung/api.js +32 -0
  73. package/dist/esm/rechnung/auth.d.ts +21 -0
  74. package/dist/esm/rechnung/auth.js +33 -0
  75. package/dist/esm/rechnung/endpunkte.d.ts +48 -0
  76. package/dist/esm/rechnung/endpunkte.js +116 -0
  77. package/dist/esm/rechnung/fehler.d.ts +21 -0
  78. package/dist/esm/rechnung/fehler.js +39 -0
  79. package/dist/esm/rechnung/index.d.ts +18 -0
  80. package/dist/esm/rechnung/index.js +17 -0
  81. package/dist/esm/rechnung/typen.d.ts +224 -0
  82. package/dist/esm/rechnung/typen.js +8 -0
  83. package/dist/esm/rechnung/vertrag.d.ts +98 -0
  84. package/dist/esm/rechnung/vertrag.js +188 -0
  85. package/fixtures/erwartet/karte-eigener.blatt32.json +159 -0
  86. package/fixtures/erwartet/karte-eigener.blatt48.json +159 -0
  87. package/fixtures/erwartet/karte-gptom-ios.blatt32.json +231 -0
  88. package/fixtures/erwartet/karte-gptom-ios.blatt48.json +231 -0
  89. package/fixtures/erwartet/karte-gptom.blatt32.json +231 -0
  90. package/fixtures/erwartet/karte-gptom.blatt48.json +231 -0
  91. package/fixtures/erwartet/karte-hobex-cloud.blatt32.json +201 -0
  92. package/fixtures/erwartet/karte-hobex-cloud.blatt48.json +201 -0
  93. package/fixtures/erwartet/karte-hobex-hps.blatt32.json +225 -0
  94. package/fixtures/erwartet/karte-hobex-hps.blatt48.json +225 -0
  95. package/fixtures/erwartet/karte-mypos.blatt32.json +255 -0
  96. package/fixtures/erwartet/karte-mypos.blatt48.json +243 -0
  97. package/fixtures/erwartet/karte-stripe-eps.blatt32.json +195 -0
  98. package/fixtures/erwartet/karte-stripe-eps.blatt48.json +195 -0
  99. package/fixtures/erwartet/karte-stripe.blatt32.json +213 -0
  100. package/fixtures/erwartet/karte-stripe.blatt48.json +213 -0
  101. package/fixtures/erwartet/karte-sumup.blatt32.json +219 -0
  102. package/fixtures/erwartet/karte-sumup.blatt48.json +207 -0
  103. package/fixtures/erwartet/langer-artikelname.blatt32.json +177 -0
  104. package/fixtures/erwartet/langer-artikelname.blatt48.json +171 -0
  105. package/fixtures/erwartet/logo-probe-hoch.raster32.txt +120 -0
  106. package/fixtures/erwartet/logo-probe.raster32.txt +54 -0
  107. package/fixtures/erwartet/null-ausfall.blatt32.json +207 -0
  108. package/fixtures/erwartet/null-ausfall.blatt48.json +189 -0
  109. package/fixtures/erwartet/null-ausfall.grid32.txt +2 -0
  110. package/fixtures/erwartet/null-ausfall.grid48.txt +2 -0
  111. package/fixtures/erwartet/null-jahr.blatt32.json +213 -0
  112. package/fixtures/erwartet/null-jahr.blatt48.json +189 -0
  113. package/fixtures/erwartet/null-jahr.grid32.txt +2 -0
  114. package/fixtures/erwartet/null-jahr.grid48.txt +2 -0
  115. package/fixtures/erwartet/null-monat.blatt32.json +207 -0
  116. package/fixtures/erwartet/null-monat.blatt48.json +189 -0
  117. package/fixtures/erwartet/null-monat.grid32.txt +2 -0
  118. package/fixtures/erwartet/null-monat.grid48.txt +2 -0
  119. package/fixtures/erwartet/null-pruef.blatt32.json +207 -0
  120. package/fixtures/erwartet/null-pruef.blatt48.json +189 -0
  121. package/fixtures/erwartet/null-pruef.grid32.txt +2 -0
  122. package/fixtures/erwartet/null-pruef.grid48.txt +2 -0
  123. package/fixtures/erwartet/null-schluss.blatt32.json +207 -0
  124. package/fixtures/erwartet/null-schluss.blatt48.json +189 -0
  125. package/fixtures/erwartet/null-schluss.grid32.txt +2 -0
  126. package/fixtures/erwartet/null-schluss.grid48.txt +2 -0
  127. package/fixtures/erwartet/null-start.blatt32.json +207 -0
  128. package/fixtures/erwartet/null-start.blatt48.json +189 -0
  129. package/fixtures/erwartet/null-start.grid32.txt +2 -0
  130. package/fixtures/erwartet/null-start.grid48.txt +2 -0
  131. package/fixtures/erwartet/rabatt-chef-trinkgeld.blatt32.json +213 -0
  132. package/fixtures/erwartet/rabatt-chef-trinkgeld.blatt48.json +207 -0
  133. package/fixtures/erwartet/rabatt-einfach.blatt32.json +183 -0
  134. package/fixtures/erwartet/rabatt-einfach.blatt48.json +177 -0
  135. package/fixtures/erwartet/rabatt-trinkgeld.blatt32.json +213 -0
  136. package/fixtures/erwartet/rabatt-trinkgeld.blatt48.json +207 -0
  137. package/fixtures/erwartet/rabatt-wertgutschein.blatt32.json +219 -0
  138. package/fixtures/erwartet/rabatt-wertgutschein.blatt48.json +213 -0
  139. package/fixtures/erwartet/rabattzeilen.blatt32.json +201 -0
  140. package/fixtures/erwartet/rabattzeilen.blatt48.json +195 -0
  141. package/fixtures/erwartet/signaturausfall-verkauf.blatt32.json +195 -0
  142. package/fixtures/erwartet/signaturausfall-verkauf.blatt48.json +183 -0
  143. package/fixtures/erwartet/storno-rabatt.blatt32.json +249 -0
  144. package/fixtures/erwartet/storno-rabatt.blatt48.json +237 -0
  145. package/fixtures/erwartet/storno-rabatt.grid32.txt +2 -0
  146. package/fixtures/erwartet/storno-rabatt.grid48.txt +2 -0
  147. package/fixtures/erwartet/storno-teil.blatt32.json +207 -0
  148. package/fixtures/erwartet/storno-teil.blatt48.json +201 -0
  149. package/fixtures/erwartet/storno-teil.grid32.txt +2 -0
  150. package/fixtures/erwartet/storno-teil.grid48.txt +2 -0
  151. package/fixtures/erwartet/storno-voll.blatt32.json +219 -0
  152. package/fixtures/erwartet/storno-voll.blatt48.json +213 -0
  153. package/fixtures/erwartet/storno-voll.grid32.txt +2 -0
  154. package/fixtures/erwartet/storno-voll.grid48.txt +2 -0
  155. package/fixtures/erwartet/testkasse-verkauf.blatt32.json +225 -0
  156. package/fixtures/erwartet/testkasse-verkauf.blatt48.json +219 -0
  157. package/fixtures/erwartet/testkasse-verkauf.grid32.txt +5 -1
  158. package/fixtures/erwartet/testkasse-verkauf.grid48.txt +5 -1
  159. package/fixtures/erwartet/testsignatur-verkauf.blatt32.json +237 -0
  160. package/fixtures/erwartet/testsignatur-verkauf.blatt48.json +219 -0
  161. package/fixtures/erwartet/testsignatur-verkauf.grid32.txt +5 -1
  162. package/fixtures/erwartet/testsignatur-verkauf.grid48.txt +5 -1
  163. package/fixtures/erwartet/training.blatt32.json +237 -0
  164. package/fixtures/erwartet/training.blatt48.json +219 -0
  165. package/fixtures/erwartet/training.grid32.txt +2 -0
  166. package/fixtures/erwartet/training.grid48.txt +2 -0
  167. package/fixtures/erwartet/verkauf-bar.blatt32.json +177 -0
  168. package/fixtures/erwartet/verkauf-bar.blatt48.json +171 -0
  169. package/fixtures/erwartet/verkauf-karte.blatt32.json +177 -0
  170. package/fixtures/erwartet/verkauf-karte.blatt48.json +171 -0
  171. package/fixtures/erwartet/verkauf-kleinunternehmer.blatt32.json +183 -0
  172. package/fixtures/erwartet/verkauf-kleinunternehmer.blatt48.json +177 -0
  173. package/fixtures/hobex-hps-codes.json +1 -1
  174. package/fixtures/kasse-settings-standard.json +1 -1
  175. package/fixtures/kasse-texte.json +1 -1
  176. package/fixtures/manifest.json +109 -43
  177. package/fixtures/oberflaeche.json +87 -1
  178. package/fixtures/rechnung-api-beispiele/credit-fehler-grund.json +24 -0
  179. package/fixtures/rechnung-api-beispiele/credit-ok.json +20 -0
  180. package/fixtures/rechnung-api-beispiele/customer-fehler-uid.json +25 -0
  181. package/fixtures/rechnung-api-beispiele/customer-get-fehler-beide.json +15 -0
  182. package/fixtures/rechnung-api-beispiele/customer-ok.json +20 -0
  183. package/fixtures/rechnung-api-beispiele/customer-search-fehler-leer.json +14 -0
  184. package/fixtures/rechnung-api-beispiele/issue-brutto-20.json +27 -0
  185. package/fixtures/rechnung-api-beispiele/issue-fehler-cent.json +26 -0
  186. package/fixtures/rechnung-api-beispiele/issue-fehler-menge.json +26 -0
  187. package/fixtures/rechnung-api-beispiele/issue-fehler-negativ.json +26 -0
  188. package/fixtures/rechnung-api-beispiele/issue-fehler-satz.json +26 -0
  189. package/fixtures/rechnung-api-beispiele/issue-fehler-unbekannt.json +27 -0
  190. package/fixtures/rechnung-api-beispiele/issue-gemischt.json +33 -0
  191. package/fixtures/rechnung-api-beispiele/issue-kleinunternehmer.json +27 -0
  192. package/fixtures/rechnung-api-beispiele/issue-netto-20.json +28 -0
  193. package/fixtures/rechnung-api-beispiele/issue-rabatt.json +28 -0
  194. package/fixtures/rechnung-api.schema.json +672 -0
  195. package/package.json +12 -1
@@ -1,11 +1,12 @@
1
1
  import type { ReceiptLayout } from './layout.js';
2
2
  import type { PosPaperSize } from '../printing/escpos.js';
3
- import { type QrModulGroesse } from '../printing/index.js';
3
+ import { type QrModulGroesse, type RasterBild } from '../printing/index.js';
4
+ import { type DruckLogo } from './layout-escpos.js';
4
5
  /**
5
6
  * ePOS-Print XML (Epson TM-Drucker: Server Direct Print, ePOS-Print ueber
6
7
  * HTTP) -- **aus dem Zeichenraster**: jede Rasterzeile wird eine <text>-Zeile
7
- * mit exakt N Zeichen und Zeilenumbruch, Aufdrucke doppelt hoch (Warnungen
8
- * invers), QR als <symbol>, Leerraum als <feed>, am Ende Schnitt. Kein
8
+ * mit exakt N Zeichen und Zeilenumbruch, Aufdrucke als Rahmen aus
9
+ * Rasterzeilen, QR als <symbol>, Leerraum als <feed>, am Ende Schnitt. Kein
9
10
  * eigenes Setzen -- was Bildschirm, ESC/POS und PDF zeigen, druckt der Epson
10
11
  * Zeile fuer Zeile genauso.
11
12
  *
@@ -22,16 +23,20 @@ export interface EposPrintXmlOptions {
22
23
  */
23
24
  qrBreite?: number;
24
25
  /**
25
- * Deckel fuer die gerechnete QR-Modulgroesse; Vorgabe `mittel`.
26
+ * Deckel fuer die gerechnete QR-Modulgroesse; Vorgabe `auto` (hoechstens 6
27
+ * Punkte je Modul) -- wie ESC/POS, Blatt und der Flutter-Zwilling.
26
28
  *
27
- * Warum `mittel` und nicht `auto`: `auto` deckelt beim Bestandswert des
28
- * **ESC/POS**-Befehls dieses Pakets (4), dieser Weg druckt aber seit jeher
29
- * mit 6. Die Vorgabe nennt den Bestandswert dieses Wegs also ausdruecklich,
30
- * damit ohne Wahl kein Byte anders herauskommt.
29
+ * Bis 0.13 stand hier `mittel`, weil `auto` damals beim ESC/POS-Wert 4
30
+ * deckelte und dieser Weg seit jeher mit 6 druckt. Seit `auto` ueberall 6
31
+ * heisst, ist das derselbe Wert: ohne Wahl kommt kein Byte anders heraus.
31
32
  */
32
33
  qrGroesse?: QrModulGroesse;
33
34
  /** Papierschnitt am Ende, Vorgabe true. */
34
35
  cut?: boolean;
36
+ /** Firmenlogo; ohne Angabe kein Logo. */
37
+ logo?: DruckLogo | null;
38
+ /** "erstellt mit Kasseneck" am Ende. */
39
+ marke?: boolean;
35
40
  }
36
41
  /**
37
42
  * Das XML **samt** dem, was dem QR unterwegs zugestossen ist -- dieselbe
@@ -45,6 +50,8 @@ export interface EposPrintErgebnis {
45
50
  qrAusweich: string | null;
46
51
  }
47
52
  export declare function eposXmlEscape(text: string): string;
53
+ /** Ein Rasterbild als ePOS-`<image>` (einfarbig, Punktmass, Rasterzeilen Base64). */
54
+ export declare function eposBildXml(bild: RasterBild): string;
48
55
  /** Nur das XML; wer die QR-Meldungen braucht, nimmt [eposPrintXmlErgebnis]. */
49
56
  export declare function eposPrintXml(layout: ReceiptLayout, options?: EposPrintXmlOptions): string;
50
57
  /**
@@ -77,6 +84,10 @@ export interface EposDirectOptions {
77
84
  qrBreite?: number;
78
85
  /** Deckel fuer die gerechnete QR-Modulgroesse; siehe [EposPrintXmlOptions.qrGroesse]. */
79
86
  qrGroesse?: QrModulGroesse;
87
+ /** Firmenlogo; ohne Angabe kein Logo. */
88
+ logo?: DruckLogo | null;
89
+ /** "erstellt mit Kasseneck" am Ende. */
90
+ marke?: boolean;
80
91
  timeoutMs?: number;
81
92
  }
82
93
  export interface EposResponse {
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EposConnectionError = void 0;
4
4
  exports.eposXmlEscape = eposXmlEscape;
5
+ exports.eposBildXml = eposBildXml;
5
6
  exports.eposPrintXml = eposPrintXml;
6
7
  exports.eposPrintXmlErgebnis = eposPrintXmlErgebnis;
7
8
  exports.eposServiceUrl = eposServiceUrl;
@@ -11,9 +12,14 @@ exports.eposDirectPrint = eposDirectPrint;
11
12
  exports.eposDirectStatus = eposDirectStatus;
12
13
  const index_js_1 = require("../printing/index.js");
13
14
  const grid_js_1 = require("./grid.js");
15
+ const layout_escpos_js_1 = require("./layout-escpos.js");
14
16
  function eposXmlEscape(text) {
15
17
  return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&apos;');
16
18
  }
19
+ /** Ein Rasterbild als ePOS-`<image>` (einfarbig, Punktmass, Rasterzeilen Base64). */
20
+ function eposBildXml(bild) {
21
+ return `<image width="${bild.breite}" height="${bild.hoehe}" color="color_1" mode="mono">${(0, index_js_1.rasterZeilenBase64)(bild)}</image>`;
22
+ }
17
23
  const NS = 'http://www.epson-pos.com/schemas/2011/03/epos-print';
18
24
  /** Nur das XML; wer die QR-Meldungen braucht, nimmt [eposPrintXmlErgebnis]. */
19
25
  function eposPrintXml(layout, options = {}) {
@@ -30,8 +36,9 @@ function eposPrintXml(layout, options = {}) {
30
36
  * laesst es weg; genau daran fehlte am echten Beleg der QR.
31
37
  */
32
38
  function eposPrintXmlErgebnis(layout, options = {}) {
33
- const grid = (0, grid_js_1.renderReceiptGrid)(layout, { zeichen: options.zeichen ?? grid_js_1.ZEICHEN_JE_PAPIER[layout.paperSize] });
34
- const deckel = options.qrGroesse ?? 'mittel';
39
+ const zeichen = options.zeichen ?? grid_js_1.ZEICHEN_JE_PAPIER[layout.paperSize];
40
+ const deckel = options.qrGroesse ?? 'auto';
41
+ const blatt = (0, layout_escpos_js_1.blattFuerDruck)(layout, { zeichen, logo: options.logo, marke: options.marke, qrGroesse: deckel });
35
42
  const fest = options.qrBreite === undefined
36
43
  ? null
37
44
  : Math.min(16, Math.max(3, Math.floor(options.qrBreite)));
@@ -50,6 +57,12 @@ function eposPrintXmlErgebnis(layout, options = {}) {
50
57
  return fest;
51
58
  if (nutzlast === '')
52
59
  return index_js_1.QR_MODUL_DECKEL[deckel];
60
+ // Passt der Inhalt in keine QR-Version, gibt es kein Symbol, das der
61
+ // Drucker setzen koennte -- wie beim Blatt (Anteil 0) geht der Beleg ohne QR.
62
+ if (!(0, index_js_1.qrPasstInVersion)(nutzlast)) {
63
+ qrFehler = 'QR-Inhalt passt in keine QR-Version -- Beleg ohne QR';
64
+ return null;
65
+ }
53
66
  const mass = (0, index_js_1.qrGroesseFuer)({
54
67
  nutzlast,
55
68
  papierbreitePunkte: index_js_1.QR_DRUCK_PUNKTE[layout.paperSize],
@@ -74,32 +87,34 @@ function eposPrintXmlErgebnis(layout, options = {}) {
74
87
  out.push('<text font="font_a"/>');
75
88
  out.push('<text align="left"/>');
76
89
  out.push('<text width="1" height="1" reverse="false" em="false"/>');
77
- for (const z of grid.lines) {
78
- switch (z.kind) {
79
- case 'space':
80
- out.push('<feed line="1"/>');
90
+ for (const block of blatt.bloecke) {
91
+ switch (block.art) {
92
+ case 'zeile':
93
+ if (block.leer)
94
+ out.push('<feed line="1"/>');
95
+ else if (block.fett) {
96
+ out.push(`<text em="true">${eposXmlEscape(block.text)}&#10;</text>`);
97
+ out.push('<text em="false"/>');
98
+ }
99
+ else
100
+ out.push(`<text>${eposXmlEscape(block.text)}&#10;</text>`);
101
+ break;
102
+ case 'logo':
103
+ if (options.logo) {
104
+ out.push('<text align="center"/>');
105
+ out.push(eposBildXml(options.logo.raster));
106
+ out.push('<text align="left"/>');
107
+ }
81
108
  break;
82
109
  case 'qr': {
83
- const breite = qrBreiteFuer(z.qr ?? '');
110
+ const breite = qrBreiteFuer(block.nutzlast);
84
111
  if (breite === null)
85
112
  break;
86
113
  out.push('<text align="center"/>');
87
- out.push(`<symbol type="qrcode_model_2" level="level_m" width="${breite}" height="0" size="0">${eposXmlEscape(z.qr ?? '')}</symbol>`);
114
+ out.push(`<symbol type="qrcode_model_2" level="level_m" width="${breite}" height="0" size="0">${eposXmlEscape(block.nutzlast)}</symbol>`);
88
115
  out.push('<text align="left"/>');
89
116
  break;
90
117
  }
91
- case 'banner':
92
- out.push(`<text width="1" height="2" reverse="${z.ton === 'warnung' ? 'true' : 'false'}" em="true">${eposXmlEscape(z.text)}&#10;</text>`);
93
- out.push('<text width="1" height="1" reverse="false" em="false"/>');
94
- break;
95
- default:
96
- if (z.bold)
97
- out.push(`<text em="true">${eposXmlEscape(z.text)}&#10;</text>`);
98
- else
99
- out.push(`<text>${eposXmlEscape(z.text)}&#10;</text>`);
100
- if (z.bold)
101
- out.push('<text em="false"/>');
102
- break;
103
118
  }
104
119
  }
105
120
  if (options.cut !== false) {
@@ -220,6 +235,10 @@ function eposDirectPrint(layout, o, fetchFn = fetch) {
220
235
  xmlOptionen.qrBreite = o.qrBreite;
221
236
  if (o.qrGroesse !== undefined)
222
237
  xmlOptionen.qrGroesse = o.qrGroesse;
238
+ if (o.logo)
239
+ xmlOptionen.logo = o.logo;
240
+ if (o.marke !== undefined)
241
+ xmlOptionen.marke = o.marke;
223
242
  return eposDirectSend(eposPrintXml({ ...layout, paperSize: papier }, xmlOptionen), o, fetchFn);
224
243
  }
225
244
  /** Verbindungstest: leeres Dokument, druckt nichts, liefert den Druckerstatus. */
@@ -27,7 +27,7 @@ export interface GridLine {
27
27
  text: string;
28
28
  kind: GridLineKind;
29
29
  bold: boolean;
30
- /** Bei `banner`: `warnung` = invers/auffaellig, `belegart` = Rahmen. */
30
+ /** Bei `banner` (Rahmen- und Textzeilen): `warnung` = Test/Ausfall, `belegart` = Storno, Nullbeleg … */
31
31
  ton?: 'belegart' | 'warnung';
32
32
  /** Bei `qr`: die Nutzlast. */
33
33
  qr?: string;
@@ -67,10 +67,18 @@ function renderReceiptGrid(layout, options = {}) {
67
67
  for (const t of (0, escpos_js_1.wortzeilenText)(z.text, zeichen))
68
68
  lines.push({ text: ausrichten(t, zeichen, z.align), kind: 'text', bold: z.bold });
69
69
  break;
70
- case 'banner':
70
+ case 'banner': {
71
+ // Der Rahmen ist Teil des Rasters: eine Zeile '=' ueber die volle Breite
72
+ // davor und danach. So setzt ihn jeder Weg -- Bildschirm, Bon, ePOS, PDF,
73
+ // myPOS -- Zeichen fuer Zeichen gleich. Vorher zeichnete jeder Weg seinen
74
+ // eigenen Rahmen (Rechteck, doppelt hoch, invers, gefuellt).
75
+ const rahmen = '='.repeat(zeichen);
76
+ lines.push({ text: rahmen, kind: 'banner', bold: true, ton: z.ton });
71
77
  for (const t of (0, escpos_js_1.wortzeilenText)(z.text, zeichen))
72
78
  lines.push({ text: ausrichten(t, zeichen, 'center'), kind: 'banner', bold: true, ton: z.ton });
79
+ lines.push({ text: rahmen, kind: 'banner', bold: true, ton: z.ton });
73
80
  break;
81
+ }
74
82
  case 'rule':
75
83
  lines.push({ text: (z.char || '-').charAt(0).repeat(zeichen), kind: 'rule', bold: false });
76
84
  break;
@@ -1,4 +1,6 @@
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, type Pruefangaben, AKTUELLES_REGELWERK, type LayoutBannerLine, type LayoutRegelwerk, SMALL_BUSINESS_NOTICE, formatCents, } from './layout.js';
2
- export { type EscPosLayoutOptions, type EscPosLayoutErgebnis, type QrPrintMode, escPosLayoutBytes, escPosLayoutErgebnis, } from './layout-escpos.js';
2
+ export { type EscPosLayoutOptions, type EscPosLayoutErgebnis, type QrPrintMode, type DruckLogo, pruefeLogoRaster, escPosLayoutBytes, escPosLayoutErgebnis, } from './layout-escpos.js';
3
3
  export { type GridLine, type GridLineKind, type ReceiptGrid, type RenderReceiptGridOptions, renderReceiptGrid, gridSpaltenBreiten, gridAlsText, ZEICHEN_JE_PAPIER, } from './grid.js';
4
- export { type EposPrintXmlOptions, type EposPrintErgebnis, type EposDirectOptions, type EposResponse, EposConnectionError, eposPrintXml, eposPrintXmlErgebnis, eposXmlEscape, eposServiceUrl, eposSoapEnvelope, eposParseResponse, eposDirectPrint, eposDirectStatus } from './epos.js';
4
+ export { type EposPrintXmlOptions, type EposPrintErgebnis, type EposDirectOptions, type EposResponse, EposConnectionError, eposPrintXml, eposPrintXmlErgebnis, eposXmlEscape, eposBildXml, eposServiceUrl, eposSoapEnvelope, eposParseResponse, eposDirectPrint, eposDirectStatus } from './epos.js';
5
+ export { type LogoStufe, type BlattLogo, type LogoMass, type BlattBlock, type BelegBlatt, type BelegBlattOptionen, LOGO_STUFEN, LOGO_PIXEL_MAX, PUNKTE_JE_ZEICHEN, PUNKTE_JE_ZEILE, MARKE_TEXT, papierFuerZeichen, logoMass, logoPixelZulaessig, logoRasterMass, qrBlattAnteil, belegBlatt, } from './blatt.js';
6
+ export { logoRaster } from './bild.js';
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.eposDirectStatus = exports.eposDirectPrint = exports.eposParseResponse = exports.eposSoapEnvelope = exports.eposServiceUrl = exports.eposXmlEscape = exports.eposPrintXmlErgebnis = exports.eposPrintXml = exports.EposConnectionError = exports.ZEICHEN_JE_PAPIER = exports.gridAlsText = exports.gridSpaltenBreiten = exports.renderReceiptGrid = exports.escPosLayoutErgebnis = exports.escPosLayoutBytes = exports.formatCents = exports.SMALL_BUSINESS_NOTICE = exports.AKTUELLES_REGELWERK = exports.receiptZdaText = exports.receiptIsSmallBusinessConsistent = exports.receiptAmountsAreZero = exports.receiptIsZero = exports.receiptSignatureIsTest = exports.receiptSignatureFailed = exports.buildReceiptLayout = void 0;
3
+ exports.logoRaster = exports.belegBlatt = exports.qrBlattAnteil = exports.logoRasterMass = exports.logoPixelZulaessig = exports.logoMass = exports.papierFuerZeichen = exports.MARKE_TEXT = exports.PUNKTE_JE_ZEILE = exports.PUNKTE_JE_ZEICHEN = exports.LOGO_PIXEL_MAX = exports.LOGO_STUFEN = exports.eposDirectStatus = exports.eposDirectPrint = exports.eposParseResponse = exports.eposSoapEnvelope = exports.eposServiceUrl = exports.eposBildXml = exports.eposXmlEscape = exports.eposPrintXmlErgebnis = exports.eposPrintXml = exports.EposConnectionError = exports.ZEICHEN_JE_PAPIER = exports.gridAlsText = exports.gridSpaltenBreiten = exports.renderReceiptGrid = exports.escPosLayoutErgebnis = exports.escPosLayoutBytes = exports.pruefeLogoRaster = exports.formatCents = exports.SMALL_BUSINESS_NOTICE = exports.AKTUELLES_REGELWERK = exports.receiptZdaText = exports.receiptIsSmallBusinessConsistent = exports.receiptAmountsAreZero = exports.receiptIsZero = exports.receiptSignatureIsTest = exports.receiptSignatureFailed = exports.buildReceiptLayout = void 0;
4
4
  var layout_js_1 = require("./layout.js");
5
5
  Object.defineProperty(exports, "buildReceiptLayout", { enumerable: true, get: function () { return layout_js_1.buildReceiptLayout; } });
6
6
  Object.defineProperty(exports, "receiptSignatureFailed", { enumerable: true, get: function () { return layout_js_1.receiptSignatureFailed; } });
@@ -13,6 +13,7 @@ Object.defineProperty(exports, "AKTUELLES_REGELWERK", { enumerable: true, get: f
13
13
  Object.defineProperty(exports, "SMALL_BUSINESS_NOTICE", { enumerable: true, get: function () { return layout_js_1.SMALL_BUSINESS_NOTICE; } });
14
14
  Object.defineProperty(exports, "formatCents", { enumerable: true, get: function () { return layout_js_1.formatCents; } });
15
15
  var layout_escpos_js_1 = require("./layout-escpos.js");
16
+ Object.defineProperty(exports, "pruefeLogoRaster", { enumerable: true, get: function () { return layout_escpos_js_1.pruefeLogoRaster; } });
16
17
  Object.defineProperty(exports, "escPosLayoutBytes", { enumerable: true, get: function () { return layout_escpos_js_1.escPosLayoutBytes; } });
17
18
  Object.defineProperty(exports, "escPosLayoutErgebnis", { enumerable: true, get: function () { return layout_escpos_js_1.escPosLayoutErgebnis; } });
18
19
  var grid_js_1 = require("./grid.js");
@@ -25,8 +26,23 @@ Object.defineProperty(exports, "EposConnectionError", { enumerable: true, get: f
25
26
  Object.defineProperty(exports, "eposPrintXml", { enumerable: true, get: function () { return epos_js_1.eposPrintXml; } });
26
27
  Object.defineProperty(exports, "eposPrintXmlErgebnis", { enumerable: true, get: function () { return epos_js_1.eposPrintXmlErgebnis; } });
27
28
  Object.defineProperty(exports, "eposXmlEscape", { enumerable: true, get: function () { return epos_js_1.eposXmlEscape; } });
29
+ Object.defineProperty(exports, "eposBildXml", { enumerable: true, get: function () { return epos_js_1.eposBildXml; } });
28
30
  Object.defineProperty(exports, "eposServiceUrl", { enumerable: true, get: function () { return epos_js_1.eposServiceUrl; } });
29
31
  Object.defineProperty(exports, "eposSoapEnvelope", { enumerable: true, get: function () { return epos_js_1.eposSoapEnvelope; } });
30
32
  Object.defineProperty(exports, "eposParseResponse", { enumerable: true, get: function () { return epos_js_1.eposParseResponse; } });
31
33
  Object.defineProperty(exports, "eposDirectPrint", { enumerable: true, get: function () { return epos_js_1.eposDirectPrint; } });
32
34
  Object.defineProperty(exports, "eposDirectStatus", { enumerable: true, get: function () { return epos_js_1.eposDirectStatus; } });
35
+ var blatt_js_1 = require("./blatt.js");
36
+ Object.defineProperty(exports, "LOGO_STUFEN", { enumerable: true, get: function () { return blatt_js_1.LOGO_STUFEN; } });
37
+ Object.defineProperty(exports, "LOGO_PIXEL_MAX", { enumerable: true, get: function () { return blatt_js_1.LOGO_PIXEL_MAX; } });
38
+ Object.defineProperty(exports, "PUNKTE_JE_ZEICHEN", { enumerable: true, get: function () { return blatt_js_1.PUNKTE_JE_ZEICHEN; } });
39
+ Object.defineProperty(exports, "PUNKTE_JE_ZEILE", { enumerable: true, get: function () { return blatt_js_1.PUNKTE_JE_ZEILE; } });
40
+ Object.defineProperty(exports, "MARKE_TEXT", { enumerable: true, get: function () { return blatt_js_1.MARKE_TEXT; } });
41
+ Object.defineProperty(exports, "papierFuerZeichen", { enumerable: true, get: function () { return blatt_js_1.papierFuerZeichen; } });
42
+ Object.defineProperty(exports, "logoMass", { enumerable: true, get: function () { return blatt_js_1.logoMass; } });
43
+ Object.defineProperty(exports, "logoPixelZulaessig", { enumerable: true, get: function () { return blatt_js_1.logoPixelZulaessig; } });
44
+ Object.defineProperty(exports, "logoRasterMass", { enumerable: true, get: function () { return blatt_js_1.logoRasterMass; } });
45
+ Object.defineProperty(exports, "qrBlattAnteil", { enumerable: true, get: function () { return blatt_js_1.qrBlattAnteil; } });
46
+ Object.defineProperty(exports, "belegBlatt", { enumerable: true, get: function () { return blatt_js_1.belegBlatt; } });
47
+ var bild_js_1 = require("./bild.js");
48
+ Object.defineProperty(exports, "logoRaster", { enumerable: true, get: function () { return bild_js_1.logoRaster; } });
@@ -1,5 +1,6 @@
1
- import { type PosCodeTable, type PosCutMode, type PosPaperSize, type QrCorrection, type QrMatrix, type QrModulGroesse, type QrSize } from '../printing/index.js';
1
+ import { type PosCodeTable, type PosCutMode, type PosPaperSize, type QrCorrection, type QrMatrix, type QrModulGroesse, type QrSize, type RasterBild } from '../printing/index.js';
2
2
  import type { ReceiptLayout } from './layout.js';
3
+ import { type BelegBlatt, type LogoStufe, type LogoMass } from './blatt.js';
3
4
  /**
4
5
  * Bruecke vom Layout-Modell zu ESC/POS-Bytes — der Bondrucker-Ausgabeweg.
5
6
  *
@@ -28,6 +29,29 @@ import type { ReceiptLayout } from './layout.js';
28
29
  * (`qrMatrix`), weil dieses Paket keine QR-Codes rechnet.
29
30
  */
30
31
  export type QrPrintMode = 'native' | 'nativeModel1' | 'imageRaster';
32
+ /** Firmenlogo fuer den Druck: Stufe, Pixelmass des Originals und das fertige Rasterbild (`logoRaster`). */
33
+ export interface DruckLogo {
34
+ stufe: LogoStufe;
35
+ pxBreite: number;
36
+ pxHoehe: number;
37
+ raster: RasterBild;
38
+ }
39
+ /** Das Rasterbild muss genau so gross sein, wie das Blatt das Logo setzt -- sonst stuende am Bon ein anderes Logo als am Schirm. */
40
+ export declare function pruefeLogoRaster(logo: DruckLogo, mass: LogoMass, zeichen: number): void;
41
+ /**
42
+ * Baut das Blatt fuer einen Druckweg (ESC/POS, ePOS) an EINER Stelle: die
43
+ * Zuordnung `DruckLogo` -> `BlattLogo` und die Groessenpruefung des mitgebrachten
44
+ * Rasterbilds teilen sich beide Wege -- ohne das muesste eine Aenderung daran an
45
+ * zwei Stellen nachgezogen werden. Wirft VOR jeder Ausgabe (also bevor der
46
+ * Aufrufer auch nur ein Byte/Zeichen geschrieben hat), wenn das Rasterbild nicht
47
+ * zur Logo-Stufe passt.
48
+ */
49
+ export declare function blattFuerDruck(layout: ReceiptLayout, optionen: {
50
+ zeichen: number;
51
+ logo?: DruckLogo | null;
52
+ marke?: boolean;
53
+ qrGroesse: QrModulGroesse;
54
+ }): BelegBlatt;
31
55
  export interface EscPosLayoutOptions {
32
56
  /** Papierbreite; Vorgabe ist die des Layouts (dessen Spaltenbreiten daran haengen). */
33
57
  paperSize?: PosPaperSize;
@@ -40,9 +64,9 @@ export interface EscPosLayoutOptions {
40
64
  * dann passt der Aufrufer selbst auf, dass das Symbol aufs Papier geht.
41
65
  */
42
66
  qrSize?: QrSize;
43
- /** Fehlerkorrekturstufe des QR-Codes. */
67
+ /** Fehlerkorrekturstufe des QR-Codes; Vorgabe `M` (wie ePOS, Bildweg und Blatt). */
44
68
  qrCorrection?: QrCorrection;
45
- /** Deckel fuer die gerechnete Modulgroesse; Vorgabe `auto`. */
69
+ /** Deckel fuer die gerechnete Modulgroesse; Vorgabe `auto` (hoechstens 6 Punkte je Modul). */
46
70
  qrGroesse?: QrModulGroesse;
47
71
  /** Druckweg des QR; Vorgabe `native` (der Bestandsweg). */
48
72
  qrModus?: QrPrintMode;
@@ -54,6 +78,10 @@ export interface EscPosLayoutOptions {
54
78
  * aus der QR-Bibliothek, die er ohnehin fuer den Bildschirm benutzt.
55
79
  */
56
80
  qrMatrix?: (nutzlast: string) => QrMatrix;
81
+ /** Firmenlogo; ohne Angabe kein Logo (Bestand). */
82
+ logo?: DruckLogo | null;
83
+ /** "erstellt mit Kasseneck" am Ende (Konto-Flag `kreiseck_logo`). */
84
+ marke?: boolean;
57
85
  }
58
86
  /**
59
87
  * Der Bytestrom **samt** dem, was dem QR unterwegs zugestossen ist.
@@ -1,9 +1,41 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pruefeLogoRaster = pruefeLogoRaster;
4
+ exports.blattFuerDruck = blattFuerDruck;
3
5
  exports.escPosLayoutBytes = escPosLayoutBytes;
4
6
  exports.escPosLayoutErgebnis = escPosLayoutErgebnis;
5
7
  const index_js_1 = require("../printing/index.js");
8
+ const blatt_js_1 = require("./blatt.js");
6
9
  const grid_js_1 = require("./grid.js");
10
+ /** Das Rasterbild muss genau so gross sein, wie das Blatt das Logo setzt -- sonst stuende am Bon ein anderes Logo als am Schirm. */
11
+ function pruefeLogoRaster(logo, mass, zeichen) {
12
+ const soll = (0, blatt_js_1.logoRasterMass)(mass, zeichen);
13
+ if (logo.raster.breite !== soll.breite || logo.raster.hoehe !== soll.hoehe) {
14
+ throw new Error(`Logo-Raster ${logo.raster.breite}x${logo.raster.hoehe} passt nicht zum Blatt (${soll.breite}x${soll.hoehe})`);
15
+ }
16
+ }
17
+ /**
18
+ * Baut das Blatt fuer einen Druckweg (ESC/POS, ePOS) an EINER Stelle: die
19
+ * Zuordnung `DruckLogo` -> `BlattLogo` und die Groessenpruefung des mitgebrachten
20
+ * Rasterbilds teilen sich beide Wege -- ohne das muesste eine Aenderung daran an
21
+ * zwei Stellen nachgezogen werden. Wirft VOR jeder Ausgabe (also bevor der
22
+ * Aufrufer auch nur ein Byte/Zeichen geschrieben hat), wenn das Rasterbild nicht
23
+ * zur Logo-Stufe passt.
24
+ */
25
+ function blattFuerDruck(layout, optionen) {
26
+ const blattOptionen = {
27
+ zeichen: optionen.zeichen,
28
+ marke: optionen.marke === true,
29
+ qrGroesse: optionen.qrGroesse,
30
+ };
31
+ if (optionen.logo)
32
+ blattOptionen.logo = { stufe: optionen.logo.stufe, pxBreite: optionen.logo.pxBreite, pxHoehe: optionen.logo.pxHoehe };
33
+ const blatt = (0, blatt_js_1.belegBlatt)(layout, blattOptionen);
34
+ const logoBlock = blatt.bloecke.find((b) => b.art === 'logo');
35
+ if (optionen.logo && logoBlock && logoBlock.art === 'logo')
36
+ pruefeLogoRaster(optionen.logo, logoBlock, blatt.zeichen);
37
+ return blatt;
38
+ }
7
39
  /**
8
40
  * Druckbar gemachtes Layout: Texte durch [escPosPrintableText] (Codepage,
9
41
  * "EUR" statt "€", Striche), damit das Raster mit den Zeichen rechnet, die
@@ -72,6 +104,13 @@ function escPosLayoutErgebnis(layout, options = {}) {
72
104
  * `qrFehler` aus `escPosQrCode`, und der Beleg geht ohne QR hinaus.
73
105
  */
74
106
  const qrZeile = (nutzlast) => {
107
+ // Ein Inhalt, der in keine QR-Version passt, laesst sich weder als Befehl
108
+ // noch als Bild drucken -- beide Wege wuerfen. Der Beleg geht ohne QR
109
+ // hinaus und sagt es ueber `qrFehler`, wie das Blatt (Anteil 0).
110
+ if (nutzlast !== '' && !(0, index_js_1.qrPasstInVersion)(nutzlast)) {
111
+ doc.qrFehler = 'QR-Inhalt passt in keine QR-Version -- Beleg ohne QR';
112
+ return;
113
+ }
75
114
  const raster = options.qrMatrix;
76
115
  if (nutzlast !== '' && raster !== undefined) {
77
116
  if (modus === 'imageRaster') {
@@ -98,27 +137,28 @@ function escPosLayoutErgebnis(layout, options = {}) {
98
137
  }
99
138
  (0, index_js_1.escPosQrCode)(doc, nutzlast, qrOptionen);
100
139
  };
101
- const grid = (0, grid_js_1.renderReceiptGrid)(druckbaresLayout(layout), { zeichen: grid_js_1.ZEICHEN_JE_PAPIER[paperSize] });
102
- for (const zeile of grid.lines) {
103
- switch (zeile.kind) {
104
- case 'space':
105
- (0, index_js_1.escPosFeed)(doc, 1);
106
- break;
140
+ // `blattFuerDruck` prueft das Logo-Raster bereits VOR der Rueckgabe -- die
141
+ // Schleife unten schreibt darum nie ein Byte auf ein falsch grosses Logo.
142
+ const blatt = blattFuerDruck(druckbaresLayout(layout), {
143
+ zeichen: grid_js_1.ZEICHEN_JE_PAPIER[paperSize],
144
+ logo: options.logo,
145
+ marke: options.marke,
146
+ qrGroesse: options.qrGroesse ?? 'auto',
147
+ });
148
+ for (const block of blatt.bloecke) {
149
+ switch (block.art) {
107
150
  case 'qr':
108
- qrZeile(zeile.qr ?? '');
151
+ qrZeile(block.nutzlast);
109
152
  break;
110
- case 'banner': {
111
- // Belegart/Warnung: fett zwischen zwei Volllinien — derselbe Rahmen-
112
- // Stil wie im Beleg-Viewer und im PDF (frueher druckte der Bon invers
113
- // weiss-auf-schwarz und sah damit anders aus als jede Anzeige).
114
- const rahmen = '='.repeat(grid_js_1.ZEICHEN_JE_PAPIER[paperSize]);
115
- (0, index_js_1.escPosText)(doc, rahmen, { styles: { align: 'left', bold: true } });
116
- (0, index_js_1.escPosText)(doc, zeile.text.trimEnd(), { styles: { align: 'left', bold: true, height: 2 } });
117
- (0, index_js_1.escPosText)(doc, rahmen, { styles: { align: 'left', bold: true } });
153
+ case 'logo':
154
+ if (options.logo)
155
+ (0, index_js_1.escPosRasterBild)(doc, options.logo.raster, { align: 'center' });
118
156
  break;
119
- }
120
- default:
121
- (0, index_js_1.escPosText)(doc, zeile.text.trimEnd(), { styles: { align: 'left', bold: zeile.bold } });
157
+ case 'zeile':
158
+ if (block.leer)
159
+ (0, index_js_1.escPosFeed)(doc, 1);
160
+ else
161
+ (0, index_js_1.escPosText)(doc, block.text.trimEnd(), { styles: { align: 'left', bold: block.fett } });
122
162
  break;
123
163
  }
124
164
  }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Fassade ueber den Aufrufen der Rechnungs-API: Schluessel einmal binden, dann rufen.
3
+ *
4
+ * Wie [createPartnerApi] bewusst **keine** Klasse — die Aufrufe sind freie
5
+ * Funktionen (endpunkte.ts) und bleiben einzeln importierbar.
6
+ */
7
+ import { type FetchLike } from '../client/transport.js';
8
+ import type { EInvoiceFormat } from './vertrag.js';
9
+ import type { CancelInvoiceRequest, CancelResult, CreditNoteRequest, CreditNoteResult, Customer, CustomerInput, CustomerPage, CustomerSearch, InvoiceDetail, InvoiceListQuery, InvoicePage, IssueInvoiceRequest, IssueResult } from './typen.js';
10
+ export interface RechnungApiOptions {
11
+ /** `api_key` des Kontos (`kr_live_…` / `kr_test_…`). Gehoert auf einen Server. */
12
+ apiKey: string;
13
+ /** Abweichende Basis-URL; Vorgabe `https://api.kasseneck.at/v1`. */
14
+ baseUrl?: string;
15
+ /** Zeitlimit je Aufruf in Millisekunden. */
16
+ timeoutMs?: number;
17
+ /** Eigene `fetch`-Umsetzung (Tests, Proxys). */
18
+ fetch?: FetchLike;
19
+ }
20
+ export interface RechnungApi {
21
+ createCustomer(customer: CustomerInput, optionen?: {
22
+ idempotencyKey?: string;
23
+ }): Promise<Customer>;
24
+ getCustomer(kennung: {
25
+ customerId: string;
26
+ } | {
27
+ externalId: string;
28
+ }): Promise<Customer>;
29
+ updateCustomer(customerId: string, patch: Partial<CustomerInput>): Promise<Customer>;
30
+ searchCustomers(suche: CustomerSearch): Promise<CustomerPage>;
31
+ issueInvoice(anfrage: IssueInvoiceRequest): Promise<IssueResult>;
32
+ cancelInvoice(anfrage: CancelInvoiceRequest): Promise<CancelResult>;
33
+ createCreditNote(anfrage: CreditNoteRequest): Promise<CreditNoteResult>;
34
+ getInvoice(kennung: {
35
+ invoiceId: string;
36
+ } | {
37
+ number: string;
38
+ }): Promise<InvoiceDetail>;
39
+ listInvoices(abfrage?: InvoiceListQuery): Promise<InvoicePage>;
40
+ getInvoicePdf(invoiceId: string): Promise<Uint8Array>;
41
+ getInvoiceXml(invoiceId: string, format?: EInvoiceFormat): Promise<string>;
42
+ }
43
+ export declare function createRechnungApi(optionen: RechnungApiOptions): RechnungApi;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ /**
3
+ * Fassade ueber den Aufrufen der Rechnungs-API: Schluessel einmal binden, dann rufen.
4
+ *
5
+ * Wie [createPartnerApi] bewusst **keine** Klasse — die Aufrufe sind freie
6
+ * Funktionen (endpunkte.ts) und bleiben einzeln importierbar.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.createRechnungApi = createRechnungApi;
10
+ const transport_js_1 = require("../client/transport.js");
11
+ const auth_js_1 = require("./auth.js");
12
+ const endpunkte_js_1 = require("./endpunkte.js");
13
+ function createRechnungApi(optionen) {
14
+ const transportOptionen = {
15
+ auth: (0, auth_js_1.rechnungKeyAuth)({ apiKey: optionen.apiKey }),
16
+ baseUrl: optionen.baseUrl,
17
+ timeoutMs: optionen.timeoutMs,
18
+ fetch: optionen.fetch,
19
+ };
20
+ const rufen = (0, transport_js_1.createTransport)(transportOptionen);
21
+ const rufenBinaer = (0, transport_js_1.createBinaryTransport)(transportOptionen);
22
+ return {
23
+ createCustomer: (customer, o) => (0, endpunkte_js_1.createCustomer)(rufen, customer, o),
24
+ getCustomer: (kennung) => (0, endpunkte_js_1.getCustomer)(rufen, kennung),
25
+ updateCustomer: (id, patch) => (0, endpunkte_js_1.updateCustomer)(rufen, id, patch),
26
+ searchCustomers: (suche) => (0, endpunkte_js_1.searchCustomers)(rufen, suche),
27
+ issueInvoice: (anfrage) => (0, endpunkte_js_1.issueInvoice)(rufen, anfrage),
28
+ cancelInvoice: (anfrage) => (0, endpunkte_js_1.cancelInvoice)(rufen, anfrage),
29
+ createCreditNote: (anfrage) => (0, endpunkte_js_1.createCreditNote)(rufen, anfrage),
30
+ getInvoice: (kennung) => (0, endpunkte_js_1.getInvoice)(rufen, kennung),
31
+ listInvoices: (abfrage) => (0, endpunkte_js_1.listInvoices)(rufen, abfrage),
32
+ getInvoicePdf: (id) => (0, endpunkte_js_1.getInvoicePdf)(rufenBinaer, id),
33
+ getInvoiceXml: (id, format) => (0, endpunkte_js_1.getInvoiceXml)(rufen, id, format),
34
+ };
35
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Anmeldung fuer die Rechnungs-API: der `api_key` des Kontos als Bearer.
3
+ *
4
+ * Anders als `apiKeyAuth` **ohne** `cashregister-token` — eine Rechnung
5
+ * entsteht nicht an einer Kasse, sondern am Konto.
6
+ *
7
+ * **Der Schluessel gehoert auf einen Server.** Mit ihm entstehen festgeschriebene
8
+ * Rechnungen mit fortlaufender Nummer, die sich nur noch per Gutschrift
9
+ * korrigieren lassen.
10
+ *
11
+ * Geprueft wird nur, was ohne Netz sicher falsch ist: ein leerer Wert, ein
12
+ * Partner-Schluessel (`pk_…`) oder ein Kassen-Token (`cb_…`). Die Form des
13
+ * Kontoschluessels selbst bleibt offen, weil das Backend neben `kr_<env>_…`
14
+ * weiterhin aeltere Formen annimmt. Die Meldung nennt nie den Wert, nur seine Art.
15
+ */
16
+ import type { KasseneckAuth } from '../client/auth.js';
17
+ export interface RechnungKeyAuthOptions {
18
+ /** `api_key` des Kontos, z. B. `kr_live_…` oder `kr_test_…`. */
19
+ apiKey: string;
20
+ }
21
+ export declare function rechnungKeyAuth(options: RechnungKeyAuthOptions): KasseneckAuth;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ /**
3
+ * Anmeldung fuer die Rechnungs-API: der `api_key` des Kontos als Bearer.
4
+ *
5
+ * Anders als `apiKeyAuth` **ohne** `cashregister-token` — eine Rechnung
6
+ * entsteht nicht an einer Kasse, sondern am Konto.
7
+ *
8
+ * **Der Schluessel gehoert auf einen Server.** Mit ihm entstehen festgeschriebene
9
+ * Rechnungen mit fortlaufender Nummer, die sich nur noch per Gutschrift
10
+ * korrigieren lassen.
11
+ *
12
+ * Geprueft wird nur, was ohne Netz sicher falsch ist: ein leerer Wert, ein
13
+ * Partner-Schluessel (`pk_…`) oder ein Kassen-Token (`cb_…`). Die Form des
14
+ * Kontoschluessels selbst bleibt offen, weil das Backend neben `kr_<env>_…`
15
+ * weiterhin aeltere Formen annimmt. Die Meldung nennt nie den Wert, nur seine Art.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.rechnungKeyAuth = rechnungKeyAuth;
19
+ const errors_js_1 = require("../client/errors.js");
20
+ function rechnungKeyAuth(options) {
21
+ const schluessel = typeof options?.apiKey === 'string' ? options.apiKey.trim() : '';
22
+ if (!schluessel) {
23
+ throw new errors_js_1.KasseneckAuthError('rechnungKeyAuth: apiKey fehlt');
24
+ }
25
+ if (/^pk_(live|test)_/i.test(schluessel)) {
26
+ throw new errors_js_1.KasseneckAuthError('rechnungKeyAuth: das ist ein Partner-Schluessel (pk_…) — die Rechnungs-API nimmt den api_key des Kontos (kr_…)');
27
+ }
28
+ if (/^cb_(live|test)_/i.test(schluessel)) {
29
+ throw new errors_js_1.KasseneckAuthError('rechnungKeyAuth: das ist ein Kassen-Token (cb_…) — die Rechnungs-API nimmt den api_key des Kontos (kr_…)');
30
+ }
31
+ // Pro Aufruf ein frisches Objekt, wie bei den anderen Anmeldungen.
32
+ return () => ({
33
+ headers: { Authorization: `Bearer ${schluessel}` },
34
+ params: {},
35
+ });
36
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Die Aufrufe der Rechnungs-API — Kunden, Rechnungen, Gutschriften, Dateien.
3
+ *
4
+ * Jede Funktion nimmt den Transport als ersten Parameter und ist einzeln
5
+ * importierbar; die Fassade [createRechnungApi] bindet ihn nur einmal.
6
+ *
7
+ * **Geprueft wird hier nichts Fachliches.** Die Anfrage geht unveraendert an
8
+ * das Backend, das sie gegen denselben Vertrag prueft (`vertrag.ts`) und einen
9
+ * Formfehler als `validation` mit `errors[]` zurueckgibt — zwei Pruefungen
10
+ * hiessen zwei Wahrheiten, von denen eine veraltet.
11
+ *
12
+ * **Nicht automatisch wiederholen.** Wer nach einem Zeitlimit erneut
13
+ * ausstellt, tut das mit **demselben** `idempotencyKey`: dann kommt die schon
14
+ * ausgestellte Rechnung zurueck (`replayed: true`) statt einer zweiten.
15
+ *
16
+ * Nach dem Senden wird nichts hart gecastet: fehlt ein zugesagtes Feld, wirft
17
+ * der Aufruf `KasseneckValidationError` mit `scope:'response'`.
18
+ */
19
+ import type { InternerBinaerTransport, InternerTransport } from '../client/aufrufe.js';
20
+ import type { EInvoiceFormat } from './vertrag.js';
21
+ import type { CancelInvoiceRequest, CancelResult, CreditNoteRequest, CreditNoteResult, Customer, CustomerInput, CustomerPage, CustomerSearch, InvoiceDetail, InvoiceListQuery, InvoicePage, IssueInvoiceRequest, IssueResult } from './typen.js';
22
+ export declare function createCustomer(rufen: InternerTransport, customer: CustomerInput, optionen?: {
23
+ idempotencyKey?: string;
24
+ }): Promise<Customer>;
25
+ export declare function getCustomer(rufen: InternerTransport, kennung: {
26
+ customerId: string;
27
+ } | {
28
+ externalId: string;
29
+ }): Promise<Customer>;
30
+ export declare function updateCustomer(rufen: InternerTransport, customerId: string, patch: Partial<CustomerInput>): Promise<Customer>;
31
+ export declare function searchCustomers(rufen: InternerTransport, suche: CustomerSearch): Promise<CustomerPage>;
32
+ export declare function issueInvoice(rufen: InternerTransport, anfrage: IssueInvoiceRequest): Promise<IssueResult>;
33
+ export declare function cancelInvoice(rufen: InternerTransport, anfrage: CancelInvoiceRequest): Promise<CancelResult>;
34
+ export declare function createCreditNote(rufen: InternerTransport, anfrage: CreditNoteRequest): Promise<CreditNoteResult>;
35
+ export declare function getInvoice(rufen: InternerTransport, kennung: {
36
+ invoiceId: string;
37
+ } | {
38
+ number: string;
39
+ }): Promise<InvoiceDetail>;
40
+ export declare function listInvoices(rufen: InternerTransport, abfrage?: InvoiceListQuery): Promise<InvoicePage>;
41
+ /** Das PDF der Rechnung (bei Gutschriften: der Gutschrift), mit eingebetteter Factur-X-Datei. */
42
+ export declare function getInvoicePdf(rufenBinaer: InternerBinaerTransport, invoiceId: string): Promise<Uint8Array>;
43
+ /**
44
+ * Die E-Rechnung als XML-Text. Sie kommt im gewohnten Umschlag (`data.xml`)
45
+ * und nicht als rohe Datei: so bleibt ein fachlicher Fehler
46
+ * (`einvoice_incomplete` mit `missing[]`) ein gewoehnlicher Fehler.
47
+ */
48
+ export declare function getInvoiceXml(rufen: InternerTransport, invoiceId: string, format?: EInvoiceFormat): Promise<string>;