@kreiseck/kasseneck-api 0.28.0 → 0.30.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 (113) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/README.md +41 -5
  3. package/dist/cjs/client/api.d.ts +3 -3
  4. package/dist/cjs/client/index.d.ts +1 -1
  5. package/dist/cjs/client/receipts.d.ts +32 -3
  6. package/dist/cjs/client/receipts.js +121 -6
  7. package/dist/cjs/enums/keck-payment-method.d.ts +10 -0
  8. package/dist/cjs/enums/keck-payment-method.js +6 -0
  9. package/dist/cjs/index.d.ts +2 -2
  10. package/dist/cjs/index.js +6 -2
  11. package/dist/cjs/models/cancellation.d.ts +11 -1
  12. package/dist/cjs/models/cancellation.js +15 -0
  13. package/dist/cjs/models/index.d.ts +2 -0
  14. package/dist/cjs/models/index.js +7 -1
  15. package/dist/cjs/models/payment-errors.d.ts +22 -0
  16. package/dist/cjs/models/payment-errors.js +46 -0
  17. package/dist/cjs/models/receipt-payment.d.ts +85 -0
  18. package/dist/cjs/models/receipt-payment.js +40 -0
  19. package/dist/cjs/models/receipt-summary.d.ts +9 -0
  20. package/dist/cjs/models/receipt-summary.js +2 -0
  21. package/dist/cjs/models/receipt.d.ts +9 -0
  22. package/dist/cjs/models/receipt.js +3 -0
  23. package/dist/cjs/partner/fehler.d.ts +28 -2
  24. package/dist/cjs/partner/fehler.js +55 -11
  25. package/dist/cjs/partner/index.d.ts +1 -1
  26. package/dist/cjs/partner/typen.d.ts +9 -2
  27. package/dist/cjs/receipt/layout.js +112 -10
  28. package/dist/esm/client/api.d.ts +3 -3
  29. package/dist/esm/client/index.d.ts +1 -1
  30. package/dist/esm/client/receipts.d.ts +32 -3
  31. package/dist/esm/client/receipts.js +121 -6
  32. package/dist/esm/enums/keck-payment-method.d.ts +10 -0
  33. package/dist/esm/enums/keck-payment-method.js +6 -0
  34. package/dist/esm/index.d.ts +2 -2
  35. package/dist/esm/index.js +1 -1
  36. package/dist/esm/models/cancellation.d.ts +11 -1
  37. package/dist/esm/models/cancellation.js +15 -0
  38. package/dist/esm/models/index.d.ts +2 -0
  39. package/dist/esm/models/index.js +2 -0
  40. package/dist/esm/models/payment-errors.d.ts +22 -0
  41. package/dist/esm/models/payment-errors.js +42 -0
  42. package/dist/esm/models/receipt-payment.d.ts +85 -0
  43. package/dist/esm/models/receipt-payment.js +36 -0
  44. package/dist/esm/models/receipt-summary.d.ts +9 -0
  45. package/dist/esm/models/receipt-summary.js +2 -0
  46. package/dist/esm/models/receipt.d.ts +9 -0
  47. package/dist/esm/models/receipt.js +3 -0
  48. package/dist/esm/partner/fehler.d.ts +28 -2
  49. package/dist/esm/partner/fehler.js +55 -11
  50. package/dist/esm/partner/index.d.ts +1 -1
  51. package/dist/esm/partner/typen.d.ts +9 -2
  52. package/dist/esm/receipt/layout.js +112 -10
  53. package/fixtures/belege/split-bar-rueckgeld.json +58 -0
  54. package/fixtures/belege/split-eine-karte-trinkgeld.json +75 -0
  55. package/fixtures/belege/split-karte-karte-bar.json +102 -0
  56. package/fixtures/belege/split-langer-betrag.json +74 -0
  57. package/fixtures/belege/split-tischrunde-trinkgeld.json +152 -0
  58. package/fixtures/belege/split-trinkgeld-karte.json +82 -0
  59. package/fixtures/belege/split-zwei-karten-gleicher-anbieter.json +89 -0
  60. package/fixtures/belege/storno-split-teil.json +71 -0
  61. package/fixtures/belege/storno-split-voll.json +100 -0
  62. package/fixtures/erwartet/split-bar-rueckgeld.blatt32.json +194 -0
  63. package/fixtures/erwartet/split-bar-rueckgeld.blatt48.json +182 -0
  64. package/fixtures/erwartet/split-bar-rueckgeld.grid32.txt +28 -0
  65. package/fixtures/erwartet/split-bar-rueckgeld.grid48.txt +26 -0
  66. package/fixtures/erwartet/split-bar-rueckgeld.lines.json +286 -0
  67. package/fixtures/erwartet/split-eine-karte-trinkgeld.blatt32.json +242 -0
  68. package/fixtures/erwartet/split-eine-karte-trinkgeld.blatt48.json +224 -0
  69. package/fixtures/erwartet/split-eine-karte-trinkgeld.grid32.txt +36 -0
  70. package/fixtures/erwartet/split-eine-karte-trinkgeld.grid48.txt +33 -0
  71. package/fixtures/erwartet/split-eine-karte-trinkgeld.lines.json +371 -0
  72. package/fixtures/erwartet/split-karte-karte-bar.blatt32.json +356 -0
  73. package/fixtures/erwartet/split-karte-karte-bar.blatt48.json +338 -0
  74. package/fixtures/erwartet/split-karte-karte-bar.grid32.txt +55 -0
  75. package/fixtures/erwartet/split-karte-karte-bar.grid48.txt +52 -0
  76. package/fixtures/erwartet/split-karte-karte-bar.lines.json +519 -0
  77. package/fixtures/erwartet/split-langer-betrag.blatt32.json +266 -0
  78. package/fixtures/erwartet/split-langer-betrag.blatt48.json +260 -0
  79. package/fixtures/erwartet/split-langer-betrag.grid32.txt +40 -0
  80. package/fixtures/erwartet/split-langer-betrag.grid48.txt +39 -0
  81. package/fixtures/erwartet/split-langer-betrag.lines.json +343 -0
  82. package/fixtures/erwartet/split-tischrunde-trinkgeld.blatt32.json +470 -0
  83. package/fixtures/erwartet/split-tischrunde-trinkgeld.blatt48.json +434 -0
  84. package/fixtures/erwartet/split-tischrunde-trinkgeld.grid32.txt +74 -0
  85. package/fixtures/erwartet/split-tischrunde-trinkgeld.grid48.txt +68 -0
  86. package/fixtures/erwartet/split-tischrunde-trinkgeld.lines.json +740 -0
  87. package/fixtures/erwartet/split-trinkgeld-karte.blatt32.json +272 -0
  88. package/fixtures/erwartet/split-trinkgeld-karte.blatt48.json +254 -0
  89. package/fixtures/erwartet/split-trinkgeld-karte.grid32.txt +41 -0
  90. package/fixtures/erwartet/split-trinkgeld-karte.grid48.txt +38 -0
  91. package/fixtures/erwartet/split-trinkgeld-karte.lines.json +428 -0
  92. package/fixtures/erwartet/split-zwei-karten-gleicher-anbieter.blatt32.json +326 -0
  93. package/fixtures/erwartet/split-zwei-karten-gleicher-anbieter.blatt48.json +296 -0
  94. package/fixtures/erwartet/split-zwei-karten-gleicher-anbieter.grid32.txt +50 -0
  95. package/fixtures/erwartet/split-zwei-karten-gleicher-anbieter.grid48.txt +45 -0
  96. package/fixtures/erwartet/split-zwei-karten-gleicher-anbieter.lines.json +504 -0
  97. package/fixtures/erwartet/storno-split-teil.blatt32.json +230 -0
  98. package/fixtures/erwartet/storno-split-teil.blatt48.json +224 -0
  99. package/fixtures/erwartet/storno-split-teil.grid32.txt +34 -0
  100. package/fixtures/erwartet/storno-split-teil.grid48.txt +33 -0
  101. package/fixtures/erwartet/storno-split-teil.lines.json +304 -0
  102. package/fixtures/erwartet/storno-split-voll.blatt32.json +320 -0
  103. package/fixtures/erwartet/storno-split-voll.blatt48.json +314 -0
  104. package/fixtures/erwartet/storno-split-voll.grid32.txt +49 -0
  105. package/fixtures/erwartet/storno-split-voll.grid48.txt +48 -0
  106. package/fixtures/erwartet/storno-split-voll.lines.json +410 -0
  107. package/fixtures/hobex-hps-codes.json +1 -1
  108. package/fixtures/kasse-texte.json +1 -1
  109. package/fixtures/manifest.json +72 -0
  110. package/fixtures/oberflaeche.json +12 -6
  111. package/fixtures/rechnung-api.schema.json +1 -1
  112. package/fixtures/rechnung-texte.json +1 -1
  113. package/package.json +1 -1
