@kreiseck/kasseneck-api 1.5.0 → 1.5.1

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 (44) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +64 -26
  3. package/dist/cjs/client/aufrufe.d.ts +56 -2
  4. package/dist/cjs/client/aufrufe.js +168 -1
  5. package/dist/cjs/client/errors.d.ts +32 -19
  6. package/dist/cjs/client/errors.js +28 -17
  7. package/dist/cjs/client/index.d.ts +2 -2
  8. package/dist/cjs/client/index.js +2 -1
  9. package/dist/cjs/client/transport.d.ts +27 -1
  10. package/dist/cjs/client/transport.js +25 -27
  11. package/dist/cjs/index.d.ts +1 -1
  12. package/dist/cjs/index.js +3 -2
  13. package/dist/cjs/inventory/schreiben.d.ts +3 -0
  14. package/dist/cjs/inventory/schreiben.js +6 -1
  15. package/dist/cjs/invoice/endpunkte.d.ts +6 -0
  16. package/dist/cjs/invoice/endpunkte.js +13 -2
  17. package/dist/cjs/pos/texte.d.ts +11 -6
  18. package/dist/cjs/pos/texte.js +11 -6
  19. package/dist/cjs/version.d.ts +1 -1
  20. package/dist/cjs/version.js +1 -1
  21. package/dist/esm/client/aufrufe.d.ts +56 -2
  22. package/dist/esm/client/aufrufe.js +166 -0
  23. package/dist/esm/client/errors.d.ts +32 -19
  24. package/dist/esm/client/errors.js +28 -17
  25. package/dist/esm/client/index.d.ts +2 -2
  26. package/dist/esm/client/index.js +1 -1
  27. package/dist/esm/client/transport.d.ts +27 -1
  28. package/dist/esm/client/transport.js +26 -28
  29. package/dist/esm/index.d.ts +1 -1
  30. package/dist/esm/index.js +1 -1
  31. package/dist/esm/inventory/schreiben.d.ts +3 -0
  32. package/dist/esm/inventory/schreiben.js +6 -1
  33. package/dist/esm/invoice/endpunkte.d.ts +6 -0
  34. package/dist/esm/invoice/endpunkte.js +13 -2
  35. package/dist/esm/pos/texte.d.ts +11 -6
  36. package/dist/esm/pos/texte.js +11 -6
  37. package/dist/esm/version.d.ts +1 -1
  38. package/dist/esm/version.js +1 -1
  39. package/fixtures/hobex-hps-codes.json +1 -1
  40. package/fixtures/invoice-api.schema.json +1 -1
  41. package/fixtures/invoice-texts.json +1 -1
  42. package/fixtures/pos-texts.json +1 -1
  43. package/fixtures/surface.json +55 -1
  44. package/package.json +1 -1
@@ -26,20 +26,27 @@
26
26
  * **Entscheidend ist `outcome`:** `'rejected'` heisst abgelehnt, nichts
27
27
  * geschehen, Wiederholen hilft nicht. `'unknown'` heisst: der Vorgang kann
28
28
  * ausgefuehrt sein (bei `createReceipt` ein signierter Beleg). Dann **nie
29
- * wiederholen**, sondern das Ergebnis nachlesen (Belegliste, `getReceipt`).
29
+ * blind wiederholen**: Belege, Stornos und Zahlungen nachlesen
30
+ * (Belegliste, `getReceipt`, Terminal-Beleg); ein Aufruf mit
31
+ * `idempotencyKey` (Lager schreiben, Rechnung, Partner-Betrieb mit
32
+ * Schluessel) darf mit **demselben** Schluessel erneut gesendet werden und
33
+ * wirkt genau einmal, nie mit einem neuen. `createInvoiceItem` erkennt die
34
+ * Wiederholung an `source` + `reference` (dieselben Werte erneut senden);
35
+ * Posten aendern oder zurueckziehen und Mandate haben keinen Schluessel:
36
+ * erst nachlesen.
30
37
  * - `KasseneckHttpError` — die Antwort war **keine** verwertbare Huelle:
31
38
  * HTTP 500/404 ohne Huelle, leerer Rumpf oder Text statt JSON. Beim
32
39
  * Bericht-Download gelten dieselben Gruende fuer alles, was kein PDF ist.
33
40
  * `reason` trennt die Faelle maschinenlesbar. Auf einem Aufruf mit
34
- * Wirkung (signierend oder geldbewegend) hat HTTP 5xx
41
+ * Wirkung (`UNKNOWN_OUTCOME_CALLS` in aufrufe.ts) hat HTTP 5xx
35
42
  * `outcome: 'unknown'`, ebenso HTTP 200 mit Kennzeichen, aber leerem oder
36
43
  * unlesbarem Rumpf.
37
44
  * - `KasseneckNetworkError` — die Antwort kam gar nicht: Netz weg, DNS,
38
45
  * abgebrochene Verbindung oder Zeitueberschreitung (`timedOut`). Auch hier
39
46
  * gilt `outcome`: war die Anfrage schon unterwegs und ist der Aufruf einer
40
- * mit Wirkung (signierend: `createReceipt`, `cancelReceipt`,
41
- * `financeWebService`; geldbewegend: `hobexPayApi`, `hobexRefundApi`,
42
- * `stripeCaptureIntent`), ist er `'unknown'`.
47
+ * mit Wirkung (signieren, Geld bewegen, buchen, ausstellen, anlegen,
48
+ * aendern, loeschen, senden; die Liste `UNKNOWN_OUTCOME_CALLS`), ist er
49
+ * `'unknown'`. Lesen und Probelauf bleiben `'rejected'`.
43
50
  * - `KasseneckAuthError` — es kam nicht einmal zur Anfrage, weil die Anmeldung
44
51
  * scheiterte (fehlende Zugangsdaten, oder der Token-/Sitzungsgeber warf).
45
52
  * In der Browser-Kasse mit ihrer 90-Sekunden-Sitzung ist das Alltag, kein
