@kreiseck/kasseneck-api 0.16.0 → 0.17.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 (39) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +35 -0
  3. package/dist/cjs/client/aufrufe.d.ts +1 -1
  4. package/dist/cjs/client/aufrufe.js +1 -0
  5. package/dist/cjs/rechnung/api.d.ts +8 -3
  6. package/dist/cjs/rechnung/api.js +2 -1
  7. package/dist/cjs/rechnung/endpunkte.d.ts +13 -4
  8. package/dist/cjs/rechnung/endpunkte.js +19 -3
  9. package/dist/cjs/rechnung/index.d.ts +4 -3
  10. package/dist/cjs/rechnung/index.js +8 -1
  11. package/dist/cjs/rechnung/texte.d.ts +202 -0
  12. package/dist/cjs/rechnung/texte.js +377 -0
  13. package/dist/cjs/rechnung/typen.d.ts +23 -2
  14. package/dist/cjs/rechnung/vertrag.d.ts +25 -2
  15. package/dist/cjs/rechnung/vertrag.js +139 -2
  16. package/dist/esm/client/aufrufe.d.ts +1 -1
  17. package/dist/esm/client/aufrufe.js +1 -0
  18. package/dist/esm/rechnung/api.d.ts +8 -3
  19. package/dist/esm/rechnung/api.js +3 -2
  20. package/dist/esm/rechnung/endpunkte.d.ts +13 -4
  21. package/dist/esm/rechnung/endpunkte.js +18 -3
  22. package/dist/esm/rechnung/index.d.ts +4 -3
  23. package/dist/esm/rechnung/index.js +3 -2
  24. package/dist/esm/rechnung/texte.d.ts +202 -0
  25. package/dist/esm/rechnung/texte.js +373 -0
  26. package/dist/esm/rechnung/typen.d.ts +23 -2
  27. package/dist/esm/rechnung/vertrag.d.ts +25 -2
  28. package/dist/esm/rechnung/vertrag.js +138 -1
  29. package/fixtures/hobex-hps-codes.json +1 -1
  30. package/fixtures/kasse-texte.json +1 -1
  31. package/fixtures/oberflaeche.json +62 -3
  32. package/fixtures/rechnung-api-beispiele/brands-ok.json +8 -0
  33. package/fixtures/rechnung-api-beispiele/issue-englisch.json +30 -0
  34. package/fixtures/rechnung-api-beispiele/issue-fehler-einheit.json +26 -0
  35. package/fixtures/rechnung-api-beispiele/issue-fehler-sprache.json +26 -0
  36. package/fixtures/rechnung-api-beispiele/issue-netto-20.json +1 -1
  37. package/fixtures/rechnung-api.schema.json +142 -6
  38. package/fixtures/rechnung-texte.json +424 -0
  39. package/package.json +2 -1
@@ -31,6 +31,7 @@ export const RECHNUNG_AUFRUFE = [
31
31
  'getInvoicePdf',
32
32
  'getInvoiceXml',
33
33
  'getInvoiceSetupStatus',
34
+ 'listBrands',
34
35
  ];
35
36
  /**
36
37
  * Stabile Fehlercodes. Das Fremdsystem verzweigt am Code, der Text darf sich
@@ -54,6 +55,8 @@ export const INVOICE_ERROR_CODES = [
54
55
  'einvoice_incomplete',
55
56
  'invoice_api_not_enabled',
56
57
  'invoice_setup_incomplete',
58
+ 'language_not_allowed',
59
+ 'brand_not_found',
57
60
  ];
58
61
  /** Gruende einer Gutschrift. Der Server druckt den deutschen Anzeigetext. */