@@ -303,16 +303,13 @@ function stripeBlock(daten, cardPaymentId) {
303
303
  return zeilen;
304
304
  }
305
305
  /**
306
- * Der Kartenzahlungsblock des Belegs -- fuer JEDEN Anbieter, den das Backend
307
- * kennt. Ohne `cardPaymentData` bleibt der Block weg; ein unbekannter Anbieter
308
- * ebenfalls, still und ohne Fehler: ein Beleg muss sich immer zeigen lassen.
306
+ * Der Kartenzahlungsblock eines Anbieters -- fuer JEDEN Anbieter, den das
307
+ * Backend kennt. Ein unbekannter Anbieter bekommt keinen Block, still und
308
+ * ohne Fehler: ein Beleg muss sich immer zeigen lassen.
309
309
  */
310
- function kartenblock(receipt) {
311
- const daten = receipt.cardPaymentData;
312
- if (daten == null)
313
- return [];
310
+ function anbieterBlock(provider, daten, id) {
314
311
  const zeilen = (() => {
315
- switch (receipt.creditCardProvider) {
312
+ switch (provider) {
316
313
  case 'hobexHps':
317
314
  case 'hobexCloudApi':
318
315
  return hobexBlock(daten);
@@ -324,7 +321,7 @@ function kartenblock(receipt) {
324
321
  case 'myposPro':
325
322
  return myposBlock(daten);
326
323
  case 'stripe':
327
- return stripeBlock(daten, receipt.cardPaymentId ?? null);
324
+ return stripeBlock(daten, id);
328
325
  default:
329
326
  return [];
330
327
  }
@@ -337,12 +334,117 @@ function kartenblock(receipt) {
337
334
  // gehoert aber zum Blatt, nicht zum Terminal.
338
335
  return [...zeilen, { kind: 'space', lines: 1 }];
339
336
  }
337
+ /**
338
+ * Die Kartenzahlungsbloecke des Belegs. Mit Zahlungsliste (`payments`) je
339
+ * Zahlung mit Anbieter und Terminaldaten ein Block, in Zahlungsreihenfolge --
340
+ * zwei Karten desselben Anbieters ergeben zwei Bloecke; die alten
341
+ * Einzelfelder zaehlen dann nicht. Bei mehreren Zahlungen steht vor jedem
342
+ * Block, nicht fett und zentriert, die Nummer der Zahlung aus der
343
+ * Aufschluesselung („2. Kartenzahlung") -- so ist jeder Block seiner Zeile
344
+ * zuzuordnen. Ohne (oder mit leerer) Liste der bisherige Weg ueber
345
+ * `creditCardProvider`/`cardPaymentData`/`cardPaymentId` -- ebenso bei
346
+ * hoechstens einer Zahlung ohne `providerData`, wenn die Altfelder gesetzt sind.
347
+ */
348
+ function kartenblock(receipt) {
349
+ const zahlungen = receipt.payments;
350
+ // Eine einzelne Zahlung ohne Terminaldaten neben gesetzten Altfeldern
351
+ // (creditCardProvider + cardPaymentData): der bisherige Block, wie ohne Liste.
352
+ const altfelderTragen = zahlungen != null && zahlungen.length <= 1
353
+ && zahlungen.every((z) => z.providerData == null)
354
+ && receipt.creditCardProvider != null && receipt.cardPaymentData != null;
355
+ if (zahlungen != null && zahlungen.length > 0 && !altfelderTragen) {
356
+ const zeilen = [];
357
+ zahlungen.forEach((zahlung, i) => {
358
+ if (zahlung.provider == null || zahlung.providerData == null)
359
+ return;
360
+ const block = anbieterBlock(zahlung.provider, zahlung.providerData, zahlung.providerPaymentId ?? null);
361
+ if (block.length === 0)
362
+ return;
363
+ if (zahlungen.length > 1)
364
+ zeilen.push(textZeile(zahlungNummerText(zahlung, i), 'center'));
365
+ zeilen.push(...block);
366
+ });
367
+ return zeilen;
368
+ }
369
+ const daten = receipt.cardPaymentData;
370
+ if (daten == null)
371
+ return [];
372
+ return anbieterBlock(receipt.creditCardProvider, daten, receipt.cardPaymentId ?? null);
373
+ }
340
374
  function zahlungsartText(wert) {
341
375
  if (wert != null && typeof wert === 'object') {
342
376
  return wert.label;
343
377
  }
344
378
  return typeof wert === 'string' ? wert : '';
345
379
  }
380
+ /** Barzahlarten -- Zwilling von `BAR_ZAHLARTEN` (functions/gemeinsam/tip-core.js). */
381
+ const BAR_ZAHLARTEN = ['cash', 'uberCash', 'boltCash'];
382
+ function zahlartSchluessel(wert) {
383
+ if (wert != null && typeof wert === 'object')
384
+ return wert.value;
385
+ return typeof wert === 'string' ? wert : '';
386
+ }
387
+ /**
388
+ * Nummerierter Text einer Zahlung („1. Kartenzahlung", „3. Barzahlung") --
389
+ * in der Aufschluesselung und ueber ihrem Kartenblock dieselbe Nummer, in
390
+ * Zahlungsreihenfolge ab 1.
391
+ */
392
+ function zahlungNummerText(zahlung, index) {
393
+ return `${index + 1}. ${zahlungsartText(zahlung.method)}`;
394
+ }
395
+ /** „davon Trinkgeld" eingerueckt unter einer Zahlung, die Trinkgeld traegt. */
396
+ function zahlungTrinkgeldZeilen(zahlung) {
397
+ if (typeof zahlung.tipCents !== 'number' || zahlung.tipCents <= 0)
398
+ return [];
399
+ return [paarZeile(' davon Trinkgeld', `${formatCents(zahlung.tipCents)} €`, 8, 4)];
400
+ }
401
+ /**
402
+ * Gegeben/Rueckgeld unter einer Barzahlung mit `tenderedCents`. Fehlt
403
+ * `changeCents` (der Server rechnet es sonst selbst), ergibt es sich aus
404
+ * gegeben minus Betrag.
405
+ */
406
+ function barZeilen(zahlung) {
407
+ if (!BAR_ZAHLARTEN.includes(zahlartSchluessel(zahlung.method)) || typeof zahlung.tenderedCents !== 'number')
408
+ return [];
409
+ const rueckgeld = typeof zahlung.changeCents === 'number' ? zahlung.changeCents : zahlung.tenderedCents - zahlung.amountCents;
410
+ return [
411
+ paarZeile(' Gegeben:', `${formatCents(zahlung.tenderedCents)} €`, 8, 4),
412
+ paarZeile(' Rückgeld:', `${formatCents(rueckgeld)} €`, 8, 4),
413
+ ];
414
+ }
415
+ /**
416
+ * Die Zahlungszeilen unter „Gesamt:".
417
+ *
418
+ * - Ohne Zahlungsliste: „Zahlungsart: <Label>" aus `paymentMethod`, wie immer.
419
+ * - Genau eine Zahlung: dieselbe Zeile, Label aus der Zahlung.
420
+ * - Mehrere Zahlungen (auch zwei Karten, die `paymentMethod: creditCard`
421
+ * ergeben -- entschieden wird an der Laenge, nie an `mixed`): „Zahlungsarten:"
422
+ * und je Zahlung eine nummerierte Zeile mit Betrag, ohne Anbieter (der
423
+ * steht im Kartenblock mit derselben Nummer). Breite 8:4 -- auf 58 mm
424
+ * bleiben der Betragsspalte elf Zeichen, genug fuer „-9999,99 €".
425
+ *
426
+ * Unter jeder Zahlung in dieser Reihenfolge: „davon Trinkgeld" (bei
427
+ * `tipCents`), dann bei einer Barzahlung mit gegebenem Betrag „Gegeben:" und
428
+ * „Rückgeld:" -- alles, was zu einer Zahlung gehoert, zwei Zeichen eingerueckt,
429
+ * die Zahlung selbst buendig.
430
+ */
431
+ function zahlungsZeilen(receipt) {
432
+ const zahlungen = receipt.payments;
433
+ if (zahlungen == null || zahlungen.length === 0) {
434
+ return [paarZeile('Zahlungsart:', zahlungsartText(receipt.paymentMethod))];
435
+ }
436
+ if (zahlungen.length === 1) {
437
+ const zahlung = zahlungen[0];
438
+ return [paarZeile('Zahlungsart:', zahlungsartText(zahlung.method)), ...zahlungTrinkgeldZeilen(zahlung), ...barZeilen(zahlung)];
439
+ }
440
+ const zeilen = [textZeile('Zahlungsarten:')];
441
+ zahlungen.forEach((zahlung, i) => {
442
+ zeilen.push(paarZeile(zahlungNummerText(zahlung, i), `${formatCents(zahlung.amountCents)} €`, 8, 4));
443
+ zeilen.push(...zahlungTrinkgeldZeilen(zahlung));
444
+ zeilen.push(...barZeilen(zahlung));
445
+ });
446
+ return zeilen;
447
+ }
346
448
  // -------------------------------------------------------- Kleinunternehmer
347
449
  /**
348
450
  * Hinweis auf die Steuerbefreiung, den ein Kleinunternehmerbeleg tragen muss —
@@ -910,7 +1012,7 @@ function buildReceiptLayout(receipt, company, options = {}) {
910
1012
  lines.push({ kind: 'rule', char: '-' });
911
1013
  }
912
1014
  lines.push(paarZeile('Gesamt:', `${formatCents(summeCents)} €`));
913
- lines.push(paarZeile('Zahlungsart:', zahlungsartText(receipt.paymentMethod)));
1015
+ lines.push(...zahlungsZeilen(receipt));
914
1016
  lines.push({ kind: 'space', lines: 1 });
915
1017
  // --- Rechtshinweise und Ausfallhinweis
916
1018
  const hinweise = company.isSmallBusiness
@@ -3,7 +3,7 @@ import { type CreateStripeLinkOptions, type StripeCaptureResult } from '../payme
3
3
  import { type HobexPayOptions, type HobexRefundOptions } from '../payments/hobex.js';
4
4
  import { type TransportOptions } from './transport.js';
5
5
  import { type CashboxStatus, type SignatureStatus } from './status.js';
6
- import { type SendReceiptEmailOptions, type SendReceiptEmailResult, type ListMyReceiptsOptions, type ReceiptList, type ReceiptWithCompany, type SellReceiptOptions, type CancelReceiptOptions, type CancelReceiptResult, type CreateCancelReceiptOptions } from './receipts.js';
6
+ import { type SendReceiptEmailOptions, type SendReceiptEmailResult, type ListMyReceiptsOptions, type ReceiptList, type ReceiptWithCompany, type SellReceiptOptions, type SellReceiptWithPaymentsOptions, type CancelReceiptOptions, type CancelReceiptResult, type CreateCancelReceiptOptions } from './receipts.js';
7
7
  /**
8
8
  * Schlichte Factory ueber den Endpunkt-Funktionen: bindet einen Transport
9
9
  * einmal und liefert die Aufrufe ohne den wiederkehrenden ersten Parameter.
@@ -30,9 +30,9 @@ import { type SendReceiptEmailOptions, type SendReceiptEmailResult, type ListMyR
30
30
  */
31
31
  export interface KasseneckApi {
32
32
  /** Normalbeleg (Verkauf). */
33
- sellReceipt(options: SellReceiptOptions): Promise<Receipt>;
33
+ sellReceipt(options: SellReceiptOptions | SellReceiptWithPaymentsOptions): Promise<Receipt>;
34
34
  /** Normalbeleg samt Firmen-/Druckdaten fuer den Belegdruck. */
35
- sellReceiptWithCompany(options: SellReceiptOptions): Promise<ReceiptWithCompany>;
35
+ sellReceiptWithCompany(options: SellReceiptOptions | SellReceiptWithPaymentsOptions): Promise<ReceiptWithCompany>;
36
36
  /** Storno eines bestehenden Belegs — voll oder in Teilen, ueber den Storno-Endpunkt. */
37
37
  cancelReceipt(options: CancelReceiptOptions): Promise<CancelReceiptResult>;
38
38
  /** Storno aus frei uebergebenen Positionen. */
@@ -2,7 +2,7 @@ export { type AuthCredentials, type KasseneckAuth, type ApiKeyAuthOptions, type
2
2
  export { DEFAULT_BASE_URL, DEFAULT_TIMEOUT_MS, type HttpResponseLike, type HttpRequestInit, type FetchLike, type TransportOptions, type TransportBodyFields, type KasseneckTransport, type KasseneckBinaryTransport, createTransport, createBinaryTransport, } from './transport.js';
3
3
  export { AUFRUFE, type Aufruf, } from './aufrufe.js';
4
4
  export { KasseneckApiError, KasseneckAuthError, KasseneckHttpError, KasseneckNetworkError, KasseneckValidationError, type ValidationScope, type KasseneckError, type HttpFailureReason, type CauseDigest, isKasseneckApiError, isKasseneckAuthError, isKasseneckHttpError, isKasseneckNetworkError, isKasseneckValidationError, } from './errors.js';
5
- export { type ReceiptCommonOptions, type SellReceiptOptions, type TipOptions, type TipRecipientShare, type CancelReceiptOptions, type CreateCancelReceiptOptions, type ReceiptWithCompany, sellReceipt, sellReceiptWithCompany, cancelReceipt, type CancelReceiptResult, createCancelReceipt, zeroReceipt, getReceipt, getReceiptWithCompany, generateFullReceiptId, getFirstReceiptDate, listMyReceipts, type ListMyReceiptsOptions, type ReceiptList, type ReceiptListStats, checkVoucherCombinationError, type SendReceiptEmailOptions, type SendReceiptEmailResult, sendReceiptEmail, } from './receipts.js';
5
+ export { type ReceiptCommonOptions, type SellReceiptOptions, type SellReceiptWithPaymentsOptions, type TipOptions, type TipRecipientShare, type CancelReceiptOptions, type CreateCancelReceiptOptions, type ReceiptWithCompany, sellReceipt, sellReceiptWithCompany, cancelReceipt, type CancelReceiptResult, createCancelReceipt, zeroReceipt, getReceipt, getReceiptWithCompany, generateFullReceiptId, getFirstReceiptDate, listMyReceipts, type ListMyReceiptsOptions, type ReceiptList, type ReceiptListStats, checkVoucherCombinationError, type SendReceiptEmailOptions, type SendReceiptEmailResult, sendReceiptEmail, } from './receipts.js';
6
6
  export { listMyCashregisters } from './cashregisters.js';
7
7
  export { downloadDailyReport, downloadMonthlyReport } from './reports.js';
8
8
  export { type CashboxStatus, type SignatureStatus, getCashboxStatus, getSignatureStatus, } from './status.js';
@@ -1,5 +1,5 @@
1
1
  import { ReceiptType, type ReceiptTypeKey, KeckPaymentMethod, type KeckPaymentMethodKey, CreditCardProvider } from '../enums/index.js';
2
- import { type Receipt, type ReceiptCompany, type ReceiptItem, type Voucher, type ReceiptSummary, type ReportMonth, type CancellationItem, type CancellationOf, type CancellationReason } from '../models/index.js';
2
+ import { type Receipt, type ReceiptCompany, type ReceiptItem, type Voucher, type ReceiptSummary, type ReportMonth, type CancellationItem, type CancellationOf, type CancellationReason, type ReceiptPaymentInput } from '../models/index.js';
3
3
  import type { InternerTransport } from './aufrufe.js';
4
4
  import type { Pruefangaben, ReceiptLayout } from '../receipt/layout.js';
5
5
  import type { LogoStufe } from '../receipt/blatt.js';
@@ -90,11 +90,32 @@ export interface CreateReceiptOptions extends ReceiptCommonOptions {
90
90
  * ausdruecklich uebergebene `paymentMethod` sticht.
91
91
  */
92
92
  paymentMethodFromServer?: string;
93
+ /**
94
+ * Mehrere Zahlungen je Beleg (siehe [ReceiptPaymentInput]). Schliesst
95
+ * `paymentMethod`, `paymentMethodFromServer` und die Kartenfelder aus —
96
+ * die Kartenangaben gehoeren dann in die einzelne Zahlung (Backend:
97
+ * `PAYMENTS_CONFLICT`). Nur bei `standard` und `training`.
98
+ */
99
+ payments?: ReceiptPaymentInput[];
93
100
  items?: ReceiptItem[];
94
101
  vouchers?: Voucher[];
95
102
  }
103
+ /** Verkauf mit einer Zahlungsart (`paymentMethod`, Kartenfelder aus [ReceiptCommonOptions]). */
96
104
  export interface SellReceiptOptions extends ReceiptCommonOptions {
97
105
  paymentMethod: KeckPaymentMethod | KeckPaymentMethodKey;
106
+ payments?: undefined;
107
+ items?: ReceiptItem[];
108
+ vouchers?: Voucher[];
109
+ }
110
+ /**
111
+ * Verkauf mit mehreren Zahlungen (`payments`, siehe [ReceiptPaymentInput]).
112
+ * Ohne `paymentMethod` und ohne die Kartenfelder aus [ReceiptCommonOptions] —
113
+ * die Kartenangaben stehen in der einzelnen Zahlung (Backend:
114
+ * `PAYMENTS_CONFLICT`, zur Laufzeit ebenso geprueft).
115
+ */
116
+ export interface SellReceiptWithPaymentsOptions extends ReceiptCommonOptions {
117
+ payments: ReceiptPaymentInput[];
118
+ paymentMethod?: undefined;
98
119
  items?: ReceiptItem[];
99
120
  vouchers?: Voucher[];
100
121
  }
@@ -126,6 +147,14 @@ export type CancelReceiptOptions = {
126
147
  creditCardProvider?: CreditCardProvider;
127
148
  cardPaymentId?: string;
128
149
  cardPaymentData?: Record<string, unknown>;
150
+ /**
151
+ * Rueckzahlung je Zahlung (Betraege negativ, `refundOf` = `id` der
152
+ * Originalzahlung). Schliesst `paymentMethod` und die Kartenfelder aus
153
+ * (Backend: `PAYMENTS_CONFLICT`). Ohne Angabe spiegelt der Server die
154
+ * Restbetraege jeder Originalzahlung; ein Teilstorno eines Belegs mit
155
+ * mehreren Zahlungen braucht sie (`STORNO_PAYMENTS_REQUIRED`).
156
+ */
157
+ payments?: ReceiptPaymentInput[];
129
158
  } & ({
130
159
  receipt: Receipt;
131
160
  cashregisterId?: string;
@@ -183,12 +212,12 @@ export interface ReceiptWithCompany {
183
212
  */
184
213
  export declare function createReceipt(rufen: InternerTransport, options: CreateReceiptOptions): Promise<Receipt>;
185
214
  /** Normalbeleg (Verkauf) nach RKSV. */
186
- export declare function sellReceipt(rufen: InternerTransport, options: SellReceiptOptions): Promise<Receipt>;
215
+ export declare function sellReceipt(rufen: InternerTransport, options: SellReceiptOptions | SellReceiptWithPaymentsOptions): Promise<Receipt>;
187
216
  /**
188
217
  * Normalbeleg wie [sellReceipt], liefert zusaetzlich die Firmen-/Druckdaten
189
218
  * aus derselben Antwort — alles, was ein Belegdruck braucht, in einem Aufruf.
190
219
  */
191
- export declare function sellReceiptWithCompany(rufen: InternerTransport, options: SellReceiptOptions): Promise<ReceiptWithCompany>;
220
+ export declare function sellReceiptWithCompany(rufen: InternerTransport, options: SellReceiptOptions | SellReceiptWithPaymentsOptions): Promise<ReceiptWithCompany>;
192
221
  /**
193
222
  * Storno-Beleg zu einem bestehenden Beleg — voll oder in Teilen. Prueft die
194
223
  * Eingabe, bevor etwas hinausgeht; der Server haelt die Restmengen und die
@@ -50,6 +50,22 @@ function createReceiptParams(options) {
50
50
  if (items != null && items.length > 0) {
51
51
  params['items'] = alsNutzlast(items, toReceiptItemPayload);
52
52
  }
53
+ // `payments: null` gilt wie im Backend (zahlungs-eingang.js) als nicht angegeben.
54
+ if (options.payments != null) {
55
+ // Der alte Storno-Weg und der Null-/Startbeleg nehmen keine Zahlungsliste
56
+ // (Backend: PAYMENTS_NOT_ALLOWED); ein Storno mit mehreren Zahlungen
57
+ // laeuft ueber cancelReceipt.
58
+ if (typ.value === ReceiptType.cancellation.value) {
59
+ throw eingabefehler('payments am Storno gehen nur ueber cancelReceipt.');
60
+ }
61
+ if (typ.value !== ReceiptType.standard.value && typ.value !== ReceiptType.training.value) {
62
+ throw eingabefehler(`payments sind bei receiptType "${typ.value}" nicht erlaubt.`);
63
+ }
64
+ const konflikt = zahlungsKonflikt(options);
65
+ if (konflikt != null)
66
+ throw eingabefehler(konflikt);
67
+ params['payments'] = gepruefteZahlungen(options.payments, false, 'createReceipt');
68
+ }
53
69
  // Vom Aufrufer kommt sie geprueft, vom Server roh — siehe die beiden Felder
54
70
  // in [CreateReceiptOptions]. Die Typpruefung allein reicht dafuer nicht: ein
55
71
  // Verbraucher ohne Typen faellt durch dieses Netz, und ein Tippfehler in der
@@ -133,11 +149,15 @@ export async function cancelReceipt(rufen, options) {
133
149
  if (options.note !== undefined && options.note.length > NOTE_MAX) {
134
150
  throw new KasseneckValidationError('cancelReceipt', `Anmerkung ist zu lang (hoechstens ${NOTE_MAX} Zeichen)`, 'request');
135
151
  }
152
+ // `payments: null` gilt wie im Backend als nicht angegeben.
153
+ const zahlungen = options.payments != null ? gepruefteStornoZahlungen(options) : undefined;
136
154
  const params = { cashregisterId, originalReceiptId, reason: options.reason };
137
155
  if (options.items !== undefined)
138
156
  params.items = options.items.map((p) => ({ index: p.index, quantity: p.quantity }));
139
157
  if (options.note !== undefined && options.note !== '')
140
158
  params.note = options.note;
159
+ if (zahlungen !== undefined)
160
+ params.payments = zahlungen;
141
161
  if (options.paymentMethod != null)
142
162
  params.paymentMethod = gepruefteZahlungsart(options.paymentMethod);
143
163
  const karte = options.creditCardProvider != null || options.cardPaymentId != null || options.cardPaymentData != null;
@@ -491,15 +511,110 @@ function gepruefterTip(tip) {
491
511
  }
492
512
  return nutzlast;
493
513
  }
494
- /** Zahlungsart des Aufrufers pruefen — unbekannt wirft, bevor etwas rausgeht. */
514
+ /**
515
+ * Zahlungsart des Aufrufers pruefen — unbekannt wirft, bevor etwas rausgeht.
516
+ * `mixed` wirft ebenfalls: den Wert vergibt nur der Server (Beleg mit
517
+ * mehreren Zahlarten); gesendet wird stattdessen die Zahlungsliste.
518
+ */
495
519
  function gepruefteZahlungsart(wert) {
496
- if (typeof wert === 'object') {
497
- return wert.value;
520
+ let zahlungsart;
521
+ if (typeof wert === 'object' && wert !== null) {
522
+ zahlungsart = wert.value;
523
+ }
524
+ else {
525
+ if (typeof wert !== 'string' || !Object.prototype.hasOwnProperty.call(KeckPaymentMethod, wert)) {
526
+ throw eingabefehler(`Zahlungsart: unbekannter Schluessel "${String(wert)}"`);
527
+ }
528
+ zahlungsart = KeckPaymentMethod[wert].value;
498
529
  }
499
- if (!Object.prototype.hasOwnProperty.call(KeckPaymentMethod, wert)) {
500
- throw eingabefehler(`Zahlungsart: unbekannter Schluessel "${wert}"`);
530
+ if (zahlungsart === KeckPaymentMethod.mixed.value) {
531
+ throw eingabefehler('Zahlungsart "mixed" vergibt nur der Server – mehrere Zahlarten gehen als payments hinaus.');
501
532
  }
502
- return KeckPaymentMethod[wert].value;
533
+ return zahlungsart;
534
+ }
535
+ /** Hoechstzahl der Zahlungen je Beleg (Backend: MAX_ZAHLUNGEN). */
536
+ const MAX_ZAHLUNGEN = 20;
537
+ /**
538
+ * `payments` neben einer Einzel-Zahlungsart oder Kartenfeldern? Liefert den
539
+ * Grund (Backend: PAYMENTS_CONFLICT), sonst null. Nie still eines bevorzugen.
540
+ */
541
+ function zahlungsKonflikt(options) {
542
+ for (const feld of ['paymentMethod', 'paymentMethodFromServer', 'creditCardProvider', 'cardPaymentId', 'cardPaymentData']) {
543
+ if (options[feld] != null) {
544
+ return `payments und ${feld} duerfen nicht gemeinsam gesendet werden – Kartenangaben gehoeren in die Zahlung.`;
545
+ }
546
+ }
547
+ return null;
548
+ }
549
+ /**
550
+ * Zahlungsliste pruefen und in Nutzlast-Form bringen — Formpruefung wie
551
+ * `pruefeZahlungen` im Backend, soweit sie ohne Beleg und Zahlbetrag geht
552
+ * (Summe, Anbieter-Pflicht und Trinkgeld prueft der Server). Wirft, bevor
553
+ * etwas hinausgeht.
554
+ */
555
+ function gepruefteZahlungen(roh, storno, functionName) {
556
+ const fehler = (grund) => new KasseneckValidationError(functionName, grund, 'request');
557
+ if (!Array.isArray(roh))
558
+ throw fehler('payments muss eine Liste sein.');
559
+ if (roh.length > MAX_ZAHLUNGEN)
560
+ throw fehler(`payments: es sind hoechstens ${MAX_ZAHLUNGEN} Eintraege erlaubt.`);
561
+ return roh.map((eintrag, i) => {
562
+ const nr = i + 1;
563
+ if (eintrag == null || typeof eintrag !== 'object' || Array.isArray(eintrag)) {
564
+ throw fehler(`Zahlung ${nr}: kein gueltiges Objekt.`);
565
+ }
566
+ const z = eintrag;
567
+ const method = gepruefteZahlungsart(z['method']);
568
+ const betrag = z['amountCents'];
569
+ if (typeof betrag !== 'number' || !Number.isInteger(betrag) || (storno ? betrag >= 0 : betrag <= 0)) {
570
+ throw fehler(`Zahlung ${nr}: amountCents muss eine ganze Zahl ${storno ? 'kleiner' : 'groesser'} als 0 sein.`);
571
+ }
572
+ const aus = { method, amountCents: betrag };
573
+ if (z['tenderedCents'] !== undefined) {
574
+ const gegeben = z['tenderedCents'];
575
+ if (storno || typeof gegeben !== 'number' || !Number.isInteger(gegeben) || gegeben < betrag) {
576
+ throw fehler(`Zahlung ${nr}: tenderedCents muss eine ganze Zahl von mindestens amountCents sein (nur am Verkauf).`);
577
+ }
578
+ aus['tenderedCents'] = gegeben;
579
+ }
580
+ if (z['tipCents'] !== undefined) {
581
+ const trinkgeld = z['tipCents'];
582
+ if (typeof trinkgeld !== 'number' || !Number.isInteger(trinkgeld) || trinkgeld <= 0) {
583
+ throw fehler(`Zahlung ${nr}: tipCents muss eine ganze Zahl groesser als 0 sein.`);
584
+ }
585
+ aus['tipCents'] = trinkgeld;
586
+ }
587
+ if (z['provider'] !== undefined) {
588
+ aus['provider'] = kartenanbieter(String(z['provider']));
589
+ }
590
+ if (z['providerPaymentId'] !== undefined) {
591
+ if (typeof z['providerPaymentId'] !== 'string' || z['providerPaymentId'] === '') {
592
+ throw fehler(`Zahlung ${nr}: providerPaymentId muss ein nicht-leerer Text sein.`);
593
+ }
594
+ aus['providerPaymentId'] = z['providerPaymentId'];
595
+ }
596
+ if (z['providerData'] !== undefined) {
597
+ const daten = z['providerData'];
598
+ if (daten === null || typeof daten !== 'object' || Array.isArray(daten)) {
599
+ throw fehler(`Zahlung ${nr}: providerData muss ein Objekt sein.`);
600
+ }
601
+ aus['providerData'] = daten;
602
+ }
603
+ if (z['refundOf'] !== undefined) {
604
+ if (!storno || typeof z['refundOf'] !== 'string' || z['refundOf'] === '') {
605
+ throw fehler(`Zahlung ${nr}: refundOf gibt es nur am Storno, als id der Originalzahlung.`);
606
+ }
607
+ aus['refundOf'] = z['refundOf'];
608
+ }
609
+ return aus;
610
+ });
611
+ }
612
+ /** `payments` am Storno: Konflikt mit Zahlungsart/Kartenfeldern, dann Form. */
613
+ function gepruefteStornoZahlungen(options) {
614
+ const konflikt = zahlungsKonflikt(options);
615
+ if (konflikt != null)
616
+ throw new KasseneckValidationError('cancelReceipt', konflikt, 'request');
617
+ return gepruefteZahlungen(options.payments, true, 'cancelReceipt');
503
618
  }
504
619
  /** Kartenanbieter pruefen — er stammt vom Aufrufer, nicht aus Serverdaten. */
505
620
  function kartenanbieter(wert) {
@@ -5,6 +5,11 @@
5
5
  * `label` ist das deutsche Anzeige-Label fuer die Zahlungsart-Zeile auf dem Beleg.
6
6
  * Muss 1:1 mit dem Backend-Mapping `paymentMethodToString` (functions/helper.js)
7
7
  * uebereinstimmen.
8
+ *
9
+ * `mixed` vergibt nur der Server: ein Beleg mit mehreren Zahlungen
10
+ * verschiedener Zahlart (`payments`) traegt ihn als Einzelfeld
11
+ * `paymentMethod`. Lesen ist erlaubt, Senden nicht — wer mehrere Zahlarten
12
+ * kassiert, schickt die Zahlungsliste, nie `mixed`.
8
13
  */
9
14
  export declare const KeckPaymentMethod: {
10
15
  readonly cash: {
@@ -52,6 +57,11 @@ export declare const KeckPaymentMethod: {
52
57
  readonly needsCreditCard: true;
53
58
  readonly label: "Bolt Card";
54
59
  };
60
+ readonly mixed: {
61
+ readonly value: "mixed";
62
+ readonly needsCreditCard: false;
63
+ readonly label: "Mehrere Zahlungsarten";
64
+ };
55
65
  };
56
66
  export type KeckPaymentMethodKey = keyof typeof KeckPaymentMethod;
57
67
  export type KeckPaymentMethod = (typeof KeckPaymentMethod)[KeckPaymentMethodKey];
@@ -6,6 +6,11 @@ import { defineEnum } from './define-enum.js';
6
6
  * `label` ist das deutsche Anzeige-Label fuer die Zahlungsart-Zeile auf dem Beleg.
7
7
  * Muss 1:1 mit dem Backend-Mapping `paymentMethodToString` (functions/helper.js)
8
8
  * uebereinstimmen.
9
+ *
10
+ * `mixed` vergibt nur der Server: ein Beleg mit mehreren Zahlungen
11
+ * verschiedener Zahlart (`payments`) traegt ihn als Einzelfeld
12
+ * `paymentMethod`. Lesen ist erlaubt, Senden nicht — wer mehrere Zahlarten
13
+ * kassiert, schickt die Zahlungsliste, nie `mixed`.
9
14
  */
10
15
  export const KeckPaymentMethod = defineEnum({
11
16
  cash: { value: 'cash', needsCreditCard: false, label: 'Barzahlung' },
@@ -17,4 +22,5 @@ export const KeckPaymentMethod = defineEnum({
17
22
  boltApp: { value: 'boltApp', needsCreditCard: false, label: 'Bolt App' },
18
23
  boltCash: { value: 'boltCash', needsCreditCard: false, label: 'Bolt Cash' },
19
24
  boltCard: { value: 'boltCard', needsCreditCard: true, label: 'Bolt Card' },
25
+ mixed: { value: 'mixed', needsCreditCard: false, label: 'Mehrere Zahlungsarten' },
20
26
  });
@@ -1,5 +1,5 @@
1
1
  export { ReceiptType, type ReceiptTypeKey, VatRate, type VatRateKey, KeckPaymentMethod, type KeckPaymentMethodKey, CreditCardProvider, type CreditCardProviderKey, VoucherType, type VoucherTypeKey, VoucherAction, type VoucherActionKey, StripeLinkMode, type StripeLinkModeKey, } from './enums/index.js';
2
- export { type ReceiptItem, type ReceiptItemPayload, type ReceiptItemPayloadRead, toReceiptItemPayload, fromReceiptItemPayload, receiptItemTotalCents, receiptItemIsValid, negateReceiptItem, type TipRecipient, isTipItem, type Voucher, type VoucherPayload, toVoucherPayload, fromVoucherPayload, voucherIsValid, type Receipt, type ReceiptPayload, type ReceiptPayloadRead, toReceiptPayload, fromReceiptPayload, receiptSubSumCents, receiptSumCents, type CancellationOf, type CancellationItem, type Cancellation, type CancellationReason, type CancellationErrorCode, CANCELLATION_REASONS, CANCELLATION_ERROR_CODES, CANCELLATION_RESERVATION_MS, isCancellationReason, isCancellationErrorCode, type ReceiptEmailErrorCode, RECEIPT_EMAIL_ERROR_CODES, isReceiptEmailErrorCode, remainingQuantities, type ReceiptCompany, type ReceiptCompanyPayload, fromReceiptCompanyPayload, receiptCompanyTaxInfo, type Cashregister, type CashregisterOnboarding, type CashregisterPayload, type CashregisterOnboardingPayload, fromCashregisterPayload, type ReceiptSummary, type ReceiptSummaryPayload, fromReceiptSummaryPayload, type ZeroKind, ZERO_KINDS, istZeroKind, type ReportMonth, reportMonthFromDate, previousReportMonth, nextReportMonth, reportMonthKey, reportMonthReadable, type StripeUrlSession, type StripeUrlSessionPayload, toStripeUrlSessionPayload, fromStripeUrlSessionPayload, type HobexReceipt, type HobexReceiptPayload, toHobexReceiptPayload, fromHobexReceiptPayload, hobexReceiptToCardPaymentData, hobexReceiptNeedsSignature, } from './models/index.js';
3
- export { type AuthCredentials, type KasseneckAuth, type ApiKeyAuthOptions, type RegisterUserAuthOptions, apiKeyAuth, registerUserAuth, DEFAULT_BASE_URL, DEFAULT_TIMEOUT_MS, type HttpResponseLike, type HttpRequestInit, type FetchLike, type TransportOptions, type TransportBodyFields, type KasseneckTransport, type KasseneckBinaryTransport, AUFRUFE, type Aufruf, createTransport, createBinaryTransport, KasseneckApiError, KasseneckAuthError, KasseneckHttpError, KasseneckNetworkError, KasseneckValidationError, type ValidationScope, type KasseneckError, type HttpFailureReason, type CauseDigest, isKasseneckApiError, isKasseneckAuthError, isKasseneckHttpError, isKasseneckNetworkError, isKasseneckValidationError, type ReceiptCommonOptions, type SellReceiptOptions, type TipOptions, type TipRecipientShare, type CancelReceiptOptions, type CancelReceiptResult, type CreateCancelReceiptOptions, type ReceiptWithCompany, sellReceipt, sellReceiptWithCompany, cancelReceipt, createCancelReceipt, zeroReceipt, getReceipt, getReceiptWithCompany, generateFullReceiptId, getFirstReceiptDate, listMyReceipts, type ListMyReceiptsOptions, type ReceiptList, type ReceiptListStats, listMyCashregisters, checkVoucherCombinationError, type SendReceiptEmailOptions, type SendReceiptEmailResult, sendReceiptEmail, downloadDailyReport, downloadMonthlyReport, type CashboxStatus, type SignatureStatus, getCashboxStatus, getSignatureStatus, type KasseneckApi, createKasseneckApi, } from './client/index.js';
2
+ export { type ReceiptItem, type ReceiptItemPayload, type ReceiptItemPayloadRead, toReceiptItemPayload, fromReceiptItemPayload, receiptItemTotalCents, receiptItemIsValid, negateReceiptItem, type TipRecipient, isTipItem, type Voucher, type VoucherPayload, toVoucherPayload, fromVoucherPayload, voucherIsValid, type Receipt, type ReceiptPayload, type ReceiptPayloadRead, toReceiptPayload, fromReceiptPayload, receiptSubSumCents, receiptSumCents, type CancellationOf, type CancellationItem, type Cancellation, type CancellationReason, type CancellationErrorCode, CANCELLATION_REASONS, CANCELLATION_ERROR_CODES, CANCELLATION_RESERVATION_MS, isCancellationReason, isCancellationErrorCode, type ReceiptPayment, type ReceiptPaymentPayload, type ReceiptPaymentInput, fromReceiptPaymentPayload, toReceiptPaymentPayload, type PaymentErrorCode, PAYMENT_ERROR_CODES, isPaymentErrorCode, type ReceiptEmailErrorCode, RECEIPT_EMAIL_ERROR_CODES, isReceiptEmailErrorCode, remainingQuantities, type ReceiptCompany, type ReceiptCompanyPayload, fromReceiptCompanyPayload, receiptCompanyTaxInfo, type Cashregister, type CashregisterOnboarding, type CashregisterPayload, type CashregisterOnboardingPayload, fromCashregisterPayload, type ReceiptSummary, type ReceiptSummaryPayload, fromReceiptSummaryPayload, type ZeroKind, ZERO_KINDS, istZeroKind, type ReportMonth, reportMonthFromDate, previousReportMonth, nextReportMonth, reportMonthKey, reportMonthReadable, type StripeUrlSession, type StripeUrlSessionPayload, toStripeUrlSessionPayload, fromStripeUrlSessionPayload, type HobexReceipt, type HobexReceiptPayload, toHobexReceiptPayload, fromHobexReceiptPayload, hobexReceiptToCardPaymentData, hobexReceiptNeedsSignature, } from './models/index.js';
3
+ export { type AuthCredentials, type KasseneckAuth, type ApiKeyAuthOptions, type RegisterUserAuthOptions, apiKeyAuth, registerUserAuth, DEFAULT_BASE_URL, DEFAULT_TIMEOUT_MS, type HttpResponseLike, type HttpRequestInit, type FetchLike, type TransportOptions, type TransportBodyFields, type KasseneckTransport, type KasseneckBinaryTransport, AUFRUFE, type Aufruf, createTransport, createBinaryTransport, KasseneckApiError, KasseneckAuthError, KasseneckHttpError, KasseneckNetworkError, KasseneckValidationError, type ValidationScope, type KasseneckError, type HttpFailureReason, type CauseDigest, isKasseneckApiError, isKasseneckAuthError, isKasseneckHttpError, isKasseneckNetworkError, isKasseneckValidationError, type ReceiptCommonOptions, type SellReceiptOptions, type SellReceiptWithPaymentsOptions, type TipOptions, type TipRecipientShare, type CancelReceiptOptions, type CancelReceiptResult, type CreateCancelReceiptOptions, type ReceiptWithCompany, sellReceipt, sellReceiptWithCompany, cancelReceipt, createCancelReceipt, zeroReceipt, getReceipt, getReceiptWithCompany, generateFullReceiptId, getFirstReceiptDate, listMyReceipts, type ListMyReceiptsOptions, type ReceiptList, type ReceiptListStats, listMyCashregisters, checkVoucherCombinationError, type SendReceiptEmailOptions, type SendReceiptEmailResult, sendReceiptEmail, downloadDailyReport, downloadMonthlyReport, type CashboxStatus, type SignatureStatus, getCashboxStatus, getSignatureStatus, type KasseneckApi, createKasseneckApi, } from './client/index.js';
4
4
  export { parseServerTimeStamp, toViennaWallClock, type ViennaWallClock } from './vienna-time.js';
5
5
  export { type KasseSettingsBetrieb, type KasseSettingsGeraet, type KasseSettings, type ArticleGroup, type KasseArtikel, KASSE_BETRIEB_STANDARD, KASSE_GERAET_STANDARD, mergeKasseSettings, fromArticleGroupPayload, fromKasseArtikelPayload, listMyArticleGroups, listMyArticles, getKasseSettings, setMyKasseSettings, setMyRegisterDeviceSettings, verteileRabatt, cancelScopeOf, receiptsScopeOf, } from './kasse/index.js';
package/dist/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export { ReceiptType, VatRate, KeckPaymentMethod, CreditCardProvider, VoucherType, VoucherAction, StripeLinkMode, } from './enums/index.js';
2
- export { toReceiptItemPayload, fromReceiptItemPayload, receiptItemTotalCents, receiptItemIsValid, negateReceiptItem, isTipItem, toVoucherPayload, fromVoucherPayload, voucherIsValid, toReceiptPayload, fromReceiptPayload, receiptSubSumCents, receiptSumCents, CANCELLATION_REASONS, CANCELLATION_ERROR_CODES, CANCELLATION_RESERVATION_MS, isCancellationReason, isCancellationErrorCode, RECEIPT_EMAIL_ERROR_CODES, isReceiptEmailErrorCode, remainingQuantities, fromReceiptCompanyPayload, receiptCompanyTaxInfo, fromCashregisterPayload, fromReceiptSummaryPayload, ZERO_KINDS, istZeroKind, reportMonthFromDate, previousReportMonth, nextReportMonth, reportMonthKey, reportMonthReadable, toStripeUrlSessionPayload, fromStripeUrlSessionPayload, toHobexReceiptPayload, fromHobexReceiptPayload, hobexReceiptToCardPaymentData, hobexReceiptNeedsSignature, } from './models/index.js';
2
+ export { toReceiptItemPayload, fromReceiptItemPayload, receiptItemTotalCents, receiptItemIsValid, negateReceiptItem, isTipItem, toVoucherPayload, fromVoucherPayload, voucherIsValid, toReceiptPayload, fromReceiptPayload, receiptSubSumCents, receiptSumCents, CANCELLATION_REASONS, CANCELLATION_ERROR_CODES, CANCELLATION_RESERVATION_MS, isCancellationReason, isCancellationErrorCode, fromReceiptPaymentPayload, toReceiptPaymentPayload, PAYMENT_ERROR_CODES, isPaymentErrorCode, RECEIPT_EMAIL_ERROR_CODES, isReceiptEmailErrorCode, remainingQuantities, fromReceiptCompanyPayload, receiptCompanyTaxInfo, fromCashregisterPayload, fromReceiptSummaryPayload, ZERO_KINDS, istZeroKind, reportMonthFromDate, previousReportMonth, nextReportMonth, reportMonthKey, reportMonthReadable, toStripeUrlSessionPayload, fromStripeUrlSessionPayload, toHobexReceiptPayload, fromHobexReceiptPayload, hobexReceiptToCardPaymentData, hobexReceiptNeedsSignature, } from './models/index.js';
3
3
  export { apiKeyAuth, registerUserAuth, DEFAULT_BASE_URL, DEFAULT_TIMEOUT_MS, AUFRUFE, createTransport, createBinaryTransport, KasseneckApiError, KasseneckAuthError, KasseneckHttpError, KasseneckNetworkError, KasseneckValidationError, isKasseneckApiError, isKasseneckAuthError, isKasseneckHttpError, isKasseneckNetworkError, isKasseneckValidationError, sellReceipt, sellReceiptWithCompany, cancelReceipt, createCancelReceipt, zeroReceipt, getReceipt, getReceiptWithCompany, generateFullReceiptId, getFirstReceiptDate, listMyReceipts, listMyCashregisters, checkVoucherCombinationError, sendReceiptEmail, downloadDailyReport, downloadMonthlyReport, getCashboxStatus, getSignatureStatus, createKasseneckApi, } from './client/index.js';
4
4
  export { parseServerTimeStamp, toViennaWallClock } from './vienna-time.js';
5
5
  export { KASSE_BETRIEB_STANDARD, KASSE_GERAET_STANDARD, mergeKasseSettings, fromArticleGroupPayload, fromKasseArtikelPayload, listMyArticleGroups, listMyArticles, getKasseSettings, setMyKasseSettings, setMyRegisterDeviceSettings, verteileRabatt, cancelScopeOf, receiptsScopeOf, } from './kasse/index.js';
@@ -27,8 +27,18 @@ export declare function isCancellationReason(value: unknown): value is Cancellat
27
27
  *
28
28
  * Nur Auth-/Parameterfehler (Sitzung abgelaufen, Pflichtfeld fehlt) kommen
29
29
  * ohne Code; dort bleibt `code` undefined.
30
+ *
31
+ * Die vier `STORNO_…`-Codes am Ende gehoeren zur Rueckzahlung je Zahlung
32
+ * (mehrere Zahlungen je Beleg); Formfehler an `payments` selbst melden die
33
+ * Codes aus [PAYMENT_ERROR_CODES].
34
+ *
35
+ * Die Werte hier sind die von `/v1` und intern. Unter `/v3` heissen die
36
+ * Storno-Codes nach dem /v3-Vokabular anders (`already_cancelled`,
37
+ * `cancellation_payments_required`, functions/gemeinsam/api-vokabular-v3.js);
38
+ * diese Namen kommen mit der Umstellung des Pakets auf `/v3`.
39
+ * [isCancellationErrorCode] prueft darum exakt.
30
40
  */
31
- export declare const CANCELLATION_ERROR_CODES: readonly ["beleg_nicht_gefunden", "belegart_nicht_stornierbar", "trainingsbeleg", "bereits_storniert", "position_ungueltig", "menge_ueber_rest", "grund_unbekannt", "anmerkung_zu_lang", "items_ungueltig", "kasse_nicht_zugewiesen", "keine_berechtigung", "nur_eigene_belege", "kasse_unvollstaendig", "storno_fehlgeschlagen"];
41
+ export declare const CANCELLATION_ERROR_CODES: readonly ["beleg_nicht_gefunden", "belegart_nicht_stornierbar", "trainingsbeleg", "bereits_storniert", "position_ungueltig", "menge_ueber_rest", "grund_unbekannt", "anmerkung_zu_lang", "items_ungueltig", "kasse_nicht_zugewiesen", "keine_berechtigung", "nur_eigene_belege", "kasse_unvollstaendig", "storno_fehlgeschlagen", "STORNO_PAYMENTS_REQUIRED", "STORNO_REFUND_EXCEEDS_PAYMENT", "STORNO_REFUND_REFERENCE_REQUIRED", "STORNO_REFUND_REFERENCE_UNKNOWN"];
32
42
  export type CancellationErrorCode = (typeof CANCELLATION_ERROR_CODES)[number];
33
43
  export declare function isCancellationErrorCode(value: unknown): value is CancellationErrorCode;
34
44
  /** Bezug eines Storno-Belegs auf sein Original. */
@@ -27,6 +27,16 @@ export function isCancellationReason(value) {
27
27
  *
28
28
  * Nur Auth-/Parameterfehler (Sitzung abgelaufen, Pflichtfeld fehlt) kommen
29
29
  * ohne Code; dort bleibt `code` undefined.
30
+ *
31
+ * Die vier `STORNO_…`-Codes am Ende gehoeren zur Rueckzahlung je Zahlung
32
+ * (mehrere Zahlungen je Beleg); Formfehler an `payments` selbst melden die
33
+ * Codes aus [PAYMENT_ERROR_CODES].
34
+ *
35
+ * Die Werte hier sind die von `/v1` und intern. Unter `/v3` heissen die
36
+ * Storno-Codes nach dem /v3-Vokabular anders (`already_cancelled`,
37
+ * `cancellation_payments_required`, functions/gemeinsam/api-vokabular-v3.js);
38
+ * diese Namen kommen mit der Umstellung des Pakets auf `/v3`.
39
+ * [isCancellationErrorCode] prueft darum exakt.
30
40
  */
31
41
  export const CANCELLATION_ERROR_CODES = [
32
42
  'beleg_nicht_gefunden', // Original fehlt oder gehoert nicht zu dieser Kasse
@@ -43,6 +53,11 @@ export const CANCELLATION_ERROR_CODES = [
43
53
  'nur_eigene_belege', // Recht "eigene", fremder Beleg
44
54
  'kasse_unvollstaendig', // api_key/token fehlen am Konto bzw. an der Kasse
45
55
  'storno_fehlgeschlagen', // der Storno-Beleg selbst wurde abgelehnt (z. B. Signatur)
56
+ // Mehrere Zahlungen je Beleg (Rueckzahlung je Zahlung):
57
+ 'STORNO_PAYMENTS_REQUIRED', // Teilstorno eines Belegs mit mehreren Zahlungen ohne payments
58
+ 'STORNO_REFUND_EXCEEDS_PAYMENT', // Rueckzahlungen auf eine Zahlung uebersteigen deren Rest
59
+ 'STORNO_REFUND_REFERENCE_REQUIRED', // Karten-Rueckzahlung ohne refundOf einer Kartenzahlung
60
+ 'STORNO_REFUND_REFERENCE_UNKNOWN', // refundOf nennt keine Zahlung des Originals
46
61
  ];
47
62
  export function isCancellationErrorCode(value) {
48
63
  return typeof value === 'string' && CANCELLATION_ERROR_CODES.includes(value);
@@ -2,6 +2,8 @@ export { type ReceiptItem, type ReceiptItemPayload, type ReceiptItemPayloadRead,
2
2
  export { type Voucher, type VoucherPayload, toVoucherPayload, fromVoucherPayload, voucherIsValid } from './voucher.js';
3
3
  export { type Receipt, type ReceiptPayload, type ReceiptPayloadRead, toReceiptPayload, fromReceiptPayload, receiptSubSumCents, receiptSumCents, } from './receipt.js';
4
4
  export { type CancellationOf, type CancellationItem, type Cancellation, type CancellationReason, type CancellationErrorCode, CANCELLATION_REASONS, CANCELLATION_ERROR_CODES, CANCELLATION_RESERVATION_MS, isCancellationReason, isCancellationErrorCode, remainingQuantities, } from './cancellation.js';
5
+ export { type ReceiptPayment, type ReceiptPaymentPayload, type ReceiptPaymentInput, fromReceiptPaymentPayload, toReceiptPaymentPayload, } from './receipt-payment.js';
6
+ export { type PaymentErrorCode, PAYMENT_ERROR_CODES, isPaymentErrorCode } from './payment-errors.js';
5
7
  export { type ReceiptEmailErrorCode, RECEIPT_EMAIL_ERROR_CODES, isReceiptEmailErrorCode, } from './receipt-email.js';
6
8
  export { type ReceiptCompany, type ReceiptCompanyPayload, fromReceiptCompanyPayload, receiptCompanyTaxInfo, } from './receipt-company.js';
7
9
  export { type Cashregister, type CashregisterOnboarding, type CashregisterPayload, type CashregisterOnboardingPayload, fromCashregisterPayload, } from './cashregister.js';
@@ -2,6 +2,8 @@ export { toReceiptItemPayload, fromReceiptItemPayload, receiptItemTotalCents, re
2
2
  export { toVoucherPayload, fromVoucherPayload, voucherIsValid } from './voucher.js';
3
3
  export { toReceiptPayload, fromReceiptPayload, receiptSubSumCents, receiptSumCents, } from './receipt.js';
4
4
  export { CANCELLATION_REASONS, CANCELLATION_ERROR_CODES, CANCELLATION_RESERVATION_MS, isCancellationReason, isCancellationErrorCode, remainingQuantities, } from './cancellation.js';
5
+ export { fromReceiptPaymentPayload, toReceiptPaymentPayload, } from './receipt-payment.js';
6
+ export { PAYMENT_ERROR_CODES, isPaymentErrorCode } from './payment-errors.js';
5
7
  export { RECEIPT_EMAIL_ERROR_CODES, isReceiptEmailErrorCode, } from './receipt-email.js';
6
8
  export { fromReceiptCompanyPayload, receiptCompanyTaxInfo, } from './receipt-company.js';
7
9
  export { fromCashregisterPayload, } from './cashregister.js';
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Mehrere Zahlungen je Beleg — Fehlercode-Katalog, Zwilling von
3
+ * `functions/gemeinsam/zahlungen-core.js` ZAHLUNGS_FEHLERCODES (gleiche
4
+ * Codes, gleiche Reihenfolge).
5
+ *
6
+ * `createReceipt` und `cancelReceipt` legen sie bei jedem Fehler rund um
7
+ * `payments` (und bei den Aufrufer-Vorbedingungen wie `PAYMENTS_CONFLICT`)
8
+ * als `code` neben die Meldung; das Paket reicht sie als
9
+ * [KasseneckApiError.code] durch. **Entscheide am Code, nie am Text** — die
10
+ * deutsche Meldung darf sich aendern, der Code nicht.
11
+ *
12
+ * Schreibweise: auf `/v1`, `/v2` und intern kommen die Codes gross
13
+ * (`PAYMENTS_SUM_MISMATCH`), unter `/v3` schreibt der Rand des Backends sie
14
+ * klein (`payments_sum_mismatch`, functions/gemeinsam/api-vokabular-v3.js:
15
+ * jeder dieser Codes 1:1 in Kleinschreibung, anders als die Storno-Codes).
16
+ * [isPaymentErrorCode] erkennt beide; wer selbst vergleicht, vergleicht
17
+ * `code.toUpperCase()`.
18
+ */
19
+ export declare const PAYMENT_ERROR_CODES: readonly ["PAYMENTS_INVALID", "PAYMENT_METHOD_INVALID", "PAYMENT_AMOUNT_INVALID", "PAYMENT_TENDERED_INVALID", "PAYMENT_PROVIDER_INVALID", "PAYMENT_PROVIDER_NOT_ALLOWED", "PAYMENTS_SUM_MISMATCH", "PAYMENTS_DUE_NEGATIVE", "PAYMENTS_NOT_ALLOWED", "PAYMENTS_CONFLICT", "PAYMENTS_REQUIRED", "PAYMENT_METHOD_NOT_SUPPORTED", "TIP_PAYMENT_METHOD_INVALID", "TIP_PAYMENT_METHOD_REQUIRED", "TIP_EXCEEDS_PAYMENT", "PAYMENT_REFUND_NOT_ALLOWED", "PAYMENT_TIP_INVALID", "TIP_CONFLICT"];
20
+ export type PaymentErrorCode = (typeof PAYMENT_ERROR_CODES)[number];
21
+ /** Erkennt einen Code aus [PAYMENT_ERROR_CODES] — gross (`/v1`) wie klein (`/v3`). */
22
+ export declare function isPaymentErrorCode(value: unknown): value is PaymentErrorCode | Lowercase<PaymentErrorCode>;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Mehrere Zahlungen je Beleg — Fehlercode-Katalog, Zwilling von
3
+ * `functions/gemeinsam/zahlungen-core.js` ZAHLUNGS_FEHLERCODES (gleiche
4
+ * Codes, gleiche Reihenfolge).
5
+ *
6
+ * `createReceipt` und `cancelReceipt` legen sie bei jedem Fehler rund um
7
+ * `payments` (und bei den Aufrufer-Vorbedingungen wie `PAYMENTS_CONFLICT`)
8
+ * als `code` neben die Meldung; das Paket reicht sie als
9
+ * [KasseneckApiError.code] durch. **Entscheide am Code, nie am Text** — die
10
+ * deutsche Meldung darf sich aendern, der Code nicht.
11
+ *
12
+ * Schreibweise: auf `/v1`, `/v2` und intern kommen die Codes gross
13
+ * (`PAYMENTS_SUM_MISMATCH`), unter `/v3` schreibt der Rand des Backends sie
14
+ * klein (`payments_sum_mismatch`, functions/gemeinsam/api-vokabular-v3.js:
15
+ * jeder dieser Codes 1:1 in Kleinschreibung, anders als die Storno-Codes).
16
+ * [isPaymentErrorCode] erkennt beide; wer selbst vergleicht, vergleicht
17
+ * `code.toUpperCase()`.
18
+ */
19
+ export const PAYMENT_ERROR_CODES = Object.freeze([
20
+ 'PAYMENTS_INVALID', // payments ist keine Liste oder hat mehr als 20 Eintraege
21
+ 'PAYMENT_METHOD_INVALID', // Zahlart unbekannt oder mixed
22
+ 'PAYMENT_AMOUNT_INVALID', // amountCents keine Ganzzahl, 0 oder falsches Vorzeichen
23
+ 'PAYMENT_TENDERED_INVALID', // tenderedCents an Nicht-Bar-Zahlung, zu klein oder doppelt
24
+ 'PAYMENT_PROVIDER_INVALID', // Karte ohne/mit unbekanntem provider, providerPaymentId fehlt
25
+ 'PAYMENT_PROVIDER_NOT_ALLOWED', // Anbieterfelder an einer Zahlung, die weder Karte noch online ist
26
+ 'PAYMENTS_SUM_MISMATCH', // Summe != Zahlbetrag (Antwort nennt data.expectedCents)
27
+ 'PAYMENTS_DUE_NEGATIVE', // Zahlbetrag < 0 (Wertgutschein groesser als der Beleg)
28
+ 'PAYMENTS_NOT_ALLOWED', // Null-/Startbeleg mit Zahlungen, alter Storno-Weg
29
+ 'PAYMENTS_CONFLICT', // payments zusammen mit paymentMethod oder Kartenfeldern
30
+ 'PAYMENTS_REQUIRED', // /v3 ohne payments
31
+ 'PAYMENT_METHOD_NOT_SUPPORTED', // paymentMethod/Kartenfelder unter /v3
32
+ 'TIP_PAYMENT_METHOD_INVALID', // Trinkgeld-Zahlart kommt in payments nicht vor
33
+ 'TIP_PAYMENT_METHOD_REQUIRED', // mehrere Zahlarten, tip.paymentMethod fehlt
34
+ 'TIP_EXCEEDS_PAYMENT', // Trinkgeld uebersteigt die Zahlungen seiner Zahlart
35
+ 'PAYMENT_REFUND_NOT_ALLOWED', // refundOf ausserhalb eines Stornos oder kein String
36
+ 'PAYMENT_TIP_INVALID', // tipCents keine Ganzzahl, <= 0, > amountCents oder nicht am Verkauf
37
+ 'TIP_CONFLICT', // tip und payments[].tipCents zugleich
38
+ ]);
39
+ /** Erkennt einen Code aus [PAYMENT_ERROR_CODES] — gross (`/v1`) wie klein (`/v3`). */
40
+ export function isPaymentErrorCode(value) {
41
+ return typeof value === 'string' && PAYMENT_ERROR_CODES.includes(value.toUpperCase());
42
+ }