@@ -378,12 +385,12 @@ class KasseneckHttpError extends Error {
378
385
  /** Maschinenlesbarer Grund — trennt den Rewrite-Fall vom 500er ohne Textparsen. */
379
386
  reason;
380
387
  /**
381
- * `'unknown'` auf einem Aufruf mit Wirkung (`createReceipt`,
382
- * `cancelReceipt`, `financeWebService`, `hobexPayApi`, `hobexRefundApi`,
383
- * `stripeCaptureIntent`) bei HTTP 5xx und bei HTTP 200 mit
384
- * Kennzeichen, aber unlesbarem Rumpf (`empty-body`, `not-json` auch bei
385
- * `text/html`, `missing-status`): der Handler kann gelaufen sein, nie wiederholen,
386
- * sondern nachlesen. Sonst `'rejected'` (auch 4xx).
388
+ * `'unknown'` auf einem Aufruf mit Wirkung (`UNKNOWN_OUTCOME_CALLS`:
389
+ * signieren, Geld bewegen, buchen, ausstellen, anlegen, aendern, loeschen,
390
+ * senden) bei HTTP 5xx und bei HTTP 200 mit Kennzeichen, aber unlesbarem
391
+ * Rumpf (`empty-body`, `not-json` auch bei `text/html`, `missing-status`):
392
+ * der Handler kann gelaufen sein, nie blind wiederholen (siehe
393
+ * [ErrorOutcome]). Sonst `'rejected'` (auch 4xx, Lesen und Probelauf).
387
394
  */
388
395
  outcome;
389
396
  constructor(functionName, statusCode, contentType, reason, outcome = 'rejected') {
@@ -410,9 +417,10 @@ class KasseneckNetworkError extends Error {
410
417
  /** Code der zugrunde liegenden Ursache, sofern unbedenklich (z. B. `ECONNREFUSED`). */
411
418
  causeCode;
412
419
  /**
413
- * `'unknown'`, wenn die Anfrage schon unterwegs war und der Aufruf signiert
414
- * (`createReceipt`, `cancelReceipt`, `financeWebService`): dann nie
415
- * wiederholen, sondern nachlesen. Sonst `'rejected'`.
420
+ * `'unknown'`, wenn die Anfrage schon unterwegs war und der Aufruf Wirkung
421
+ * hat (`UNKNOWN_OUTCOME_CALLS`): dann nie blind wiederholen (siehe
422
+ * [ErrorOutcome]). Sonst `'rejected'`, auch bei Lesen und Probelauf und
423
+ * wenn schon die Anmeldung das Zeitlimit verbrauchte.
416
424
  */
417
425
  outcome;
418
426
  constructor(functionName, timedOut, timeoutMs, cause = {}, outcome = 'rejected') {
@@ -481,9 +489,12 @@ class KasseneckValidationError extends Error {
481
489
  exports.KasseneckValidationError = KasseneckValidationError;
482
490
  /**
483
491
  * Ist der Ausgang dieses Fehlers unklar (`outcome === 'unknown'`)? Dann den
484
- * Aufruf **nicht wiederholen**, sondern das Ergebnis nachlesen. Gilt fuer
485
- * jede Fehlerart; nur [KasseneckApiError], [KasseneckHttpError] und
486
- * [KasseneckNetworkError] koennen `'unknown'` sein.
492
+ * Aufruf **nicht blind wiederholen**: Belege, Stornos und Zahlungen
493
+ * nachlesen; einen Aufruf mit `idempotencyKey` nur mit **demselben**
494
+ * Schluessel erneut senden (wirkt genau einmal, ein neuer buchte doppelt);
495
+ * ohne Schluessel erst nachlesen. Gilt fuer jede Fehlerart; nur
496
+ * [KasseneckApiError], [KasseneckHttpError] und [KasseneckNetworkError]
497
+ * koennen `'unknown'` sein.
487
498
  */
488
499
  function isOutcomeUnknown(error) {
489
500
  return ((error instanceof KasseneckApiError || error instanceof KasseneckHttpError || error instanceof KasseneckNetworkError)
@@ -1,6 +1,6 @@
1
1
  export { type AuthCredentials, type KasseneckAuth, type ApiKeyAuthOptions, type RegisterUserAuthOptions, apiKeyAuth, registerUserAuth, } from './auth.js';
2
- export { DEFAULT_BASE_URL, POS_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
- export { ALL_CALLS, type ApiCall, PUBLIC_CALLS, POS_CALLS, type PublicCall, type PosCall, } from './aufrufe.js';
2
+ export { DEFAULT_BASE_URL, POS_BASE_URL, DEFAULT_TIMEOUT_MS, type HttpResponseLike, type HttpRequestInit, type FetchLike, type TransportOptions, type TransportBodyFields, type TransportCallOptions, type KasseneckTransport, type KasseneckBinaryTransport, createTransport, createBinaryTransport, } from './transport.js';
3
+ export { ALL_CALLS, type ApiCall, PUBLIC_CALLS, POS_CALLS, UNKNOWN_OUTCOME_CALLS, type PublicCall, type PosCall, } from './aufrufe.js';
4
4
  export { KasseneckApiError, KasseneckAuthError, KasseneckHttpError, KasseneckNetworkError, KasseneckValidationError, type ValidationScope, type KasseneckError, type HttpFailureReason, type CauseDigest, type ErrorOutcome, CLIENT_ERROR_CODES, type ClientErrorCode, isKasseneckApiError, isKasseneckAuthError, isKasseneckHttpError, isKasseneckNetworkError, isKasseneckValidationError, isOutcomeUnknown, } from './errors.js';
5
5
  export { type ReceiptCommonOptions, type SellReceiptOptions, type TipOptions, type TipRecipientShare, type CancelReceiptOptions, type ReceiptWithCompany, sellReceipt, sellReceiptWithCompany, paymentsExpectedCents, cardRefundReference, receiptLayoutFromResult, cancelReceipt, type CancelReceiptResult, 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';
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createKasseneckApi = exports.getSignatureStatus = exports.getCashboxStatus = exports.getReportV2 = exports.downloadMonthlyReport = exports.downloadDailyReport = exports.listMyCashregisters = exports.sendReceiptEmail = exports.checkVoucherCombinationError = exports.listMyReceipts = exports.getFirstReceiptDate = exports.generateFullReceiptId = exports.getReceiptWithCompany = exports.getReceipt = exports.zeroReceipt = exports.cancelReceipt = exports.receiptLayoutFromResult = exports.cardRefundReference = exports.paymentsExpectedCents = exports.sellReceiptWithCompany = exports.sellReceipt = exports.isOutcomeUnknown = exports.isKasseneckValidationError = exports.isKasseneckNetworkError = exports.isKasseneckHttpError = exports.isKasseneckAuthError = exports.isKasseneckApiError = exports.CLIENT_ERROR_CODES = exports.KasseneckValidationError = exports.KasseneckNetworkError = exports.KasseneckHttpError = exports.KasseneckAuthError = exports.KasseneckApiError = exports.POS_CALLS = exports.PUBLIC_CALLS = exports.ALL_CALLS = exports.createBinaryTransport = exports.createTransport = exports.DEFAULT_TIMEOUT_MS = exports.POS_BASE_URL = exports.DEFAULT_BASE_URL = exports.registerUserAuth = exports.apiKeyAuth = void 0;
3
+ exports.createKasseneckApi = exports.getSignatureStatus = exports.getCashboxStatus = exports.getReportV2 = exports.downloadMonthlyReport = exports.downloadDailyReport = exports.listMyCashregisters = exports.sendReceiptEmail = exports.checkVoucherCombinationError = exports.listMyReceipts = exports.getFirstReceiptDate = exports.generateFullReceiptId = exports.getReceiptWithCompany = exports.getReceipt = exports.zeroReceipt = exports.cancelReceipt = exports.receiptLayoutFromResult = exports.cardRefundReference = exports.paymentsExpectedCents = exports.sellReceiptWithCompany = exports.sellReceipt = exports.isOutcomeUnknown = exports.isKasseneckValidationError = exports.isKasseneckNetworkError = exports.isKasseneckHttpError = exports.isKasseneckAuthError = exports.isKasseneckApiError = exports.CLIENT_ERROR_CODES = exports.KasseneckValidationError = exports.KasseneckNetworkError = exports.KasseneckHttpError = exports.KasseneckAuthError = exports.KasseneckApiError = exports.UNKNOWN_OUTCOME_CALLS = exports.POS_CALLS = exports.PUBLIC_CALLS = exports.ALL_CALLS = exports.createBinaryTransport = exports.createTransport = exports.DEFAULT_TIMEOUT_MS = exports.POS_BASE_URL = exports.DEFAULT_BASE_URL = exports.registerUserAuth = exports.apiKeyAuth = void 0;
4
4
  var auth_js_1 = require("./auth.js");
5
5
  Object.defineProperty(exports, "apiKeyAuth", { enumerable: true, get: function () { return auth_js_1.apiKeyAuth; } });
6
6
  Object.defineProperty(exports, "registerUserAuth", { enumerable: true, get: function () { return auth_js_1.registerUserAuth; } });
@@ -14,6 +14,7 @@ var aufrufe_js_1 = require("./aufrufe.js");
14
14
  Object.defineProperty(exports, "ALL_CALLS", { enumerable: true, get: function () { return aufrufe_js_1.ALL_CALLS; } });
15
15
  Object.defineProperty(exports, "PUBLIC_CALLS", { enumerable: true, get: function () { return aufrufe_js_1.PUBLIC_CALLS; } });
16
16
  Object.defineProperty(exports, "POS_CALLS", { enumerable: true, get: function () { return aufrufe_js_1.POS_CALLS; } });
17
+ Object.defineProperty(exports, "UNKNOWN_OUTCOME_CALLS", { enumerable: true, get: function () { return aufrufe_js_1.UNKNOWN_OUTCOME_CALLS; } });
17
18
  var errors_js_1 = require("./errors.js");
18
19
  Object.defineProperty(exports, "KasseneckApiError", { enumerable: true, get: function () { return errors_js_1.KasseneckApiError; } });
19
20
  Object.defineProperty(exports, "KasseneckAuthError", { enumerable: true, get: function () { return errors_js_1.KasseneckAuthError; } });
@@ -33,6 +33,12 @@ import { type KasseneckAuth } from './auth.js';
33
33
  * **Kein Wiederholen fehlgeschlagener Aufrufe.** Ein Beleg ist nicht folgenlos
34
34
  * wiederholbar; ohne entschiedene Idempotenz waere ein automatischer zweiter
35
35
  * Versuch ein zweiter Beleg.
36
+ *
37
+ * **Ausgang je Aufruf.** Ob ein Scheitern nach dem Senden `outcome: 'unknown'`
38
+ * traegt, haengt am Aufruf: mit Wirkung ([UNKNOWN_OUTCOME_CALLS] in
39
+ * aufrufe.ts) ja, Lesen und Probelauf nein. Ein Probelauf traegt denselben
40
+ * Namen wie der echte Aufruf; die Huelle sagt es darum beim Aufruf
41
+ * (`hasEffect: false`, [TransportCallOptions]).
36
42
  */
37
43
  /** Basis-URL der oeffentlichen API (Produktion). */
38
44
  export declare const DEFAULT_BASE_URL = "https://api.kasseneck.at/v3";
@@ -151,7 +157,27 @@ export interface TransportBodyFields {
151
157
  /** Vorgangsart von `financeWebService` (z. B. `status_cashbox`). */
152
158
  method?: string;
153
159
  }
154
- export type KasseneckTransport = <T = unknown>(functionName: string, params?: Record<string, unknown>, extraBodyFields?: TransportBodyFields, secretParams?: readonly string[]) => Promise<T>;
160
+ /**
161
+ * Einstellungen fuer **einen** Aufruf, die nicht mitgesendet werden.
162
+ */
163
+ export interface TransportCallOptions {
164
+ /**
165
+ * Hat dieser Aufruf Wirkung? Entscheidet den Ausgang, wenn er scheitert,
166
+ * nachdem die Anfrage unterwegs war (Netzfehler, Zeitlimit, HTTP 5xx,
167
+ * unlesbare Erfolgsantwort, HTML mit Kennzeichen): `true` ergibt
168
+ * `outcome: 'unknown'`. Ohne Angabe gilt die Liste des Pakets
169
+ * (`UNKNOWN_OUTCOME_CALLS`); ein Name, den sie nicht kennt, gilt dann als
170
+ * ohne Wirkung.
171
+ *
172
+ * `true` fuer einen Aufruf mit Wirkung, den dieses Paket nicht kennt.
173
+ * `false` gilt **nur zusammen mit `params.dryRun === true`** (Probelauf
174
+ * unter dem Namen des echten Aufrufs, schreibt nichts) und ergibt dann
175
+ * `'rejected'`; ohne `dryRun: true` bleibt ein Aufruf aus der Liste
176
+ * `'unknown'`, was immer hier steht.
177
+ */
178
+ hasEffect?: boolean;
179
+ }
180
+ export type KasseneckTransport = <T = unknown>(functionName: string, params?: Record<string, unknown>, extraBodyFields?: TransportBodyFields, secretParams?: readonly string[], options?: TransportCallOptions) => Promise<T>;
155
181
  /**
156
182
  * Ruft eine Backend-Funktion auf, die **Binaerdaten** liefert (die beiden
157
183
  * Bericht-PDFs), und gibt sie als `Uint8Array` zurueck.
@@ -41,6 +41,12 @@ const errors_js_1 = require("./errors.js");
41
41
  * **Kein Wiederholen fehlgeschlagener Aufrufe.** Ein Beleg ist nicht folgenlos
42
42
  * wiederholbar; ohne entschiedene Idempotenz waere ein automatischer zweiter
43
43
  * Versuch ein zweiter Beleg.
44
+ *
45
+ * **Ausgang je Aufruf.** Ob ein Scheitern nach dem Senden `outcome: 'unknown'`
46
+ * traegt, haengt am Aufruf: mit Wirkung ([UNKNOWN_OUTCOME_CALLS] in
47
+ * aufrufe.ts) ja, Lesen und Probelauf nein. Ein Probelauf traegt denselben
48
+ * Namen wie der echte Aufruf; die Huelle sagt es darum beim Aufruf
49
+ * (`hasEffect: false`, [TransportCallOptions]).
44
50
  */
45
51
  /** Basis-URL der oeffentlichen API (Produktion). */
46
52
  exports.DEFAULT_BASE_URL = 'https://api.kasseneck.at/v3';
@@ -61,23 +67,6 @@ const VERSION_WERT = 'v3';
61
67
  const KASSENECK_HOSTS = new Set(['api.kasseneck.at', 'kasse.kasseneck.at']);
62
68
  /** Die 1.x-Linie spricht nur `/v3`: jede Basis endet so (`/v3` oder `/api/v3`). */
63
69
  const V3_ENDE = /\/v3$/;
64
- /**
65
- * Aufrufe mit Wirkung, die nie blind wiederholt werden duerfen: sie signieren
66
- * (`createReceipt`, `cancelReceipt`), loesen bei FinanzOnline etwas aus
67
- * (`financeWebService`) oder bewegen Geld (`hobexPayApi` belastet eine Karte,
68
- * `hobexRefundApi` erstattet, `stripeCaptureIntent` zieht eine vorgemerkte
69
- * Zahlung ein). Scheitert einer, nachdem die Anfrage unterwegs war (Netz,
70
- * Zeitlimit, HTTP 5xx, unlesbare Erfolgsantwort, HTML mit Kennzeichen), ist
71
- * sein Ausgang offen.
72
- */
73
- const UNKNOWN_OUTCOME_CALLS = new Set([
74
- 'createReceipt',
75
- 'cancelReceipt',
76
- 'financeWebService',
77
- 'hobexPayApi',
78
- 'hobexRefundApi',
79
- 'stripeCaptureIntent',
80
- ]);
81
70
  /**
82
71
  * Produkte, die das Backend in `Kasseneck-Client` zaehlt (Positivliste,
83
72
  * Nachtrag §6); alles andere zaehlte dort als `ungueltig`. Das Paket weist
@@ -94,7 +83,7 @@ const CLIENT_MAX = 64;
94
83
  exports.DEFAULT_TIMEOUT_MS = 30_000;
95
84
  function createTransport(options) {
96
85
  const kern = createCore(options);
97
- return (functionName, params, extraBodyFields, secretParams) => kern(functionName, params, extraBodyFields, secretParams, alsText, jsonAuswerten);
86
+ return (functionName, params, extraBodyFields, secretParams, callOptions) => kern(functionName, params, extraBodyFields, secretParams, callOptions, alsText, jsonAuswerten);
98
87
  }
99
88
  /**
100
89
  * Zweiter Einstiegspunkt fuer die Bericht-Downloads. Er liest die Antwort als
@@ -106,7 +95,7 @@ function createTransport(options) {
106
95
  */
107
96
  function createBinaryTransport(options) {
108
97
  const kern = createCore(options);
109
- return (functionName, params) => kern(functionName, params, undefined, undefined, alsBytes, pdfAuswerten);
98
+ return (functionName, params) => kern(functionName, params, undefined, undefined, undefined, alsBytes, pdfAuswerten);
110
99
  }
111
100
  /**
112
101
  * Gemeinsamer Kern beider Einstiegspunkte: Anmeldung, Zeitlimit, Anfrage und
@@ -130,12 +119,21 @@ function createCore(options) {
130
119
  * (Berichte, Zahlungen, FinanzOnline), geht an die oeffentliche Basis.
131
120
  */
132
121
  const basisFuer = (functionName) => (0, aufrufe_js_1.isPosOnlyCall)(functionName) || (kassenweg && (0, aufrufe_js_1.isPosCall)(functionName)) ? kassenBasis : oeffentlicheBasis;
133
- return async function aufrufen(functionName, params = {}, extraBodyFields, secretParams, lesen, auswerten) {
122
+ return async function aufrufen(functionName, params = {}, extraBodyFields, secretParams, callOptions, lesen, auswerten) {
134
123
  // Die URL nennt die Backend-Funktion, die Fehler nennen den **Vorgang**:
135
124
  // `financeWebService` fuehrt ein Dutzend verschiedener Vorgaenge unter einem
136
125
  // Endpunkt, und ein Fehler, der nur "financeWebService" sagt, verschweigt
137
126
  // dem Aufrufer, welcher davon scheiterte.
138
127
  const fehlerName = extraBodyFields?.method ? `${functionName}/${extraBodyFields.method}` : functionName;
128
+ // Ausgang eines Scheiterns nach dem Senden: offen, wenn der Aufruf Wirkung
129
+ // hat. `hasEffect: true` hebt einen fremden Aufruf auf `unknown`.
130
+ // `hasEffect: false` senkt einen Aufruf mit Wirkung nur, wenn er wirklich
131
+ // ein Probelauf ist (`dryRun === true`, so streng prueft auch das
132
+ // Backend): sonst liefe ein echter Beleg oder eine Buchung nach einem
133
+ // Zeitlimit als `rejected`, und genau das fuehrt zur Doppelbuchung.
134
+ const probelauf = callOptions?.hasEffect === false && params['dryRun'] === true;
135
+ const wirkung = callOptions?.hasEffect === true || ((0, aufrufe_js_1.isUnknownOutcomeCall)(functionName) && !probelauf);
136
+ const nachDemSenden = wirkung ? 'unknown' : 'rejected';
139
137
  // Das Zeitlimit laeuft ab HIER — es deckt die Anmeldung mit ab. Haengt die
140
138
  // Token-Erneuerung auf flauem Netz, haette der Aufruf sonst weder Ergebnis
141
139
  // noch Fehler, und die Kasse stuende still.
@@ -175,8 +173,9 @@ function createCore(options) {
175
173
  }
176
174
  // Bis hierher kam keine verwertbare Antwort: Netz weg oder Zeitlimit.
177
175
  // Die Anfrage war schon unterwegs: bei einem Aufruf mit Wirkung kann
178
- // der Beleg bzw. die Zahlung entstanden sein (Ausgang unklar, nachlesen).
179
- return new errors_js_1.KasseneckNetworkError(fehlerName, abbruch.signal.aborted, zeitlimitMs, (0, errors_js_1.causeDigest)(ursache, geheimnisse), UNKNOWN_OUTCOME_CALLS.has(functionName) ? 'unknown' : 'rejected');
176
+ // der Vorgang ausgefuehrt sein (Beleg, Zahlung, Buchung, Rechnung;
177
+ // Ausgang unklar).
178
+ return new errors_js_1.KasseneckNetworkError(fehlerName, abbruch.signal.aborted, zeitlimitMs, (0, errors_js_1.causeDigest)(ursache, geheimnisse), nachDemSenden);
180
179
  };
181
180
  const basis = basisFuer(functionName);
182
181
  const url = `${basis}/${encodeURIComponent(functionName)}`;
@@ -230,7 +229,7 @@ function createCore(options) {
230
229
  throw fehler;
231
230
  }
232
231
  // 5xx auf einem Aufruf mit Wirkung: der Handler kann gelaufen sein.
233
- const ausgang = antwort.status >= 500 && UNKNOWN_OUTCOME_CALLS.has(functionName) ? 'unknown' : 'rejected';
232
+ const ausgang = antwort.status >= 500 ? nachDemSenden : 'rejected';
234
233
  throw new errors_js_1.KasseneckHttpError(fehlerName, antwort.status, inhaltstyp, 'server-error', ausgang);
235
234
  }
236
235
  // HTTP 200 mit HTML: die Auffangregel der Single-Page-App hat den Aufruf
@@ -238,9 +237,9 @@ function createCore(options) {
238
237
  if (inhaltstyp !== undefined && /^\s*text\/html\b/i.test(inhaltstyp)) {
239
238
  // Mit Kennzeichen hat der `/v3`-Rand den Aufruf gesehen (etwa ein
240
239
  // Proxy, der nur den Inhaltstyp umschreibt). Bei einem Aufruf mit
241
- // Wirkung kann der Beleg bzw. die Zahlung dann entstanden sein: unlesbarer Rumpf,
240
+ // Wirkung kann der Vorgang dann ausgefuehrt sein: unlesbarer Rumpf,
242
241
  // Ausgang unklar, statt `route_missing`.
243
- if (UNKNOWN_OUTCOME_CALLS.has(functionName) && traegtKennzeichen(antwort)) {
242
+ if (nachDemSenden === 'unknown' && traegtKennzeichen(antwort)) {
244
243
  throw new errors_js_1.KasseneckHttpError(fehlerName, antwort.status, inhaltstyp, 'not-json', 'unknown');
245
244
  }
246
245
  throw new errors_js_1.KasseneckApiError(fehlerName, 'Route fehlt: die Antwort ist eine HTML-Seite statt des Backends', {}, 'route_missing');
@@ -258,8 +257,7 @@ function createCore(options) {
258
257
  // Ab hier kam HTTP 200 mit Kennzeichen: der `/v3`-Rand hat den Aufruf
259
258
  // gesehen. Ist der Rumpf dann unlesbar (gekuerzt von einem Proxy,
260
259
  // abgebrochene Verbindung), kann ein Handler mit Wirkung gelaufen sein.
261
- const unlesbar = UNKNOWN_OUTCOME_CALLS.has(functionName) ? 'unknown' : 'rejected';
262
- return auswerten(koerper, fehlerName, antwort.status, inhaltstyp, geheimnisse, unlesbar);
260
+ return auswerten(koerper, fehlerName, antwort.status, inhaltstyp, geheimnisse, nachDemSenden);
263
261
  }
264
262
  finally {
265
263
  // Ohne Abraeumen haelt der Wecker den Node-Prozess bis zum Zeitlimit wach.
@@ -1,6 +1,6 @@
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
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 RegistrationInfo, type ReceiptPayload, type ReceiptPayloadRead, toReceiptPayload, fromReceiptPayload, receiptSubSumCents, receiptSumCents, type CancellationOf, type CancellationItem, type Cancellation, type CancellationReason, type CancellationErrorCode, type CancellationStatus, type ReturnDisposition, RETURN_DISPOSITIONS, CANCELLATION_REASONS, CANCELLATION_STATUSES, CANCELLATION_ERROR_CODES, CANCELLATION_RESERVATION_MS, isCancellationReason, isReturnDisposition, isCancellationErrorCode, cancellationErrorCode, isCancellationError, cancellationFieldErrors, type CancellationFieldError, type ReceiptPayment, type ReceiptPaymentPayload, type ReceiptPaymentInput, fromReceiptPaymentPayload, toReceiptPaymentPayload, type PaymentErrorCode, PAYMENT_ERROR_CODES, isPaymentErrorCode, paymentErrorCode, isPaymentError, paymentFieldErrors, type PaymentFieldError, type ReceiptEmailErrorCode, type ReceiptEmailVia, RECEIPT_EMAIL_ERROR_CODES, RECEIPT_EMAIL_SEND_ERROR_CODES, type ReceiptEmailSendErrorCode, RECEIPT_EMAIL_VIAS, isReceiptEmailErrorCode, receiptEmailErrorCode, isReceiptEmailError, receiptEmailFieldErrors, type ReceiptEmailFieldError, type ReceiptErrorCode, type ReceiptFieldError, RECEIPT_ERROR_CODES, isReceiptErrorCode, receiptErrorCode, isReceiptError, receiptFieldErrors, 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, isZeroKind, 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, POS_BASE_URL, DEFAULT_TIMEOUT_MS, type HttpResponseLike, type HttpRequestInit, type FetchLike, type TransportOptions, type TransportBodyFields, type KasseneckTransport, type KasseneckBinaryTransport, ALL_CALLS, type ApiCall, PUBLIC_CALLS, POS_CALLS, type PublicCall, type PosCall, createTransport, createBinaryTransport, KasseneckApiError, KasseneckAuthError, KasseneckHttpError, KasseneckNetworkError, KasseneckValidationError, type ValidationScope, type KasseneckError, type HttpFailureReason, type CauseDigest, type ErrorOutcome, CLIENT_ERROR_CODES, type ClientErrorCode, isKasseneckApiError, isKasseneckAuthError, isKasseneckHttpError, isKasseneckNetworkError, isKasseneckValidationError, isOutcomeUnknown, type ReceiptCommonOptions, type SellReceiptOptions, type TipOptions, type TipRecipientShare, type CancelReceiptOptions, type CancelReceiptResult, type ReceiptWithCompany, sellReceipt, sellReceiptWithCompany, paymentsExpectedCents, cardRefundReference, receiptLayoutFromResult, cancelReceipt, zeroReceipt, getReceipt, getReceiptWithCompany, generateFullReceiptId, getFirstReceiptDate, listMyReceipts, type ListMyReceiptsOptions, type ReceiptList, type ReceiptListStats, listMyCashregisters, checkVoucherCombinationError, type SendReceiptEmailOptions, type SendReceiptEmailResult, sendReceiptEmail, downloadDailyReport, downloadMonthlyReport, getReportV2, type ReportV2, type ReportV2Metadata, type ReportV2Options, type CashboxStatus, type SignatureStatus, getCashboxStatus, getSignatureStatus, type KasseneckApi, createKasseneckApi, } from './client/index.js';
3
+ export { type AuthCredentials, type KasseneckAuth, type ApiKeyAuthOptions, type RegisterUserAuthOptions, apiKeyAuth, registerUserAuth, DEFAULT_BASE_URL, POS_BASE_URL, DEFAULT_TIMEOUT_MS, type HttpResponseLike, type HttpRequestInit, type FetchLike, type TransportOptions, type TransportBodyFields, type TransportCallOptions, type KasseneckTransport, type KasseneckBinaryTransport, ALL_CALLS, type ApiCall, PUBLIC_CALLS, POS_CALLS, UNKNOWN_OUTCOME_CALLS, type PublicCall, type PosCall, createTransport, createBinaryTransport, KasseneckApiError, KasseneckAuthError, KasseneckHttpError, KasseneckNetworkError, KasseneckValidationError, type ValidationScope, type KasseneckError, type HttpFailureReason, type CauseDigest, type ErrorOutcome, CLIENT_ERROR_CODES, type ClientErrorCode, isKasseneckApiError, isKasseneckAuthError, isKasseneckHttpError, isKasseneckNetworkError, isKasseneckValidationError, isOutcomeUnknown, type ReceiptCommonOptions, type SellReceiptOptions, type TipOptions, type TipRecipientShare, type CancelReceiptOptions, type CancelReceiptResult, type ReceiptWithCompany, sellReceipt, sellReceiptWithCompany, paymentsExpectedCents, cardRefundReference, receiptLayoutFromResult, cancelReceipt, zeroReceipt, getReceipt, getReceiptWithCompany, generateFullReceiptId, getFirstReceiptDate, listMyReceipts, type ListMyReceiptsOptions, type ReceiptList, type ReceiptListStats, listMyCashregisters, checkVoucherCombinationError, type SendReceiptEmailOptions, type SendReceiptEmailResult, sendReceiptEmail, downloadDailyReport, downloadMonthlyReport, getReportV2, type ReportV2, type ReportV2Metadata, type ReportV2Options, type CashboxStatus, type SignatureStatus, getCashboxStatus, getSignatureStatus, type KasseneckApi, createKasseneckApi, } from './client/index.js';
4
4
  export { type ReceiptDueTip, type ReceiptDueTipRecipient, type ReceiptDueOptions, type ReceiptDueBuckets, type ReceiptDueBreakdown, type ReceiptDueErrorReason, receiptDueCents, receiptDueBreakdown, ReceiptDueError, RECEIPT_DUE_ERROR_REASONS, isReceiptDueError, } from './receipt/due.js';
5
5
  export { parseServerTimeStamp, toViennaWallClock, type ViennaWallClock } from './vienna-time.js';
6
6
  export { type PosBusinessSettings, type PosDeviceSettings, type PosSettings, type ArticleGroup, type PosArticle, POS_BUSINESS_DEFAULTS, POS_DEVICE_DEFAULTS, mergePosSettings, fromArticleGroupPayload, fromPosArticlePayload, listMyArticleGroups, listMyArticles, getPosSettings, setMyPosSettings, setMyRegisterDeviceSettings, distributeDiscount, cancelScopeOf, receiptsScopeOf, stockViewOf, } from './pos/index.js';
package/dist/cjs/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.receiptFieldErrors = exports.isReceiptError = exports.receiptErrorCode = exports.isReceiptErrorCode = exports.RECEIPT_ERROR_CODES = exports.receiptEmailFieldErrors = exports.isReceiptEmailError = exports.receiptEmailErrorCode = exports.isReceiptEmailErrorCode = exports.RECEIPT_EMAIL_VIAS = exports.RECEIPT_EMAIL_SEND_ERROR_CODES = exports.RECEIPT_EMAIL_ERROR_CODES = exports.paymentFieldErrors = exports.isPaymentError = exports.paymentErrorCode = exports.isPaymentErrorCode = exports.PAYMENT_ERROR_CODES = exports.toReceiptPaymentPayload = exports.fromReceiptPaymentPayload = exports.cancellationFieldErrors = exports.isCancellationError = exports.cancellationErrorCode = exports.isCancellationErrorCode = exports.isReturnDisposition = exports.isCancellationReason = exports.CANCELLATION_RESERVATION_MS = exports.CANCELLATION_ERROR_CODES = exports.CANCELLATION_STATUSES = exports.CANCELLATION_REASONS = exports.RETURN_DISPOSITIONS = exports.receiptSumCents = exports.receiptSubSumCents = exports.fromReceiptPayload = exports.toReceiptPayload = exports.voucherIsValid = exports.fromVoucherPayload = exports.toVoucherPayload = exports.isTipItem = exports.negateReceiptItem = exports.receiptItemIsValid = exports.receiptItemTotalCents = exports.fromReceiptItemPayload = exports.toReceiptItemPayload = exports.StripeLinkMode = exports.VoucherAction = exports.VoucherType = exports.CreditCardProvider = exports.KeckPaymentMethod = exports.VatRate = exports.ReceiptType = void 0;
4
- exports.generateFullReceiptId = exports.getReceiptWithCompany = exports.getReceipt = exports.zeroReceipt = exports.cancelReceipt = exports.receiptLayoutFromResult = exports.cardRefundReference = exports.paymentsExpectedCents = exports.sellReceiptWithCompany = exports.sellReceipt = exports.isOutcomeUnknown = exports.isKasseneckValidationError = exports.isKasseneckNetworkError = exports.isKasseneckHttpError = exports.isKasseneckAuthError = exports.isKasseneckApiError = exports.CLIENT_ERROR_CODES = exports.KasseneckValidationError = exports.KasseneckNetworkError = exports.KasseneckHttpError = exports.KasseneckAuthError = exports.KasseneckApiError = exports.createBinaryTransport = exports.createTransport = exports.POS_CALLS = exports.PUBLIC_CALLS = exports.ALL_CALLS = exports.DEFAULT_TIMEOUT_MS = exports.POS_BASE_URL = exports.DEFAULT_BASE_URL = exports.registerUserAuth = exports.apiKeyAuth = exports.hobexReceiptNeedsSignature = exports.hobexReceiptToCardPaymentData = exports.fromHobexReceiptPayload = exports.toHobexReceiptPayload = exports.fromStripeUrlSessionPayload = exports.toStripeUrlSessionPayload = exports.reportMonthReadable = exports.reportMonthKey = exports.nextReportMonth = exports.previousReportMonth = exports.reportMonthFromDate = exports.isZeroKind = exports.ZERO_KINDS = exports.fromReceiptSummaryPayload = exports.fromCashregisterPayload = exports.receiptCompanyTaxInfo = exports.fromReceiptCompanyPayload = exports.remainingQuantities = void 0;
5
- exports.stockViewOf = exports.receiptsScopeOf = exports.cancelScopeOf = exports.distributeDiscount = exports.setMyRegisterDeviceSettings = exports.setMyPosSettings = exports.getPosSettings = exports.listMyArticles = exports.listMyArticleGroups = exports.fromPosArticlePayload = exports.fromArticleGroupPayload = exports.mergePosSettings = exports.POS_DEVICE_DEFAULTS = exports.POS_BUSINESS_DEFAULTS = exports.toViennaWallClock = exports.parseServerTimeStamp = exports.isReceiptDueError = exports.RECEIPT_DUE_ERROR_REASONS = exports.ReceiptDueError = exports.receiptDueBreakdown = exports.receiptDueCents = exports.createKasseneckApi = exports.getSignatureStatus = exports.getCashboxStatus = exports.getReportV2 = exports.downloadMonthlyReport = exports.downloadDailyReport = exports.sendReceiptEmail = exports.checkVoucherCombinationError = exports.listMyCashregisters = exports.listMyReceipts = exports.getFirstReceiptDate = void 0;
4
+ exports.getReceiptWithCompany = exports.getReceipt = exports.zeroReceipt = exports.cancelReceipt = exports.receiptLayoutFromResult = exports.cardRefundReference = exports.paymentsExpectedCents = exports.sellReceiptWithCompany = exports.sellReceipt = exports.isOutcomeUnknown = exports.isKasseneckValidationError = exports.isKasseneckNetworkError = exports.isKasseneckHttpError = exports.isKasseneckAuthError = exports.isKasseneckApiError = exports.CLIENT_ERROR_CODES = exports.KasseneckValidationError = exports.KasseneckNetworkError = exports.KasseneckHttpError = exports.KasseneckAuthError = exports.KasseneckApiError = exports.createBinaryTransport = exports.createTransport = exports.UNKNOWN_OUTCOME_CALLS = exports.POS_CALLS = exports.PUBLIC_CALLS = exports.ALL_CALLS = exports.DEFAULT_TIMEOUT_MS = exports.POS_BASE_URL = exports.DEFAULT_BASE_URL = exports.registerUserAuth = exports.apiKeyAuth = exports.hobexReceiptNeedsSignature = exports.hobexReceiptToCardPaymentData = exports.fromHobexReceiptPayload = exports.toHobexReceiptPayload = exports.fromStripeUrlSessionPayload = exports.toStripeUrlSessionPayload = exports.reportMonthReadable = exports.reportMonthKey = exports.nextReportMonth = exports.previousReportMonth = exports.reportMonthFromDate = exports.isZeroKind = exports.ZERO_KINDS = exports.fromReceiptSummaryPayload = exports.fromCashregisterPayload = exports.receiptCompanyTaxInfo = exports.fromReceiptCompanyPayload = exports.remainingQuantities = void 0;
5
+ exports.stockViewOf = exports.receiptsScopeOf = exports.cancelScopeOf = exports.distributeDiscount = exports.setMyRegisterDeviceSettings = exports.setMyPosSettings = exports.getPosSettings = exports.listMyArticles = exports.listMyArticleGroups = exports.fromPosArticlePayload = exports.fromArticleGroupPayload = exports.mergePosSettings = exports.POS_DEVICE_DEFAULTS = exports.POS_BUSINESS_DEFAULTS = exports.toViennaWallClock = exports.parseServerTimeStamp = exports.isReceiptDueError = exports.RECEIPT_DUE_ERROR_REASONS = exports.ReceiptDueError = exports.receiptDueBreakdown = exports.receiptDueCents = exports.createKasseneckApi = exports.getSignatureStatus = exports.getCashboxStatus = exports.getReportV2 = exports.downloadMonthlyReport = exports.downloadDailyReport = exports.sendReceiptEmail = exports.checkVoucherCombinationError = exports.listMyCashregisters = exports.listMyReceipts = exports.getFirstReceiptDate = exports.generateFullReceiptId = void 0;
6
6
  var index_js_1 = require("./enums/index.js");
7
7
  Object.defineProperty(exports, "ReceiptType", { enumerable: true, get: function () { return index_js_1.ReceiptType; } });
8
8
  Object.defineProperty(exports, "VatRate", { enumerable: true, get: function () { return index_js_1.VatRate; } });
@@ -82,6 +82,7 @@ Object.defineProperty(exports, "DEFAULT_TIMEOUT_MS", { enumerable: true, get: fu
82
82
  Object.defineProperty(exports, "ALL_CALLS", { enumerable: true, get: function () { return index_js_3.ALL_CALLS; } });
83
83
  Object.defineProperty(exports, "PUBLIC_CALLS", { enumerable: true, get: function () { return index_js_3.PUBLIC_CALLS; } });
84
84
  Object.defineProperty(exports, "POS_CALLS", { enumerable: true, get: function () { return index_js_3.POS_CALLS; } });
85
+ Object.defineProperty(exports, "UNKNOWN_OUTCOME_CALLS", { enumerable: true, get: function () { return index_js_3.UNKNOWN_OUTCOME_CALLS; } });
85
86
  Object.defineProperty(exports, "createTransport", { enumerable: true, get: function () { return index_js_3.createTransport; } });
86
87
  Object.defineProperty(exports, "createBinaryTransport", { enumerable: true, get: function () { return index_js_3.createBinaryTransport; } });
87
88
  Object.defineProperty(exports, "KasseneckApiError", { enumerable: true, get: function () { return index_js_3.KasseneckApiError; } });
@@ -23,6 +23,9 @@
23
23
  * **Wiederholen:** nach einem Zeitlimit oder Netzfehler denselben Aufruf mit
24
24
  * **demselben** `idempotencyKey` noch einmal senden. Er wirkt genau einmal und
25
25
  * liefert die gespeicherte Antwort; ein neuer Schluessel buchte ein zweites Mal.
26
+ * Darum meldet jeder schreibende Aufruf in diesen Faellen (auch HTTP 5xx und
27
+ * unlesbare Antwort) `outcome: 'unknown'`, nie `'rejected'`. Lesen und der
28
+ * Probelauf (`previewGoodsReceipt`) bleiben `'rejected'`.
26
29
  */
27
30
  import type { InternerTransport } from '../client/aufrufe.js';
28
31
  import type { Article, ChangeStockConditionRequest, CreateArticleRequest, CreateReservationRequest, DeactivateArticleRequest, ExtendReservationRequest, GoodsReceiptPreview, GoodsReceiptPreviewRequest, ReceiveGoodsRequest, RecordStockLossRequest, ReleaseReservationRequest, Reservation, ReservationListQuery, ReservationPage, ReverseStockMovementRequest, StockOperation, TransferStockRequest, UpdateArticleRequest } from './typen.js';
@@ -24,6 +24,9 @@
24
24
  * **Wiederholen:** nach einem Zeitlimit oder Netzfehler denselben Aufruf mit
25
25
  * **demselben** `idempotencyKey` noch einmal senden. Er wirkt genau einmal und
26
26
  * liefert die gespeicherte Antwort; ein neuer Schluessel buchte ein zweites Mal.
27
+ * Darum meldet jeder schreibende Aufruf in diesen Faellen (auch HTTP 5xx und
28
+ * unlesbare Antwort) `outcome: 'unknown'`, nie `'rejected'`. Lesen und der
29
+ * Probelauf (`previewGoodsReceipt`) bleiben `'rejected'`.
27
30
  */
28
31
  Object.defineProperty(exports, "__esModule", { value: true });
29
32
  exports.createArticle = createArticle;
@@ -214,7 +217,9 @@ async function previewGoodsReceipt(transport, request) {
214
217
  delete p.idempotencyKey;
215
218
  schluessel(name, p, { pflicht: false });
216
219
  eingangZahlen(name, p);
217
- const daten = await transport(name, { ...p, dryRun: true });
220
+ // Ein Probelauf schreibt nichts: nach einem Zeitlimit bleibt er `rejected`,
221
+ // obwohl `receiveGoods` sonst Wirkung hat.
222
+ const daten = await transport(name, { ...p, dryRun: true }, undefined, undefined, { hasEffect: false });
218
223
  return { preview: (0, lesen_js_1.liste)(name, daten, 'preview', lesen_js_1.vorschauZeile) };
219
224
  }
220
225
  const stueckPositionen = (name, p) => positionen(name, p.items, { pflicht: true, menge: 'pflicht' });
@@ -12,6 +12,12 @@
12
12
  * **Nicht automatisch wiederholen.** Wer nach einem Zeitlimit erneut
13
13
  * ausstellt, tut das mit **demselben** `idempotencyKey`: dann kommt die schon
14
14
  * ausgestellte Rechnung zurueck (`replayed: true`) statt einer zweiten.
15
+ * Jeder Aufruf mit Wirkung (ausstellen, stornieren, gutschreiben, Zahlung
16
+ * nachtragen, Kunde anlegen oder aendern) meldet nach Zeitlimit, Netzfehler,
17
+ * HTTP 5xx oder unlesbarer Antwort `outcome: 'unknown'`: er kann gewirkt
18
+ * haben. Mit Schluessel denselben Schluessel erneut senden, ohne Schluessel
19
+ * (`updateCustomer`, `createCustomer` ohne) erst nachlesen. Lesen und der
20
+ * Probelauf (`previewInvoice`) bleiben `'rejected'`.
15
21
  *
16
22
  * Nach dem Senden wird nichts hart gecastet: fehlt ein zugesagtes Feld, wirft
17
23
  * der Aufruf `KasseneckValidationError` mit `scope:'response'`.
@@ -13,6 +13,12 @@
13
13
  * **Nicht automatisch wiederholen.** Wer nach einem Zeitlimit erneut
14
14
  * ausstellt, tut das mit **demselben** `idempotencyKey`: dann kommt die schon
15
15
  * ausgestellte Rechnung zurueck (`replayed: true`) statt einer zweiten.
16
+ * Jeder Aufruf mit Wirkung (ausstellen, stornieren, gutschreiben, Zahlung
17
+ * nachtragen, Kunde anlegen oder aendern) meldet nach Zeitlimit, Netzfehler,
18
+ * HTTP 5xx oder unlesbarer Antwort `outcome: 'unknown'`: er kann gewirkt
19
+ * haben. Mit Schluessel denselben Schluessel erneut senden, ohne Schluessel
20
+ * (`updateCustomer`, `createCustomer` ohne) erst nachlesen. Lesen und der
21
+ * Probelauf (`previewInvoice`) bleiben `'rejected'`.
16
22
  *
17
23
  * Nach dem Senden wird nichts hart gecastet: fehlt ein zugesagtes Feld, wirft
18
24
  * der Aufruf `KasseneckValidationError` mit `scope:'response'`.
@@ -110,7 +116,10 @@ async function searchCustomers(transport, search) {
110
116
  }
111
117
  // ---- Rechnungen -------------------------------------------------------------
112
118
  async function issueInvoice(transport, request) {
113
- const daten = await transport('issueInvoice', nutzlast(request));
119
+ const params = nutzlast(request);
120
+ // Ohne Typen kann `dryRun: true` hier ankommen: dann ist es ein Probelauf
121
+ // ohne Wirkung (sonst: `previewInvoice`).
122
+ const daten = await transport('issueInvoice', params, undefined, undefined, { hasEffect: params['dryRun'] !== true });
114
123
  const ergebnis = {
115
124
  invoice: pflichtObjekt('issueInvoice', daten, 'invoice'),
116
125
  replayed: objekt(daten)['replayed'] === true,
@@ -131,7 +140,9 @@ async function issueInvoice(transport, request) {
131
140
  * Probelauf und Ausstellen kann sich der Kunde oder das Konto aendern.
132
141
  */
133
142
  async function previewInvoice(transport, request) {
134
- const daten = await transport('issueInvoice', { ...nutzlast(request), dryRun: true });
143
+ // Ein Probelauf schreibt nichts: nach einem Zeitlimit bleibt er `rejected`,
144
+ // obwohl `issueInvoice` sonst Wirkung hat.
145
+ const daten = await transport('issueInvoice', { ...nutzlast(request), dryRun: true }, undefined, undefined, { hasEffect: false });
135
146
  const ergebnis = { preview: pflichtObjekt('issueInvoice', daten, 'preview') };
136
147
  const notice = hinweise(daten);
137
148
  if (notice)
@@ -661,12 +661,17 @@ export interface ErrorRuleDetail {
661
661
  export declare function findErrorRule(kind: ErrorKind, detail?: ErrorRuleDetail): ErrorRule;
662
662
  /**
663
663
  * Kassen-Aufrufe mit Wirkung, die sich nach einem Netzfehler nicht gefahrlos
664
- * wiederholen lassen: die sechs, deren Ausgang das Paket selbst als unklar
665
- * fuehrt (Beleg, auch Null- und Startbeleg ueber `createReceipt`, Storno,
666
- * FinanzOnline, die drei Geldwege), dazu der Druckjob (zweiter Bon) und die
667
- * Belegmail (zweite Mail). Ob die Anfrage vor dem Abriss schon draussen war,
668
- * sieht das Paket nicht (fetch wirft in beiden Faellen gleich); darum gilt
669
- * hier immer der vorsichtige Satz.
664
+ * wiederholen lassen: Beleg (auch Null- und Startbeleg ueber
665
+ * `createReceipt`), Storno, FinanzOnline, die drei Geldwege, der Druckjob
666
+ * (zweiter Bon) und die Belegmail (zweite Mail). Ob die Anfrage vor dem
667
+ * Abriss schon draussen war, sieht das Paket nicht (fetch wirft in beiden
668
+ * Faellen gleich); darum gilt hier immer der vorsichtige Satz, auch fuer
669
+ * einen Fehler, der vor dem Senden entstand.
670
+ *
671
+ * Seit 1.5.1 fuehrt der Transport jeden Aufruf mit Wirkung als unklar
672
+ * (`UNKNOWN_OUTCOME_CALLS`, eine Obermenge dieser Liste), und
673
+ * [messageOutcome] folgt zuerst ihm. Die Liste bleibt als Vertrag der
674
+ * Kassentexte (`callsWithEffect` in `fixtures/pos-texts.json`) unveraendert.
670
675
  */
671
676
  export declare const CALLS_WITH_EFFECT: readonly ["createReceipt", "cancelReceipt", "financeWebService", "hobexPayApi", "hobexRefundApi", "stripeCaptureIntent", "createPrintJob", "sendReceiptEmail"];
672
677
  /**
@@ -378,12 +378,17 @@ function findErrorRule(kind, detail = {}) {
378
378
  }
379
379
  /**
380
380
  * Kassen-Aufrufe mit Wirkung, die sich nach einem Netzfehler nicht gefahrlos
381
- * wiederholen lassen: die sechs, deren Ausgang das Paket selbst als unklar
382
- * fuehrt (Beleg, auch Null- und Startbeleg ueber `createReceipt`, Storno,
383
- * FinanzOnline, die drei Geldwege), dazu der Druckjob (zweiter Bon) und die
384
- * Belegmail (zweite Mail). Ob die Anfrage vor dem Abriss schon draussen war,
385
- * sieht das Paket nicht (fetch wirft in beiden Faellen gleich); darum gilt
386
- * hier immer der vorsichtige Satz.
381
+ * wiederholen lassen: Beleg (auch Null- und Startbeleg ueber
382
+ * `createReceipt`), Storno, FinanzOnline, die drei Geldwege, der Druckjob
383
+ * (zweiter Bon) und die Belegmail (zweite Mail). Ob die Anfrage vor dem
384
+ * Abriss schon draussen war, sieht das Paket nicht (fetch wirft in beiden
385
+ * Faellen gleich); darum gilt hier immer der vorsichtige Satz, auch fuer
386
+ * einen Fehler, der vor dem Senden entstand.
387
+ *
388
+ * Seit 1.5.1 fuehrt der Transport jeden Aufruf mit Wirkung als unklar
389
+ * (`UNKNOWN_OUTCOME_CALLS`, eine Obermenge dieser Liste), und
390
+ * [messageOutcome] folgt zuerst ihm. Die Liste bleibt als Vertrag der
391
+ * Kassentexte (`callsWithEffect` in `fixtures/pos-texts.json`) unveraendert.
387
392
  */
388
393
  exports.CALLS_WITH_EFFECT = Object.freeze([
389
394
  'createReceipt',
@@ -4,4 +4,4 @@
4
4
  * Client-Version, Nachtrag §6). Ein Test haelt sie gleich mit `package.json`;
5
5
  * beim Anheben der Version beide Stellen aendern.
6
6
  */
7
- export declare const PACKAGE_VERSION = "1.5.0";
7
+ export declare const PACKAGE_VERSION = "1.5.1";
@@ -7,4 +7,4 @@ exports.PACKAGE_VERSION = void 0;
7
7
  * Client-Version, Nachtrag §6). Ein Test haelt sie gleich mit `package.json`;
8
8
  * beim Anheben der Version beide Stellen aendern.
9
9
  */
10
- exports.PACKAGE_VERSION = '1.5.0';
10
+ exports.PACKAGE_VERSION = '1.5.1';
@@ -12,7 +12,7 @@
12
12
  * weiterhin jeden `string`: wer einen Aufruf braucht, den dieses Paket nicht
13
13
  * umhuellt, muss ihn weiterhin absetzen koennen.
14
14
  */
15
- import type { TransportBodyFields } from './transport.js';
15
+ import type { TransportBodyFields, TransportCallOptions } from './transport.js';
16
16
  export declare const ALL_CALLS: readonly ["activateCashregister", "cancelInvoice", "cancelReceipt", "createCreditNote", "createCustomer", "createCustomerCashregister", "createPartnerCustomer", "checkPartnerCustomerEmail", "createPartnerWebhook", "createPaymentLinkStripe", "createPrintJob", "createReceipt", "deletePartnerWebhook", "downloadDailyReport", "downloadReport", "endRegisterSession", "financeWebService", "generateFullReceiptId", "getCustomer", "getCustomerCredentials", "getCustomerSignatureStatus", "getFirstReceiptDate", "getInvoice", "getInvoicePdf", "getInvoiceSetupStatus", "getInvoiceXml", "getKasseSettings", "getPartnerCustomer", "getPartnerInfo", "getPrintJob", "getReceipt", "getReportV2", "hobexPayApi", "hobexRefundApi", "issueInvoice", "listCustomerCashregisters", "listInvoices", "listBrands", "listMyArticleGroups", "listMyArticles", "listMyCashregisters", "listMyPrinters", "listMyReceipts", "listMyStock", "listMyStockLocations", "listMyTipRecipients", "listPartnerCustomers", "listPartnerWebhookDeliveries", "listPartnerWebhooks", "listRegisterUsersForDevice", "listRegisterSessionsForDevice", "pairRegisterDevice", "recordInvoicePayment", "registerPinLogin", "registerUserLogin", "renewRegisterSession", "reportCustomerContract", "requestCustomerSignature", "searchCustomers", "sendPartnerCustomerFonLink", "sendPartnerWebhookTest", "sendReceiptEmail", "setMyCashregisterStockLocation", "setMyKasseLogo", "setMyKasseSettings", "setMyRegisterDeviceSettings", "stripeCaptureIntent", "unpairRegisterDevice", "rotatePartnerWebhookSecret", "updateCustomer", "updatePartnerWebhook", "getArticle", "listArticles", "lookupArticleByCode", "listLocations", "getStock", "listStock", "listStockMovements", "createWebhook", "updateWebhook", "deleteWebhook", "listWebhooks", "sendWebhookTest", "rotateWebhookSecret", "listWebhookDeliveries", "createArticle", "updateArticle", "deactivateArticle", "receiveGoods", "transferStock", "recordStockLoss", "changeStockCondition", "reverseStockMovement", "createReservation", "extendReservation", "releaseReservation", "getReservation", "listReservations"];
17
17
  export type ApiCall = typeof ALL_CALLS[number];
18
18
  /**
@@ -31,6 +31,60 @@ export declare const PUBLIC_CALLS: readonly ["createReceipt", "getReceipt", "can
31
31
  export declare const POS_CALLS: readonly ["pairRegisterDevice", "listRegisterUsersForDevice", "listRegisterSessionsForDevice", "registerUserLogin", "registerPinLogin", "renewRegisterSession", "endRegisterSession", "unpairRegisterDevice", "listMyCashregisters", "listMyReceipts", "getReceipt", "createReceipt", "generateFullReceiptId", "cancelReceipt", "sendReceiptEmail", "listMyArticleGroups", "listMyArticles", "getKasseSettings", "setMyKasseSettings", "setMyKasseLogo", "setMyRegisterDeviceSettings", "listMyPrinters", "createPrintJob", "getPrintJob", "listMyTipRecipients", "listMyStockLocations", "listMyStock", "setMyCashregisterStockLocation"];
32
32
  export type PublicCall = typeof PUBLIC_CALLS[number];
33
33
  export type PosCall = typeof POS_CALLS[number];
34
+ /**
35
+ * Die Aufrufe **mit Wirkung**, alphabetisch: sie legen etwas an, aendern oder
36
+ * loeschen es, buchen, signieren, bewegen Geld oder senden etwas hinaus
37
+ * (Mail, Druckjob, Probesendung). Scheitert einer, nachdem die Anfrage
38
+ * unterwegs war (Netzfehler, Zeitlimit, HTTP 5xx, unlesbare Erfolgsantwort,
39
+ * HTML mit Kennzeichen), meldet der Transport `outcome: 'unknown'`: der
40
+ * Vorgang kann ausgefuehrt sein.
41
+ *
42
+ * Bis 1.5.0 galt das nur fuer die sechs signierenden und geldbewegenden
43
+ * Aufrufe; ein Wareneingang oder eine Rechnung nach einem Zeitlimit kam als
44
+ * `'rejected'` an, und wer das glaubte und mit NEUEM Idempotenzschluessel
45
+ * neu sendete, buchte doppelt.
46
+ *
47
+ * Geht als `unknownOutcomeCalls` in den Vertrag (`fixtures/surface.json`);
48
+ * der Dart-Zwilling prueft seine Liste dagegen. Jeder Aufruf aus
49
+ * [ALL_CALLS], [PUBLIC_CALLS] und [POS_CALLS] steht entweder hier oder in
50
+ * [CALLS_WITHOUT_EFFECT] (Waechter `test/ausgang-einordnung.test.ts`).
51
+ */
52
+ export declare const UNKNOWN_OUTCOME_CALLS: readonly ["activateCashregister", "cancelInvoice", "cancelReceipt", "changeStockCondition", "createArticle", "createCreditNote", "createCustomer", "createCustomerCashregister", "createInvoiceItem", "createPartnerCustomer", "createPartnerWebhook", "createPrintJob", "createReceipt", "createReservation", "createWebhook", "deactivateArticle", "deletePartnerWebhook", "deleteWebhook", "extendReservation", "financeWebService", "hobexPayApi", "hobexRefundApi", "issueInvoice", "pairRegisterDevice", "receiveGoods", "recordInvoicePayment", "recordStockLoss", "releaseReservation", "reportCustomerContract", "requestCustomerSignature", "reverseStockMovement", "revokeCustomerMandate", "rotatePartnerWebhookSecret", "rotateWebhookSecret", "sendPartnerCustomerFonLink", "sendPartnerWebhookTest", "sendReceiptEmail", "sendWebhookTest", "setCustomerMandate", "setMyCashregisterStockLocation", "setMyKasseLogo", "setMyKasseSettings", "setMyRegisterDeviceSettings", "stripeCaptureIntent", "transferStock", "unpairRegisterDevice", "updateArticle", "updateCustomer", "updateInvoiceItem", "updatePartnerWebhook", "updateWebhook", "withdrawInvoiceItem"];
53
+ /** Warum ein Aufruf keine Wirkung hat, die ein Zeitlimit offen lassen koennte. */
54
+ export type CallWithoutEffectReason = 'read' | 'repeatable';
55
+ /**
56
+ * Die Aufrufe **ohne Wirkung**, je mit Grund. Bei ihnen bleibt es bei
57
+ * `outcome: 'rejected'`, auch nach Zeitlimit, Netzfehler oder HTTP 5xx; eine
58
+ * Wiederholung bucht nichts doppelt:
59
+ *
60
+ * - `read`: reines Lesen (auch Berichte, Dateien, `generateFullReceiptId`,
61
+ * das nur einen Link-Schluessel ableitet, und `getCustomerCredentials`,
62
+ * dessen Abruf das Backend nur mitschreibt).
63
+ * - `repeatable`: legt etwas an, das ohne die verlorene Antwort niemand
64
+ * erreicht und das von selbst verfaellt, und bucht nichts. Die Sitzung der
65
+ * Kassen-Anmeldung (anmelden, verlaengern, abmelden: eine Wiederholung legt
66
+ * hoechstens eine weitere kurzlebige Sitzung an bzw. verlaengert oder
67
+ * beendet dieselbe noch einmal) und der Stripe-Zahlungslink
68
+ * (`createPaymentLinkStripe`: den Link kennt nur die Antwort, ein nie
69
+ * zugestellter Link wird nie bezahlt; Geld bewegt erst die Zahlung bzw.
70
+ * `stripeCaptureIntent`).
71
+ *
72
+ * Probelaeufe (`previewGoodsReceipt`, `previewInvoice`) teilen den Namen mit
73
+ * dem echten Aufruf und stehen darum nicht hier; die Huellen setzen fuer sie
74
+ * `hasEffect: false` beim Aufruf, das nur zusammen mit `dryRun: true` gilt
75
+ * (siehe `TransportCallOptions`).
76
+ *
77
+ * Paketintern; nicht Teil der Paketoberflaeche.
78
+ */
79
+ export declare const CALLS_WITHOUT_EFFECT: Readonly<Record<string, CallWithoutEffectReason>>;
80
+ /**
81
+ * Hat dieser Aufruf Wirkung, ist sein Ausgang nach Zeitlimit, Netzfehler,
82
+ * HTTP 5xx oder unlesbarer Erfolgsantwort also unklar? `financeWebService`
83
+ * zaehlt mit jedem Vorgang. Ein Name, den dieses Paket nicht kennt (der
84
+ * offene Transport nimmt jeden), ist `false`; wer so einen Aufruf mit Wirkung
85
+ * absetzt, sagt es mit `hasEffect: true`.
86
+ */
87
+ export declare function isUnknownOutcomeCall(name: string): boolean;
34
88
  /** Einer der 28 Aufrufe des Kassenwegs. */
35
89
  export declare function isPosCall(name: string): boolean;
36
90
  /**
@@ -40,6 +94,6 @@ export declare function isPosCall(name: string): boolean;
40
94
  */
41
95
  export declare function isPosOnlyCall(name: string): boolean;
42
96
  /** Wie [KasseneckTransport], nur mit bekanntem Aufrufnamen. Nicht exportiert nach aussen. */
43
- export type InternerTransport = <T = unknown>(functionName: ApiCall, params?: Record<string, unknown>, extraBodyFields?: TransportBodyFields, secretParams?: readonly string[]) => Promise<T>;
97
+ export type InternerTransport = <T = unknown>(functionName: ApiCall, params?: Record<string, unknown>, extraBodyFields?: TransportBodyFields, secretParams?: readonly string[], options?: TransportCallOptions) => Promise<T>;
44
98
  /** Wie [KasseneckBinaryTransport], nur mit bekanntem Aufrufnamen. */
45
99
  export type InternerBinaerTransport = (functionName: ApiCall, params?: Record<string, unknown>) => Promise<Uint8Array>;