59
62
  export const CREDIT_NOTE_REASONS = [
@@ -70,6 +73,130 @@ export const CUSTOMER_TYPES = ['private', 'company'];
70
73
  export const INVOICE_LIST_STATUS = ['final', 'paid', 'cancelled', 'open', 'overdue'];
71
74
  export const DOC_TYPES = ['RE', 'GU'];
72
75
  export const EINVOICE_FORMATS = ['ubl', 'cii'];
76
+ /**
77
+ * Sprachen einer Rechnung. Die Sprache wird beim Festschreiben eingefroren;
78
+ * fehlt sie an Kunde oder Rechnung, gilt `de`. Behoerden bekommen immer `de`
79
+ * (`language_not_allowed`). Datum und Betraege bleiben in jeder Sprache
80
+ * oesterreichisch formatiert.
81
+ */
82
+ export const INVOICE_LANGUAGES = ['de', 'en'];
83
+ /**
84
+ * Einheiten einer Position. Die API nimmt nur diese Schluessel an; gedruckt
85
+ * wird das Kuerzel in der Sprache der Rechnung (`RECHNUNG_TEXTE`,
86
+ * `einheit.<schluessel>`), die E-Rechnung fuehrt den UN/ECE-Code
87
+ * (`RECHNUNG_EINHEITEN_CODES`). Ohne Angabe gilt `piece`.
88
+ */
89
+ export const INVOICE_UNITS = [
90
+ 'piece',
91
+ 'pair',
92
+ 'set',
93
+ 'dozen',
94
+ 'second',
95
+ 'minute',
96
+ 'hour',
97
+ 'day',
98
+ 'night',
99
+ 'week',
100
+ 'month',
101
+ 'quarter',
102
+ 'half_year',
103
+ 'year',
104
+ 'milligram',
105
+ 'gram',
106
+ 'kilogram',
107
+ 'tonne',
108
+ 'millimetre',
109
+ 'centimetre',
110
+ 'metre',
111
+ 'running_metre',
112
+ 'kilometre',
113
+ 'square_metre',
114
+ 'hectare',
115
+ 'millilitre',
116
+ 'litre',
117
+ 'cubic_metre',
118
+ 'kilowatt_hour',
119
+ 'megawatt_hour',
120
+ 'gigabyte',
121
+ 'terabyte',
122
+ 'flat_rate',
123
+ 'person',
124
+ 'licence',
125
+ 'user',
126
+ 'device',
127
+ 'session',
128
+ 'trip',
129
+ 'page',
130
+ 'sheet',
131
+ 'package',
132
+ 'box',
133
+ 'carton',
134
+ 'bottle',
135
+ 'can',
136
+ 'roll',
137
+ 'bag',
138
+ 'pallet',
139
+ ];
140
+ /**
141
+ * UN/ECE-Code je Einheit (Recommendation 20, Verpackungen aus Recommendation 21
142
+ * mit `X`). Mehrere Einheiten duerfen denselben Code tragen (Meter und
143
+ * Laufmeter; Lizenz, Benutzer, Geraet als Stueck). Die Validatoren der
144
+ * E-Rechnung pruefen jeden Code im Backend (Beispiel `api-einheiten`).
145
+ */
146
+ export const RECHNUNG_EINHEITEN_CODES = Object.freeze({
147
+ piece: 'C62',
148
+ pair: 'PR',
149
+ set: 'SET',
150
+ dozen: 'DZN',
151
+ second: 'SEC',
152
+ minute: 'MIN',
153
+ hour: 'HUR',
154
+ day: 'DAY',
155
+ night: 'C62',
156
+ week: 'WEE',
157
+ month: 'MON',
158
+ quarter: 'QAN',
159
+ half_year: 'SAN',
160
+ year: 'ANN',
161
+ milligram: 'MGM',
162
+ gram: 'GRM',
163
+ kilogram: 'KGM',
164
+ tonne: 'TNE',
165
+ millimetre: 'MMT',
166
+ centimetre: 'CMT',
167
+ metre: 'MTR',
168
+ running_metre: 'MTR',
169
+ kilometre: 'KMT',
170
+ square_metre: 'MTK',
171
+ // Rec 20 fuehrt fuer Hektar HAR, EN 16931 laesst davon nur H18
172
+ // („square hectometre", Synonym hectare) zu.
173
+ hectare: 'H18',
174
+ millilitre: 'MLT',
175
+ litre: 'LTR',
176
+ cubic_metre: 'MTQ',
177
+ kilowatt_hour: 'KWH',
178
+ megawatt_hour: 'MWH',
179
+ gigabyte: 'E34',
180
+ terabyte: 'E35',
181
+ flat_rate: 'LS',
182
+ person: 'IE',
183
+ licence: 'C62',
184
+ user: 'C62',
185
+ device: 'C62',
186
+ session: 'C62',
187
+ trip: 'C62',
188
+ page: 'ZP',
189
+ // Ebenso: ST („sheet") steht nicht in der Liste von EN 16931, LEF („leaf") schon.
190
+ sheet: 'LEF',
191
+ package: 'XPK',
192
+ box: 'XBX',
193
+ carton: 'XCT',
194
+ bottle: 'XBO',
195
+ can: 'XCA',
196
+ roll: 'XRO',
197
+ bag: 'XSA',
198
+ pallet: 'XPX',
199
+ });
73
200
  /**
74
201
  * Was erfuellt sein muss, bevor ueber die API ausgestellt werden darf — in
75
202
  * dieser Reihenfolge meldet `getInvoiceSetupStatus`, was fehlt, und dieselben
@@ -117,6 +244,8 @@ export const KUNDE_FELDER = Object.freeze({
117
244
  isAuthority: { typ: 'boolean', pflicht: false },
118
245
  note: text(1000),
119
246
  externalId: { typ: 'string', pflicht: false, min: 1, max: 120 },
247
+ /** Sprache der Rechnungen an diesen Kunden; fehlt = `de`. */
248
+ language: { typ: 'enum', pflicht: false, werte: INVOICE_LANGUAGES },
120
249
  });
121
250
  /** Beim Aendern ist jedes Kundenfeld optional. */
122
251
  const KUNDE_PATCH = Object.freeze(Object.fromEntries(Object.entries(KUNDE_FELDER).map(([name, feld]) => [name, { ...feld, pflicht: false }])));
@@ -125,7 +254,8 @@ export const POSITION_FELDER = Object.freeze({
125
254
  description: text(300, true),
126
255
  subtitle: text(1000),
127
256
  quantity: { typ: 'number', pflicht: true, min: 0, exklusivMin: true, max: 1_000_000, nachkomma: 3 },
128
- unit: text(20),
257
+ /** Einheit aus `INVOICE_UNITS`; ohne Angabe `piece`. */
258
+ unit: { typ: 'enum', pflicht: false, werte: INVOICE_UNITS },
129
259
  unitPriceCents: { typ: 'integer', pflicht: true, min: 0, max: 100_000_000 },
130
260
  vatRate: { typ: 'enum', pflicht: true, werte: VAT_RATES },
131
261
  discountPct: { typ: 'number', pflicht: false, min: 0, max: 100, nachkomma: 2 },
@@ -168,6 +298,10 @@ export const RECHNUNG_ANFRAGEN = Object.freeze({
168
298
  tracking: { typ: 'boolean', pflicht: false },
169
299
  items: positionen,
170
300
  metadata: { typ: 'map', pflicht: false, maxSchluessel: 20, schluesselMuster: '^[a-zA-Z0-9_]{1,40}$', wertMax: 500 },
301
+ /** Sprache dieser Rechnung; sonst die des Kunden, sonst `de`. */
302
+ language: { typ: 'enum', pflicht: false, werte: INVOICE_LANGUAGES },
303
+ /** Marke (Kennung aus `listBrands`); sonst die Standardmarke. */
304
+ brandId: id,
171
305
  },
172
306
  cancelInvoice: {
173
307
  idempotencyKey: idempotencyKey(true),
@@ -197,12 +331,15 @@ export const RECHNUNG_ANFRAGEN = Object.freeze({
197
331
  },
198
332
  getInvoicePdf: {
199
333
  invoiceId: idPflicht,
334
+ /** Andere Sprache als die der Rechnung: gekennzeichnete Uebersetzungskopie, keine eigene Rechnung. */
335
+ language: { typ: 'enum', pflicht: false, werte: INVOICE_LANGUAGES },
200
336
  },
201
337
  getInvoiceXml: {
202
338
  invoiceId: idPflicht,
203
339
  format: { typ: 'enum', pflicht: false, werte: EINVOICE_FORMATS },
204
340
  },
205
341
  getInvoiceSetupStatus: {},
342
+ listBrands: {},
206
343
  });
207
344
  /** Genau eines dieser Felder muss gesetzt sein (je Aufruf, je Gruppe). */
208
345
  export const RECHNUNG_GENAU_EINS = Object.freeze({
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.16.0",
2
+ "version": "0.17.0",
3
3
  "gemessenAn": {
4
4
  "tid": "3600335",
5
5
  "hpsVersion": "1.10.0",
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.16.0",
2
+ "version": "0.17.0",
3
3
  "meldungen": {
4
4
  "netz.keine_verbindung": {
5
5
  "text": "Keine Verbindung zum Server. Bitte die Internetverbindung prüfen und erneut versuchen."
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.16.0",
2
+ "version": "0.17.0",
3
3
  "aufrufe": [
4
4
  "activateCashregister",
5
5
  "cancelInvoice",
@@ -37,6 +37,7 @@
37
37
  "issueInvoice",
38
38
  "listCustomerCashregisters",
39
39
  "listInvoices",
40
+ "listBrands",
40
41
  "listMyArticleGroups",
41
42
  "listMyArticles",
42
43
  "listMyCashregisters",
@@ -398,7 +399,13 @@
398
399
  "credit_exceeds_invoice",
399
400
  "einvoice_incomplete",
400
401
  "invoice_api_not_enabled",
401
- "invoice_setup_incomplete"
402
+ "invoice_setup_incomplete",
403
+ "language_not_allowed",
404
+ "brand_not_found"
405
+ ],
406
+ "invoiceLanguages": [
407
+ "de",
408
+ "en"
402
409
  ],
403
410
  "invoiceListStatus": [
404
411
  "final",
@@ -417,6 +424,57 @@
417
424
  "bank_account",
418
425
  "number_format"
419
426
  ],
427
+ "invoiceUnits": [
428
+ "piece",
429
+ "pair",
430
+ "set",
431
+ "dozen",
432
+ "second",
433
+ "minute",
434
+ "hour",
435
+ "day",
436
+ "night",
437
+ "week",
438
+ "month",
439
+ "quarter",
440
+ "half_year",
441
+ "year",
442
+ "milligram",
443
+ "gram",
444
+ "kilogram",
445
+ "tonne",
446
+ "millimetre",
447
+ "centimetre",
448
+ "metre",
449
+ "running_metre",
450
+ "kilometre",
451
+ "square_metre",
452
+ "hectare",
453
+ "millilitre",
454
+ "litre",
455
+ "cubic_metre",
456
+ "kilowatt_hour",
457
+ "megawatt_hour",
458
+ "gigabyte",
459
+ "terabyte",
460
+ "flat_rate",
461
+ "person",
462
+ "licence",
463
+ "user",
464
+ "device",
465
+ "session",
466
+ "trip",
467
+ "page",
468
+ "sheet",
469
+ "package",
470
+ "box",
471
+ "carton",
472
+ "bottle",
473
+ "can",
474
+ "roll",
475
+ "bag",
476
+ "pallet"
477
+ ],
420
478
  "priceModes": [
421
479
  "net",
422
480
  "gross"
@@ -433,7 +491,8 @@
433
491
  "listInvoices",
434
492
  "getInvoicePdf",
435
493
  "getInvoiceXml",
436
- "getInvoiceSetupStatus"
494
+ "getInvoiceSetupStatus",
495
+ "listBrands"
437
496
  ],
438
497
  "taxSchemes": [
439
498
  "normal",
@@ -0,0 +1,8 @@
1
+ {
2
+ "aufruf": "listBrands",
3
+ "beschreibung": "Marken ohne Parameter",
4
+ "anfrage": {},
5
+ "erwartet": {
6
+ "ok": true
7
+ }
8
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "aufruf": "issueInvoice",
3
+ "beschreibung": "Englische Rechnung mit gewählter Marke",
4
+ "anfrage": {
5
+ "idempotencyKey": "bsp-en-1",
6
+ "customerId": "kunde_beispiel",
7
+ "taxScheme": "normal",
8
+ "priceMode": "net",
9
+ "serviceStart": "2026-09-15",
10
+ "language": "en",
11
+ "brandId": "marke_beispiel",
12
+ "items": [
13
+ {
14
+ "description": "Consulting",
15
+ "quantity": 2,
16
+ "unitPriceCents": 5000,
17
+ "vatRate": 20,
18
+ "unit": "hour"
19
+ }
20
+ ]
21
+ },
22
+ "erwartet": {
23
+ "ok": true,
24
+ "totals": {
25
+ "netCents": 10000,
26
+ "vatCents": 2000,
27
+ "grossCents": 12000
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "aufruf": "issueInvoice",
3
+ "beschreibung": "Einheit als freier Text statt Schlüssel",
4
+ "anfrage": {
5
+ "idempotencyKey": "bsp-einheit",
6
+ "taxScheme": "normal",
7
+ "priceMode": "net",
8
+ "serviceStart": "2026-09-15",
9
+ "items": [
10
+ {
11
+ "description": "Beratung",
12
+ "quantity": 2,
13
+ "unit": "Std",
14
+ "unitPriceCents": 5000,
15
+ "vatRate": 20
16
+ }
17
+ ]
18
+ },
19
+ "erwartet": {
20
+ "ok": false,
21
+ "code": "validation",
22
+ "fields": [
23
+ "items[0].unit"
24
+ ]
25
+ }
26
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "aufruf": "issueInvoice",
3
+ "beschreibung": "Unbekannte Sprache",
4
+ "anfrage": {
5
+ "idempotencyKey": "bsp-en-2",
6
+ "taxScheme": "normal",
7
+ "priceMode": "net",
8
+ "serviceStart": "2026-09-15",
9
+ "language": "fr",
10
+ "items": [
11
+ {
12
+ "description": "Beratung",
13
+ "quantity": 1,
14
+ "unitPriceCents": 1000,
15
+ "vatRate": 20
16
+ }
17
+ ]
18
+ },
19
+ "erwartet": {
20
+ "ok": false,
21
+ "code": "validation",
22
+ "fields": [
23
+ "language"
24
+ ]
25
+ }
26
+ }
@@ -13,7 +13,7 @@
13
13
  "quantity": 2,
14
14
  "unitPriceCents": 5000,
15
15
  "vatRate": 20,
16
- "unit": "Std"
16
+ "unit": "hour"
17
17
  }
18
18
  ]
19
19
  },
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "title": "Kasseneck Rechnungs-API",
4
4
  "version": 1,
5
- "paket": "0.16.0",
5
+ "paket": "0.17.0",
6
6
  "aufrufe": {
7
7
  "createCustomer": {
8
8
  "anfrage": {
@@ -79,6 +79,12 @@
79
79
  "type": "string",
80
80
  "minLength": 1,
81
81
  "maxLength": 120
82
+ },
83
+ "language": {
84
+ "enum": [
85
+ "de",
86
+ "en"
87
+ ]
82
88
  }
83
89
  },
84
90
  "required": [
@@ -204,6 +210,12 @@
204
210
  "type": "string",
205
211
  "minLength": 1,
206
212
  "maxLength": 120
213
+ },
214
+ "language": {
215
+ "enum": [
216
+ "de",
217
+ "en"
218
+ ]
207
219
  }
208
220
  },
209
221
  "additionalProperties": false
@@ -350,8 +362,57 @@
350
362
  "x-decimals": 3
351
363
  },
352
364
  "unit": {
353
- "type": "string",
354
- "maxLength": 20
365
+ "enum": [
366
+ "piece",
367
+ "pair",
368
+ "set",
369
+ "dozen",
370
+ "second",
371
+ "minute",
372
+ "hour",
373
+ "day",
374
+ "night",
375
+ "week",
376
+ "month",
377
+ "quarter",
378
+ "half_year",
379
+ "year",
380
+ "milligram",
381
+ "gram",
382
+ "kilogram",
383
+ "tonne",
384
+ "millimetre",
385
+ "centimetre",
386
+ "metre",
387
+ "running_metre",
388
+ "kilometre",
389
+ "square_metre",
390
+ "hectare",
391
+ "millilitre",
392
+ "litre",
393
+ "cubic_metre",
394
+ "kilowatt_hour",
395
+ "megawatt_hour",
396
+ "gigabyte",
397
+ "terabyte",
398
+ "flat_rate",
399
+ "person",
400
+ "licence",
401
+ "user",
402
+ "device",
403
+ "session",
404
+ "trip",
405
+ "page",
406
+ "sheet",
407
+ "package",
408
+ "box",
409
+ "carton",
410
+ "bottle",
411
+ "can",
412
+ "roll",
413
+ "bag",
414
+ "pallet"
415
+ ]
355
416
  },
356
417
  "unitPriceCents": {
357
418
  "type": "integer",
@@ -392,6 +453,17 @@
392
453
  "type": "string",
393
454
  "maxLength": 500
394
455
  }
456
+ },
457
+ "language": {
458
+ "enum": [
459
+ "de",
460
+ "en"
461
+ ]
462
+ },
463
+ "brandId": {
464
+ "type": "string",
465
+ "minLength": 1,
466
+ "maxLength": 128
395
467
  }
396
468
  },
397
469
  "required": [
@@ -490,8 +562,57 @@
490
562
  "x-decimals": 3
491
563
  },
492
564
  "unit": {
493
- "type": "string",
494
- "maxLength": 20
565
+ "enum": [
566
+ "piece",
567
+ "pair",
568
+ "set",
569
+ "dozen",
570
+ "second",
571
+ "minute",
572
+ "hour",
573
+ "day",
574
+ "night",
575
+ "week",
576
+ "month",
577
+ "quarter",
578
+ "half_year",
579
+ "year",
580
+ "milligram",
581
+ "gram",
582
+ "kilogram",
583
+ "tonne",
584
+ "millimetre",
585
+ "centimetre",
586
+ "metre",
587
+ "running_metre",
588
+ "kilometre",
589
+ "square_metre",
590
+ "hectare",
591
+ "millilitre",
592
+ "litre",
593
+ "cubic_metre",
594
+ "kilowatt_hour",
595
+ "megawatt_hour",
596
+ "gigabyte",
597
+ "terabyte",
598
+ "flat_rate",
599
+ "person",
600
+ "licence",
601
+ "user",
602
+ "device",
603
+ "session",
604
+ "trip",
605
+ "page",
606
+ "sheet",
607
+ "package",
608
+ "box",
609
+ "carton",
610
+ "bottle",
611
+ "can",
612
+ "roll",
613
+ "bag",
614
+ "pallet"
615
+ ]
495
616
  },
496
617
  "unitPriceCents": {
497
618
  "type": "integer",
@@ -614,6 +735,12 @@
614
735
  "type": "string",
615
736
  "minLength": 1,
616
737
  "maxLength": 128
738
+ },
739
+ "language": {
740
+ "enum": [
741
+ "de",
742
+ "en"
743
+ ]
617
744
  }
618
745
  },
619
746
  "required": [
@@ -650,6 +777,13 @@
650
777
  "properties": {},
651
778
  "additionalProperties": false
652
779
  }
780
+ },
781
+ "listBrands": {
782
+ "anfrage": {
783
+ "type": "object",
784
+ "properties": {},
785
+ "additionalProperties": false
786
+ }
653
787
  }
654
788
  },
655
789
  "codes": [
@@ -669,7 +803,9 @@
669
803
  "credit_exceeds_invoice",
670
804
  "einvoice_incomplete",
671
805
  "invoice_api_not_enabled",
672
- "invoice_setup_incomplete"
806
+ "invoice_setup_incomplete",
807
+ "language_not_allowed",
808
+ "brand_not_found"
673
809
  ],
674
810
  "gruende": [
675
811
  "cancellation",