@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.
- package/CHANGELOG.md +58 -0
- package/README.md +64 -26
- package/dist/cjs/client/aufrufe.d.ts +56 -2
- package/dist/cjs/client/aufrufe.js +168 -1
- package/dist/cjs/client/errors.d.ts +32 -19
- package/dist/cjs/client/errors.js +28 -17
- package/dist/cjs/client/index.d.ts +2 -2
- package/dist/cjs/client/index.js +2 -1
- package/dist/cjs/client/transport.d.ts +27 -1
- package/dist/cjs/client/transport.js +25 -27
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js +3 -2
- package/dist/cjs/inventory/schreiben.d.ts +3 -0
- package/dist/cjs/inventory/schreiben.js +6 -1
- package/dist/cjs/invoice/endpunkte.d.ts +6 -0
- package/dist/cjs/invoice/endpunkte.js +13 -2
- package/dist/cjs/pos/texte.d.ts +11 -6
- package/dist/cjs/pos/texte.js +11 -6
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/client/aufrufe.d.ts +56 -2
- package/dist/esm/client/aufrufe.js +166 -0
- package/dist/esm/client/errors.d.ts +32 -19
- package/dist/esm/client/errors.js +28 -17
- package/dist/esm/client/index.d.ts +2 -2
- package/dist/esm/client/index.js +1 -1
- package/dist/esm/client/transport.d.ts +27 -1
- package/dist/esm/client/transport.js +26 -28
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/inventory/schreiben.d.ts +3 -0
- package/dist/esm/inventory/schreiben.js +6 -1
- package/dist/esm/invoice/endpunkte.d.ts +6 -0
- package/dist/esm/invoice/endpunkte.js +13 -2
- package/dist/esm/pos/texte.d.ts +11 -6
- package/dist/esm/pos/texte.js +11 -6
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/fixtures/hobex-hps-codes.json +1 -1
- package/fixtures/invoice-api.schema.json +1 -1
- package/fixtures/invoice-texts.json +1 -1
- package/fixtures/pos-texts.json +1 -1
- package/fixtures/surface.json +55 -1
- package/package.json +1 -1
|
@@ -237,6 +237,172 @@ export const POS_CALLS = [
|
|
|
237
237
|
'listMyStock',
|
|
238
238
|
'setMyCashregisterStockLocation',
|
|
239
239
|
];
|
|
240
|
+
/**
|
|
241
|
+
* Die Aufrufe **mit Wirkung**, alphabetisch: sie legen etwas an, aendern oder
|
|
242
|
+
* loeschen es, buchen, signieren, bewegen Geld oder senden etwas hinaus
|
|
243
|
+
* (Mail, Druckjob, Probesendung). Scheitert einer, nachdem die Anfrage
|
|
244
|
+
* unterwegs war (Netzfehler, Zeitlimit, HTTP 5xx, unlesbare Erfolgsantwort,
|
|
245
|
+
* HTML mit Kennzeichen), meldet der Transport `outcome: 'unknown'`: der
|
|
246
|
+
* Vorgang kann ausgefuehrt sein.
|
|
247
|
+
*
|
|
248
|
+
* Bis 1.5.0 galt das nur fuer die sechs signierenden und geldbewegenden
|
|
249
|
+
* Aufrufe; ein Wareneingang oder eine Rechnung nach einem Zeitlimit kam als
|
|
250
|
+
* `'rejected'` an, und wer das glaubte und mit NEUEM Idempotenzschluessel
|
|
251
|
+
* neu sendete, buchte doppelt.
|
|
252
|
+
*
|
|
253
|
+
* Geht als `unknownOutcomeCalls` in den Vertrag (`fixtures/surface.json`);
|
|
254
|
+
* der Dart-Zwilling prueft seine Liste dagegen. Jeder Aufruf aus
|
|
255
|
+
* [ALL_CALLS], [PUBLIC_CALLS] und [POS_CALLS] steht entweder hier oder in
|
|
256
|
+
* [CALLS_WITHOUT_EFFECT] (Waechter `test/ausgang-einordnung.test.ts`).
|
|
257
|
+
*/
|
|
258
|
+
export const UNKNOWN_OUTCOME_CALLS = [
|
|
259
|
+
'activateCashregister',
|
|
260
|
+
'cancelInvoice',
|
|
261
|
+
'cancelReceipt',
|
|
262
|
+
'changeStockCondition',
|
|
263
|
+
'createArticle',
|
|
264
|
+
'createCreditNote',
|
|
265
|
+
'createCustomer',
|
|
266
|
+
'createCustomerCashregister',
|
|
267
|
+
'createInvoiceItem',
|
|
268
|
+
'createPartnerCustomer',
|
|
269
|
+
'createPartnerWebhook',
|
|
270
|
+
'createPrintJob',
|
|
271
|
+
'createReceipt',
|
|
272
|
+
'createReservation',
|
|
273
|
+
'createWebhook',
|
|
274
|
+
'deactivateArticle',
|
|
275
|
+
'deletePartnerWebhook',
|
|
276
|
+
'deleteWebhook',
|
|
277
|
+
'extendReservation',
|
|
278
|
+
'financeWebService',
|
|
279
|
+
'hobexPayApi',
|
|
280
|
+
'hobexRefundApi',
|
|
281
|
+
'issueInvoice',
|
|
282
|
+
'pairRegisterDevice',
|
|
283
|
+
'receiveGoods',
|
|
284
|
+
'recordInvoicePayment',
|
|
285
|
+
'recordStockLoss',
|
|
286
|
+
'releaseReservation',
|
|
287
|
+
'reportCustomerContract',
|
|
288
|
+
'requestCustomerSignature',
|
|
289
|
+
'reverseStockMovement',
|
|
290
|
+
'revokeCustomerMandate',
|
|
291
|
+
'rotatePartnerWebhookSecret',
|
|
292
|
+
'rotateWebhookSecret',
|
|
293
|
+
'sendPartnerCustomerFonLink',
|
|
294
|
+
'sendPartnerWebhookTest',
|
|
295
|
+
'sendReceiptEmail',
|
|
296
|
+
'sendWebhookTest',
|
|
297
|
+
'setCustomerMandate',
|
|
298
|
+
'setMyCashregisterStockLocation',
|
|
299
|
+
'setMyKasseLogo',
|
|
300
|
+
'setMyKasseSettings',
|
|
301
|
+
'setMyRegisterDeviceSettings',
|
|
302
|
+
'stripeCaptureIntent',
|
|
303
|
+
'transferStock',
|
|
304
|
+
'unpairRegisterDevice',
|
|
305
|
+
'updateArticle',
|
|
306
|
+
'updateCustomer',
|
|
307
|
+
'updateInvoiceItem',
|
|
308
|
+
'updatePartnerWebhook',
|
|
309
|
+
'updateWebhook',
|
|
310
|
+
'withdrawInvoiceItem',
|
|
311
|
+
];
|
|
312
|
+
/**
|
|
313
|
+
* Die Aufrufe **ohne Wirkung**, je mit Grund. Bei ihnen bleibt es bei
|
|
314
|
+
* `outcome: 'rejected'`, auch nach Zeitlimit, Netzfehler oder HTTP 5xx; eine
|
|
315
|
+
* Wiederholung bucht nichts doppelt:
|
|
316
|
+
*
|
|
317
|
+
* - `read`: reines Lesen (auch Berichte, Dateien, `generateFullReceiptId`,
|
|
318
|
+
* das nur einen Link-Schluessel ableitet, und `getCustomerCredentials`,
|
|
319
|
+
* dessen Abruf das Backend nur mitschreibt).
|
|
320
|
+
* - `repeatable`: legt etwas an, das ohne die verlorene Antwort niemand
|
|
321
|
+
* erreicht und das von selbst verfaellt, und bucht nichts. Die Sitzung der
|
|
322
|
+
* Kassen-Anmeldung (anmelden, verlaengern, abmelden: eine Wiederholung legt
|
|
323
|
+
* hoechstens eine weitere kurzlebige Sitzung an bzw. verlaengert oder
|
|
324
|
+
* beendet dieselbe noch einmal) und der Stripe-Zahlungslink
|
|
325
|
+
* (`createPaymentLinkStripe`: den Link kennt nur die Antwort, ein nie
|
|
326
|
+
* zugestellter Link wird nie bezahlt; Geld bewegt erst die Zahlung bzw.
|
|
327
|
+
* `stripeCaptureIntent`).
|
|
328
|
+
*
|
|
329
|
+
* Probelaeufe (`previewGoodsReceipt`, `previewInvoice`) teilen den Namen mit
|
|
330
|
+
* dem echten Aufruf und stehen darum nicht hier; die Huellen setzen fuer sie
|
|
331
|
+
* `hasEffect: false` beim Aufruf, das nur zusammen mit `dryRun: true` gilt
|
|
332
|
+
* (siehe `TransportCallOptions`).
|
|
333
|
+
*
|
|
334
|
+
* Paketintern; nicht Teil der Paketoberflaeche.
|
|
335
|
+
*/
|
|
336
|
+
export const CALLS_WITHOUT_EFFECT = Object.freeze({
|
|
337
|
+
checkPartnerCustomerEmail: 'read',
|
|
338
|
+
downloadDailyReport: 'read',
|
|
339
|
+
downloadReceipt: 'read',
|
|
340
|
+
downloadReport: 'read',
|
|
341
|
+
createPaymentLinkStripe: 'repeatable',
|
|
342
|
+
endRegisterSession: 'repeatable',
|
|
343
|
+
generateFullReceiptId: 'read',
|
|
344
|
+
getArticle: 'read',
|
|
345
|
+
getCustomer: 'read',
|
|
346
|
+
getCustomerCredentials: 'read',
|
|
347
|
+
getCustomerSignatureStatus: 'read',
|
|
348
|
+
getFirstReceiptDate: 'read',
|
|
349
|
+
getInvoice: 'read',
|
|
350
|
+
getInvoiceItem: 'read',
|
|
351
|
+
getInvoicePdf: 'read',
|
|
352
|
+
getInvoiceSetupStatus: 'read',
|
|
353
|
+
getInvoiceXml: 'read',
|
|
354
|
+
getKasseSettings: 'read',
|
|
355
|
+
getPartnerBilling: 'read',
|
|
356
|
+
getPartnerBillingMonth: 'read',
|
|
357
|
+
getPartnerCustomer: 'read',
|
|
358
|
+
getPartnerInfo: 'read',
|
|
359
|
+
getPrintJob: 'read',
|
|
360
|
+
getReceipt: 'read',
|
|
361
|
+
getReportV2: 'read',
|
|
362
|
+
getReservation: 'read',
|
|
363
|
+
getStock: 'read',
|
|
364
|
+
hobexGetStatus: 'read',
|
|
365
|
+
listArticles: 'read',
|
|
366
|
+
listBrands: 'read',
|
|
367
|
+
listCustomerCashregisters: 'read',
|
|
368
|
+
listInvoiceItems: 'read',
|
|
369
|
+
listInvoices: 'read',
|
|
370
|
+
listLocations: 'read',
|
|
371
|
+
listMyArticleGroups: 'read',
|
|
372
|
+
listMyArticles: 'read',
|
|
373
|
+
listMyCashregisters: 'read',
|
|
374
|
+
listMyPrinters: 'read',
|
|
375
|
+
listMyReceipts: 'read',
|
|
376
|
+
listMyStock: 'read',
|
|
377
|
+
listMyStockLocations: 'read',
|
|
378
|
+
listMyTipRecipients: 'read',
|
|
379
|
+
listPartnerCustomers: 'read',
|
|
380
|
+
listPartnerWebhookDeliveries: 'read',
|
|
381
|
+
listPartnerWebhooks: 'read',
|
|
382
|
+
listRegisterSessionsForDevice: 'read',
|
|
383
|
+
listRegisterUsersForDevice: 'read',
|
|
384
|
+
listReservations: 'read',
|
|
385
|
+
listStock: 'read',
|
|
386
|
+
listStockMovements: 'read',
|
|
387
|
+
listWebhookDeliveries: 'read',
|
|
388
|
+
listWebhooks: 'read',
|
|
389
|
+
lookupArticleByCode: 'read',
|
|
390
|
+
registerPinLogin: 'repeatable',
|
|
391
|
+
registerUserLogin: 'repeatable',
|
|
392
|
+
renewRegisterSession: 'repeatable',
|
|
393
|
+
searchCustomers: 'read',
|
|
394
|
+
});
|
|
395
|
+
const MIT_WIRKUNG = new Set(UNKNOWN_OUTCOME_CALLS);
|
|
396
|
+
/**
|
|
397
|
+
* Hat dieser Aufruf Wirkung, ist sein Ausgang nach Zeitlimit, Netzfehler,
|
|
398
|
+
* HTTP 5xx oder unlesbarer Erfolgsantwort also unklar? `financeWebService`
|
|
399
|
+
* zaehlt mit jedem Vorgang. Ein Name, den dieses Paket nicht kennt (der
|
|
400
|
+
* offene Transport nimmt jeden), ist `false`; wer so einen Aufruf mit Wirkung
|
|
401
|
+
* absetzt, sagt es mit `hasEffect: true`.
|
|
402
|
+
*/
|
|
403
|
+
export function isUnknownOutcomeCall(name) {
|
|
404
|
+
return MIT_WIRKUNG.has(name);
|
|
405
|
+
}
|
|
240
406
|
const OEFFENTLICH = new Set(PUBLIC_CALLS);
|
|
241
407
|
const KASSENWEG = new Set(POS_CALLS);
|
|
242
408
|
const NUR_KASSE = new Set(POS_CALLS.filter((name) => !OEFFENTLICH.has(name)));
|
|
@@ -25,20 +25,27 @@
|
|
|
25
25
|
* **Entscheidend ist `outcome`:** `'rejected'` heisst abgelehnt, nichts
|
|
26
26
|
* geschehen, Wiederholen hilft nicht. `'unknown'` heisst: der Vorgang kann
|
|
27
27
|
* ausgefuehrt sein (bei `createReceipt` ein signierter Beleg). Dann **nie
|
|
28
|
-
* wiederholen
|
|
28
|
+
* blind wiederholen**: Belege, Stornos und Zahlungen nachlesen
|
|
29
|
+
* (Belegliste, `getReceipt`, Terminal-Beleg); ein Aufruf mit
|
|
30
|
+
* `idempotencyKey` (Lager schreiben, Rechnung, Partner-Betrieb mit
|
|
31
|
+
* Schluessel) darf mit **demselben** Schluessel erneut gesendet werden und
|
|
32
|
+
* wirkt genau einmal, nie mit einem neuen. `createInvoiceItem` erkennt die
|
|
33
|
+
* Wiederholung an `source` + `reference` (dieselben Werte erneut senden);
|
|
34
|
+
* Posten aendern oder zurueckziehen und Mandate haben keinen Schluessel:
|
|
35
|
+
* erst nachlesen.
|
|
29
36
|
* - `KasseneckHttpError` — die Antwort war **keine** verwertbare Huelle:
|
|
30
37
|
* HTTP 500/404 ohne Huelle, leerer Rumpf oder Text statt JSON. Beim
|
|
31
38
|
* Bericht-Download gelten dieselben Gruende fuer alles, was kein PDF ist.
|
|
32
39
|
* `reason` trennt die Faelle maschinenlesbar. Auf einem Aufruf mit
|
|
33
|
-
* Wirkung (
|
|
40
|
+
* Wirkung (`UNKNOWN_OUTCOME_CALLS` in aufrufe.ts) hat HTTP 5xx
|
|
34
41
|
* `outcome: 'unknown'`, ebenso HTTP 200 mit Kennzeichen, aber leerem oder
|
|
35
42
|
* unlesbarem Rumpf.
|
|
36
43
|
* - `KasseneckNetworkError` — die Antwort kam gar nicht: Netz weg, DNS,
|
|
37
44
|
* abgebrochene Verbindung oder Zeitueberschreitung (`timedOut`). Auch hier
|
|
38
45
|
* gilt `outcome`: war die Anfrage schon unterwegs und ist der Aufruf einer
|
|
39
|
-
* mit Wirkung (
|
|
40
|
-
*
|
|
41
|
-
* `
|
|
46
|
+
* mit Wirkung (signieren, Geld bewegen, buchen, ausstellen, anlegen,
|
|
47
|
+
* aendern, loeschen, senden; die Liste `UNKNOWN_OUTCOME_CALLS`), ist er
|
|
48
|
+
* `'unknown'`. Lesen und Probelauf bleiben `'rejected'`.
|
|
42
49
|
* - `KasseneckAuthError` — es kam nicht einmal zur Anfrage, weil die Anmeldung
|
|
43
50
|
* scheiterte (fehlende Zugangsdaten, oder der Token-/Sitzungsgeber warf).
|
|
44
51
|
* In der Browser-Kasse mit ihrer 90-Sekunden-Sitzung ist das Alltag, kein
|
|
@@ -106,8 +113,10 @@ export declare function causeDigest(ursache: unknown, geheimnisse: readonly stri
|
|
|
106
113
|
export declare function fehlerDetails(daten: unknown, geheimnisse: readonly string[]): Record<string, unknown>;
|
|
107
114
|
/**
|
|
108
115
|
* Ausgang eines gescheiterten Aufrufs. `'rejected'`: nichts geschehen.
|
|
109
|
-
* `'unknown'`: der Vorgang kann ausgefuehrt sein; nie wiederholen
|
|
110
|
-
*
|
|
116
|
+
* `'unknown'`: der Vorgang kann ausgefuehrt sein; nie blind wiederholen.
|
|
117
|
+
* Belege, Stornos und Zahlungen nachlesen; ein Aufruf mit `idempotencyKey`
|
|
118
|
+
* nur mit **demselben** Schluessel erneut senden (wirkt genau einmal); ohne
|
|
119
|
+
* Schluessel erst nachlesen.
|
|
111
120
|
*/
|
|
112
121
|
export type ErrorOutcome = 'unknown' | 'rejected';
|
|
113
122
|
/**
|
|
@@ -195,12 +204,12 @@ export declare class KasseneckHttpError extends Error {
|
|
|
195
204
|
/** Maschinenlesbarer Grund — trennt den Rewrite-Fall vom 500er ohne Textparsen. */
|
|
196
205
|
readonly reason: HttpFailureReason;
|
|
197
206
|
/**
|
|
198
|
-
* `'unknown'` auf einem Aufruf mit Wirkung (`
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
207
|
+
* `'unknown'` auf einem Aufruf mit Wirkung (`UNKNOWN_OUTCOME_CALLS`:
|
|
208
|
+
* signieren, Geld bewegen, buchen, ausstellen, anlegen, aendern, loeschen,
|
|
209
|
+
* senden) bei HTTP 5xx und bei HTTP 200 mit Kennzeichen, aber unlesbarem
|
|
210
|
+
* Rumpf (`empty-body`, `not-json` auch bei `text/html`, `missing-status`):
|
|
211
|
+
* der Handler kann gelaufen sein, nie blind wiederholen (siehe
|
|
212
|
+
* [ErrorOutcome]). Sonst `'rejected'` (auch 4xx, Lesen und Probelauf).
|
|
204
213
|
*/
|
|
205
214
|
readonly outcome: ErrorOutcome;
|
|
206
215
|
constructor(functionName: string, statusCode: number, contentType: string | undefined, reason: HttpFailureReason, outcome?: ErrorOutcome);
|
|
@@ -218,9 +227,10 @@ export declare class KasseneckNetworkError extends Error {
|
|
|
218
227
|
/** Code der zugrunde liegenden Ursache, sofern unbedenklich (z. B. `ECONNREFUSED`). */
|
|
219
228
|
readonly causeCode: string | undefined;
|
|
220
229
|
/**
|
|
221
|
-
* `'unknown'`, wenn die Anfrage schon unterwegs war und der Aufruf
|
|
222
|
-
* (`
|
|
223
|
-
*
|
|
230
|
+
* `'unknown'`, wenn die Anfrage schon unterwegs war und der Aufruf Wirkung
|
|
231
|
+
* hat (`UNKNOWN_OUTCOME_CALLS`): dann nie blind wiederholen (siehe
|
|
232
|
+
* [ErrorOutcome]). Sonst `'rejected'`, auch bei Lesen und Probelauf und
|
|
233
|
+
* wenn schon die Anmeldung das Zeitlimit verbrauchte.
|
|
224
234
|
*/
|
|
225
235
|
readonly outcome: ErrorOutcome;
|
|
226
236
|
constructor(functionName: string, timedOut: boolean, timeoutMs: number, cause?: CauseDigest, outcome?: ErrorOutcome);
|
|
@@ -273,9 +283,12 @@ export declare class KasseneckValidationError extends Error {
|
|
|
273
283
|
export type KasseneckError = KasseneckApiError | KasseneckHttpError | KasseneckNetworkError | KasseneckAuthError | KasseneckValidationError;
|
|
274
284
|
/**
|
|
275
285
|
* Ist der Ausgang dieses Fehlers unklar (`outcome === 'unknown'`)? Dann den
|
|
276
|
-
* Aufruf **nicht wiederholen
|
|
277
|
-
*
|
|
278
|
-
*
|
|
286
|
+
* Aufruf **nicht blind wiederholen**: Belege, Stornos und Zahlungen
|
|
287
|
+
* nachlesen; einen Aufruf mit `idempotencyKey` nur mit **demselben**
|
|
288
|
+
* Schluessel erneut senden (wirkt genau einmal, ein neuer buchte doppelt);
|
|
289
|
+
* ohne Schluessel erst nachlesen. Gilt fuer jede Fehlerart; nur
|
|
290
|
+
* [KasseneckApiError], [KasseneckHttpError] und [KasseneckNetworkError]
|
|
291
|
+
* koennen `'unknown'` sein.
|
|
279
292
|
*/
|
|
280
293
|
export declare function isOutcomeUnknown(error: unknown): boolean;
|
|
281
294
|
export declare function isKasseneckApiError(error: unknown): error is KasseneckApiError;
|
|
@@ -25,20 +25,27 @@
|
|
|
25
25
|
* **Entscheidend ist `outcome`:** `'rejected'` heisst abgelehnt, nichts
|
|
26
26
|
* geschehen, Wiederholen hilft nicht. `'unknown'` heisst: der Vorgang kann
|
|
27
27
|
* ausgefuehrt sein (bei `createReceipt` ein signierter Beleg). Dann **nie
|
|
28
|
-
* wiederholen
|
|
28
|
+
* blind wiederholen**: Belege, Stornos und Zahlungen nachlesen
|
|
29
|
+
* (Belegliste, `getReceipt`, Terminal-Beleg); ein Aufruf mit
|
|
30
|
+
* `idempotencyKey` (Lager schreiben, Rechnung, Partner-Betrieb mit
|
|
31
|
+
* Schluessel) darf mit **demselben** Schluessel erneut gesendet werden und
|
|
32
|
+
* wirkt genau einmal, nie mit einem neuen. `createInvoiceItem` erkennt die
|
|
33
|
+
* Wiederholung an `source` + `reference` (dieselben Werte erneut senden);
|
|
34
|
+
* Posten aendern oder zurueckziehen und Mandate haben keinen Schluessel:
|
|
35
|
+
* erst nachlesen.
|
|
29
36
|
* - `KasseneckHttpError` — die Antwort war **keine** verwertbare Huelle:
|
|
30
37
|
* HTTP 500/404 ohne Huelle, leerer Rumpf oder Text statt JSON. Beim
|
|
31
38
|
* Bericht-Download gelten dieselben Gruende fuer alles, was kein PDF ist.
|
|
32
39
|
* `reason` trennt die Faelle maschinenlesbar. Auf einem Aufruf mit
|
|
33
|
-
* Wirkung (
|
|
40
|
+
* Wirkung (`UNKNOWN_OUTCOME_CALLS` in aufrufe.ts) hat HTTP 5xx
|
|
34
41
|
* `outcome: 'unknown'`, ebenso HTTP 200 mit Kennzeichen, aber leerem oder
|
|
35
42
|
* unlesbarem Rumpf.
|
|
36
43
|
* - `KasseneckNetworkError` — die Antwort kam gar nicht: Netz weg, DNS,
|
|
37
44
|
* abgebrochene Verbindung oder Zeitueberschreitung (`timedOut`). Auch hier
|
|
38
45
|
* gilt `outcome`: war die Anfrage schon unterwegs und ist der Aufruf einer
|
|
39
|
-
* mit Wirkung (
|
|
40
|
-
*
|
|
41
|
-
* `
|
|
46
|
+
* mit Wirkung (signieren, Geld bewegen, buchen, ausstellen, anlegen,
|
|
47
|
+
* aendern, loeschen, senden; die Liste `UNKNOWN_OUTCOME_CALLS`), ist er
|
|
48
|
+
* `'unknown'`. Lesen und Probelauf bleiben `'rejected'`.
|
|
42
49
|
* - `KasseneckAuthError` — es kam nicht einmal zur Anfrage, weil die Anmeldung
|
|
43
50
|
* scheiterte (fehlende Zugangsdaten, oder der Token-/Sitzungsgeber warf).
|
|
44
51
|
* In der Browser-Kasse mit ihrer 90-Sekunden-Sitzung ist das Alltag, kein
|
|
@@ -365,12 +372,12 @@ export class KasseneckHttpError extends Error {
|
|
|
365
372
|
/** Maschinenlesbarer Grund — trennt den Rewrite-Fall vom 500er ohne Textparsen. */
|
|
366
373
|
reason;
|
|
367
374
|
/**
|
|
368
|
-
* `'unknown'` auf einem Aufruf mit Wirkung (`
|
|
369
|
-
*
|
|
370
|
-
*
|
|
371
|
-
*
|
|
372
|
-
*
|
|
373
|
-
*
|
|
375
|
+
* `'unknown'` auf einem Aufruf mit Wirkung (`UNKNOWN_OUTCOME_CALLS`:
|
|
376
|
+
* signieren, Geld bewegen, buchen, ausstellen, anlegen, aendern, loeschen,
|
|
377
|
+
* senden) bei HTTP 5xx und bei HTTP 200 mit Kennzeichen, aber unlesbarem
|
|
378
|
+
* Rumpf (`empty-body`, `not-json` auch bei `text/html`, `missing-status`):
|
|
379
|
+
* der Handler kann gelaufen sein, nie blind wiederholen (siehe
|
|
380
|
+
* [ErrorOutcome]). Sonst `'rejected'` (auch 4xx, Lesen und Probelauf).
|
|
374
381
|
*/
|
|
375
382
|
outcome;
|
|
376
383
|
constructor(functionName, statusCode, contentType, reason, outcome = 'rejected') {
|
|
@@ -396,9 +403,10 @@ export class KasseneckNetworkError extends Error {
|
|
|
396
403
|
/** Code der zugrunde liegenden Ursache, sofern unbedenklich (z. B. `ECONNREFUSED`). */
|
|
397
404
|
causeCode;
|
|
398
405
|
/**
|
|
399
|
-
* `'unknown'`, wenn die Anfrage schon unterwegs war und der Aufruf
|
|
400
|
-
* (`
|
|
401
|
-
*
|
|
406
|
+
* `'unknown'`, wenn die Anfrage schon unterwegs war und der Aufruf Wirkung
|
|
407
|
+
* hat (`UNKNOWN_OUTCOME_CALLS`): dann nie blind wiederholen (siehe
|
|
408
|
+
* [ErrorOutcome]). Sonst `'rejected'`, auch bei Lesen und Probelauf und
|
|
409
|
+
* wenn schon die Anmeldung das Zeitlimit verbrauchte.
|
|
402
410
|
*/
|
|
403
411
|
outcome;
|
|
404
412
|
constructor(functionName, timedOut, timeoutMs, cause = {}, outcome = 'rejected') {
|
|
@@ -464,9 +472,12 @@ export class KasseneckValidationError extends Error {
|
|
|
464
472
|
}
|
|
465
473
|
/**
|
|
466
474
|
* Ist der Ausgang dieses Fehlers unklar (`outcome === 'unknown'`)? Dann den
|
|
467
|
-
* Aufruf **nicht wiederholen
|
|
468
|
-
*
|
|
469
|
-
*
|
|
475
|
+
* Aufruf **nicht blind wiederholen**: Belege, Stornos und Zahlungen
|
|
476
|
+
* nachlesen; einen Aufruf mit `idempotencyKey` nur mit **demselben**
|
|
477
|
+
* Schluessel erneut senden (wirkt genau einmal, ein neuer buchte doppelt);
|
|
478
|
+
* ohne Schluessel erst nachlesen. Gilt fuer jede Fehlerart; nur
|
|
479
|
+
* [KasseneckApiError], [KasseneckHttpError] und [KasseneckNetworkError]
|
|
480
|
+
* koennen `'unknown'` sein.
|
|
470
481
|
*/
|
|
471
482
|
export function isOutcomeUnknown(error) {
|
|
472
483
|
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';
|
package/dist/esm/client/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { apiKeyAuth, registerUserAuth, } from './auth.js';
|
|
2
2
|
export { DEFAULT_BASE_URL, POS_BASE_URL, DEFAULT_TIMEOUT_MS, createTransport, createBinaryTransport, } from './transport.js';
|
|
3
|
-
export { ALL_CALLS, PUBLIC_CALLS, POS_CALLS, } from './aufrufe.js';
|
|
3
|
+
export { ALL_CALLS, PUBLIC_CALLS, POS_CALLS, UNKNOWN_OUTCOME_CALLS, } from './aufrufe.js';
|
|
4
4
|
export { KasseneckApiError, KasseneckAuthError, KasseneckHttpError, KasseneckNetworkError, KasseneckValidationError, CLIENT_ERROR_CODES, isKasseneckApiError, isKasseneckAuthError, isKasseneckHttpError, isKasseneckNetworkError, isKasseneckValidationError, isOutcomeUnknown, } from './errors.js';
|
|
5
5
|
export { sellReceipt, sellReceiptWithCompany, paymentsExpectedCents, cardRefundReference, receiptLayoutFromResult, cancelReceipt, zeroReceipt, getReceipt, getReceiptWithCompany, generateFullReceiptId, getFirstReceiptDate, listMyReceipts, checkVoucherCombinationError, sendReceiptEmail, } from './receipts.js';
|
|
6
6
|
export { listMyCashregisters } from './cashregisters.js';
|
|
@@ -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
|
-
|
|
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.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isRegisterUserAuth } from './auth.js';
|
|
2
|
-
import { isPosCall, isPosOnlyCall } from './aufrufe.js';
|
|
2
|
+
import { isPosCall, isPosOnlyCall, isUnknownOutcomeCall } from './aufrufe.js';
|
|
3
3
|
import { PACKAGE_VERSION } from '../version.js';
|
|
4
4
|
import { KasseneckApiError, KasseneckAuthError, KasseneckHttpError, KasseneckNetworkError, KasseneckValidationError, causeDigest, fehlerDetails, } from './errors.js';
|
|
5
5
|
/**
|
|
@@ -36,6 +36,12 @@ import { KasseneckApiError, KasseneckAuthError, KasseneckHttpError, KasseneckNet
|
|
|
36
36
|
* **Kein Wiederholen fehlgeschlagener Aufrufe.** Ein Beleg ist nicht folgenlos
|
|
37
37
|
* wiederholbar; ohne entschiedene Idempotenz waere ein automatischer zweiter
|
|
38
38
|
* Versuch ein zweiter Beleg.
|
|
39
|
+
*
|
|
40
|
+
* **Ausgang je Aufruf.** Ob ein Scheitern nach dem Senden `outcome: 'unknown'`
|
|
41
|
+
* traegt, haengt am Aufruf: mit Wirkung ([UNKNOWN_OUTCOME_CALLS] in
|
|
42
|
+
* aufrufe.ts) ja, Lesen und Probelauf nein. Ein Probelauf traegt denselben
|
|
43
|
+
* Namen wie der echte Aufruf; die Huelle sagt es darum beim Aufruf
|
|
44
|
+
* (`hasEffect: false`, [TransportCallOptions]).
|
|
39
45
|
*/
|
|
40
46
|
/** Basis-URL der oeffentlichen API (Produktion). */
|
|
41
47
|
export const DEFAULT_BASE_URL = 'https://api.kasseneck.at/v3';
|
|
@@ -56,23 +62,6 @@ const VERSION_WERT = 'v3';
|
|
|
56
62
|
const KASSENECK_HOSTS = new Set(['api.kasseneck.at', 'kasse.kasseneck.at']);
|
|
57
63
|
/** Die 1.x-Linie spricht nur `/v3`: jede Basis endet so (`/v3` oder `/api/v3`). */
|
|
58
64
|
const V3_ENDE = /\/v3$/;
|
|
59
|
-
/**
|
|
60
|
-
* Aufrufe mit Wirkung, die nie blind wiederholt werden duerfen: sie signieren
|
|
61
|
-
* (`createReceipt`, `cancelReceipt`), loesen bei FinanzOnline etwas aus
|
|
62
|
-
* (`financeWebService`) oder bewegen Geld (`hobexPayApi` belastet eine Karte,
|
|
63
|
-
* `hobexRefundApi` erstattet, `stripeCaptureIntent` zieht eine vorgemerkte
|
|
64
|
-
* Zahlung ein). Scheitert einer, nachdem die Anfrage unterwegs war (Netz,
|
|
65
|
-
* Zeitlimit, HTTP 5xx, unlesbare Erfolgsantwort, HTML mit Kennzeichen), ist
|
|
66
|
-
* sein Ausgang offen.
|
|
67
|
-
*/
|
|
68
|
-
const UNKNOWN_OUTCOME_CALLS = new Set([
|
|
69
|
-
'createReceipt',
|
|
70
|
-
'cancelReceipt',
|
|
71
|
-
'financeWebService',
|
|
72
|
-
'hobexPayApi',
|
|
73
|
-
'hobexRefundApi',
|
|
74
|
-
'stripeCaptureIntent',
|
|
75
|
-
]);
|
|
76
65
|
/**
|
|
77
66
|
* Produkte, die das Backend in `Kasseneck-Client` zaehlt (Positivliste,
|
|
78
67
|
* Nachtrag §6); alles andere zaehlte dort als `ungueltig`. Das Paket weist
|
|
@@ -89,7 +78,7 @@ const CLIENT_MAX = 64;
|
|
|
89
78
|
export const DEFAULT_TIMEOUT_MS = 30_000;
|
|
90
79
|
export function createTransport(options) {
|
|
91
80
|
const kern = createCore(options);
|
|
92
|
-
return (functionName, params, extraBodyFields, secretParams) => kern(functionName, params, extraBodyFields, secretParams, alsText, jsonAuswerten);
|
|
81
|
+
return (functionName, params, extraBodyFields, secretParams, callOptions) => kern(functionName, params, extraBodyFields, secretParams, callOptions, alsText, jsonAuswerten);
|
|
93
82
|
}
|
|
94
83
|
/**
|
|
95
84
|
* Zweiter Einstiegspunkt fuer die Bericht-Downloads. Er liest die Antwort als
|
|
@@ -101,7 +90,7 @@ export function createTransport(options) {
|
|
|
101
90
|
*/
|
|
102
91
|
export function createBinaryTransport(options) {
|
|
103
92
|
const kern = createCore(options);
|
|
104
|
-
return (functionName, params) => kern(functionName, params, undefined, undefined, alsBytes, pdfAuswerten);
|
|
93
|
+
return (functionName, params) => kern(functionName, params, undefined, undefined, undefined, alsBytes, pdfAuswerten);
|
|
105
94
|
}
|
|
106
95
|
/**
|
|
107
96
|
* Gemeinsamer Kern beider Einstiegspunkte: Anmeldung, Zeitlimit, Anfrage und
|
|
@@ -125,12 +114,21 @@ function createCore(options) {
|
|
|
125
114
|
* (Berichte, Zahlungen, FinanzOnline), geht an die oeffentliche Basis.
|
|
126
115
|
*/
|
|
127
116
|
const basisFuer = (functionName) => isPosOnlyCall(functionName) || (kassenweg && isPosCall(functionName)) ? kassenBasis : oeffentlicheBasis;
|
|
128
|
-
return async function aufrufen(functionName, params = {}, extraBodyFields, secretParams, lesen, auswerten) {
|
|
117
|
+
return async function aufrufen(functionName, params = {}, extraBodyFields, secretParams, callOptions, lesen, auswerten) {
|
|
129
118
|
// Die URL nennt die Backend-Funktion, die Fehler nennen den **Vorgang**:
|
|
130
119
|
// `financeWebService` fuehrt ein Dutzend verschiedener Vorgaenge unter einem
|
|
131
120
|
// Endpunkt, und ein Fehler, der nur "financeWebService" sagt, verschweigt
|
|
132
121
|
// dem Aufrufer, welcher davon scheiterte.
|
|
133
122
|
const fehlerName = extraBodyFields?.method ? `${functionName}/${extraBodyFields.method}` : functionName;
|
|
123
|
+
// Ausgang eines Scheiterns nach dem Senden: offen, wenn der Aufruf Wirkung
|
|
124
|
+
// hat. `hasEffect: true` hebt einen fremden Aufruf auf `unknown`.
|
|
125
|
+
// `hasEffect: false` senkt einen Aufruf mit Wirkung nur, wenn er wirklich
|
|
126
|
+
// ein Probelauf ist (`dryRun === true`, so streng prueft auch das
|
|
127
|
+
// Backend): sonst liefe ein echter Beleg oder eine Buchung nach einem
|
|
128
|
+
// Zeitlimit als `rejected`, und genau das fuehrt zur Doppelbuchung.
|
|
129
|
+
const probelauf = callOptions?.hasEffect === false && params['dryRun'] === true;
|
|
130
|
+
const wirkung = callOptions?.hasEffect === true || (isUnknownOutcomeCall(functionName) && !probelauf);
|
|
131
|
+
const nachDemSenden = wirkung ? 'unknown' : 'rejected';
|
|
134
132
|
// Das Zeitlimit laeuft ab HIER — es deckt die Anmeldung mit ab. Haengt die
|
|
135
133
|
// Token-Erneuerung auf flauem Netz, haette der Aufruf sonst weder Ergebnis
|
|
136
134
|
// noch Fehler, und die Kasse stuende still.
|
|
@@ -170,8 +168,9 @@ function createCore(options) {
|
|
|
170
168
|
}
|
|
171
169
|
// Bis hierher kam keine verwertbare Antwort: Netz weg oder Zeitlimit.
|
|
172
170
|
// Die Anfrage war schon unterwegs: bei einem Aufruf mit Wirkung kann
|
|
173
|
-
// der
|
|
174
|
-
|
|
171
|
+
// der Vorgang ausgefuehrt sein (Beleg, Zahlung, Buchung, Rechnung;
|
|
172
|
+
// Ausgang unklar).
|
|
173
|
+
return new KasseneckNetworkError(fehlerName, abbruch.signal.aborted, zeitlimitMs, causeDigest(ursache, geheimnisse), nachDemSenden);
|
|
175
174
|
};
|
|
176
175
|
const basis = basisFuer(functionName);
|
|
177
176
|
const url = `${basis}/${encodeURIComponent(functionName)}`;
|
|
@@ -225,7 +224,7 @@ function createCore(options) {
|
|
|
225
224
|
throw fehler;
|
|
226
225
|
}
|
|
227
226
|
// 5xx auf einem Aufruf mit Wirkung: der Handler kann gelaufen sein.
|
|
228
|
-
const ausgang = antwort.status >= 500
|
|
227
|
+
const ausgang = antwort.status >= 500 ? nachDemSenden : 'rejected';
|
|
229
228
|
throw new KasseneckHttpError(fehlerName, antwort.status, inhaltstyp, 'server-error', ausgang);
|
|
230
229
|
}
|
|
231
230
|
// HTTP 200 mit HTML: die Auffangregel der Single-Page-App hat den Aufruf
|
|
@@ -233,9 +232,9 @@ function createCore(options) {
|
|
|
233
232
|
if (inhaltstyp !== undefined && /^\s*text\/html\b/i.test(inhaltstyp)) {
|
|
234
233
|
// Mit Kennzeichen hat der `/v3`-Rand den Aufruf gesehen (etwa ein
|
|
235
234
|
// Proxy, der nur den Inhaltstyp umschreibt). Bei einem Aufruf mit
|
|
236
|
-
// Wirkung kann der
|
|
235
|
+
// Wirkung kann der Vorgang dann ausgefuehrt sein: unlesbarer Rumpf,
|
|
237
236
|
// Ausgang unklar, statt `route_missing`.
|
|
238
|
-
if (
|
|
237
|
+
if (nachDemSenden === 'unknown' && traegtKennzeichen(antwort)) {
|
|
239
238
|
throw new KasseneckHttpError(fehlerName, antwort.status, inhaltstyp, 'not-json', 'unknown');
|
|
240
239
|
}
|
|
241
240
|
throw new KasseneckApiError(fehlerName, 'Route fehlt: die Antwort ist eine HTML-Seite statt des Backends', {}, 'route_missing');
|
|
@@ -253,8 +252,7 @@ function createCore(options) {
|
|
|
253
252
|
// Ab hier kam HTTP 200 mit Kennzeichen: der `/v3`-Rand hat den Aufruf
|
|
254
253
|
// gesehen. Ist der Rumpf dann unlesbar (gekuerzt von einem Proxy,
|
|
255
254
|
// abgebrochene Verbindung), kann ein Handler mit Wirkung gelaufen sein.
|
|
256
|
-
|
|
257
|
-
return auswerten(koerper, fehlerName, antwort.status, inhaltstyp, geheimnisse, unlesbar);
|
|
255
|
+
return auswerten(koerper, fehlerName, antwort.status, inhaltstyp, geheimnisse, nachDemSenden);
|
|
258
256
|
}
|
|
259
257
|
finally {
|
|
260
258
|
// Ohne Abraeumen haelt der Wecker den Node-Prozess bis zum Zeitlimit wach.
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -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/esm/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { ReceiptType, VatRate, KeckPaymentMethod, CreditCardProvider, VoucherType, VoucherAction, StripeLinkMode, } from './enums/index.js';
|
|
2
2
|
export { toReceiptItemPayload, fromReceiptItemPayload, receiptItemTotalCents, receiptItemIsValid, negateReceiptItem, isTipItem, toVoucherPayload, fromVoucherPayload, voucherIsValid, toReceiptPayload, fromReceiptPayload, receiptSubSumCents, receiptSumCents, RETURN_DISPOSITIONS, CANCELLATION_REASONS, CANCELLATION_STATUSES, CANCELLATION_ERROR_CODES, CANCELLATION_RESERVATION_MS, isCancellationReason, isReturnDisposition, isCancellationErrorCode, cancellationErrorCode, isCancellationError, cancellationFieldErrors, fromReceiptPaymentPayload, toReceiptPaymentPayload, PAYMENT_ERROR_CODES, isPaymentErrorCode, paymentErrorCode, isPaymentError, paymentFieldErrors, RECEIPT_EMAIL_ERROR_CODES, RECEIPT_EMAIL_SEND_ERROR_CODES, RECEIPT_EMAIL_VIAS, isReceiptEmailErrorCode, receiptEmailErrorCode, isReceiptEmailError, receiptEmailFieldErrors, RECEIPT_ERROR_CODES, isReceiptErrorCode, receiptErrorCode, isReceiptError, receiptFieldErrors, remainingQuantities, fromReceiptCompanyPayload, receiptCompanyTaxInfo, fromCashregisterPayload, fromReceiptSummaryPayload, ZERO_KINDS, isZeroKind, reportMonthFromDate, previousReportMonth, nextReportMonth, reportMonthKey, reportMonthReadable, toStripeUrlSessionPayload, fromStripeUrlSessionPayload, toHobexReceiptPayload, fromHobexReceiptPayload, hobexReceiptToCardPaymentData, hobexReceiptNeedsSignature, } from './models/index.js';
|
|
3
|
-
export { apiKeyAuth, registerUserAuth, DEFAULT_BASE_URL, POS_BASE_URL, DEFAULT_TIMEOUT_MS, ALL_CALLS, PUBLIC_CALLS, POS_CALLS, createTransport, createBinaryTransport, KasseneckApiError, KasseneckAuthError, KasseneckHttpError, KasseneckNetworkError, KasseneckValidationError, CLIENT_ERROR_CODES, isKasseneckApiError, isKasseneckAuthError, isKasseneckHttpError, isKasseneckNetworkError, isKasseneckValidationError, isOutcomeUnknown, sellReceipt, sellReceiptWithCompany, paymentsExpectedCents, cardRefundReference, receiptLayoutFromResult, cancelReceipt, zeroReceipt, getReceipt, getReceiptWithCompany, generateFullReceiptId, getFirstReceiptDate, listMyReceipts, listMyCashregisters, checkVoucherCombinationError, sendReceiptEmail, downloadDailyReport, downloadMonthlyReport, getReportV2, getCashboxStatus, getSignatureStatus, createKasseneckApi, } from './client/index.js';
|
|
3
|
+
export { apiKeyAuth, registerUserAuth, DEFAULT_BASE_URL, POS_BASE_URL, DEFAULT_TIMEOUT_MS, ALL_CALLS, PUBLIC_CALLS, POS_CALLS, UNKNOWN_OUTCOME_CALLS, createTransport, createBinaryTransport, KasseneckApiError, KasseneckAuthError, KasseneckHttpError, KasseneckNetworkError, KasseneckValidationError, CLIENT_ERROR_CODES, isKasseneckApiError, isKasseneckAuthError, isKasseneckHttpError, isKasseneckNetworkError, isKasseneckValidationError, isOutcomeUnknown, sellReceipt, sellReceiptWithCompany, paymentsExpectedCents, cardRefundReference, receiptLayoutFromResult, cancelReceipt, zeroReceipt, getReceipt, getReceiptWithCompany, generateFullReceiptId, getFirstReceiptDate, listMyReceipts, listMyCashregisters, checkVoucherCombinationError, sendReceiptEmail, downloadDailyReport, downloadMonthlyReport, getReportV2, getCashboxStatus, getSignatureStatus, createKasseneckApi, } from './client/index.js';
|
|
4
4
|
export { receiptDueCents, receiptDueBreakdown, ReceiptDueError, RECEIPT_DUE_ERROR_REASONS, isReceiptDueError, } from './receipt/due.js';
|
|
5
5
|
export { parseServerTimeStamp, toViennaWallClock } from './vienna-time.js';
|
|
6
6
|
export { POS_BUSINESS_DEFAULTS, POS_DEVICE_DEFAULTS, mergePosSettings, fromArticleGroupPayload, fromPosArticlePayload, listMyArticleGroups, listMyArticles, getPosSettings, setMyPosSettings, setMyRegisterDeviceSettings, distributeDiscount, cancelScopeOf, receiptsScopeOf, stockViewOf, } from './pos/index.js';
|
|
@@ -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';
|
|
@@ -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 { abfrage, anfragefehler, kennung, seitenweise } from './endpunkte.js';
|
|
28
31
|
import { artikel, liste, naechsterCursor, objekt, reservierung, vorgang, vorschauZeile } from './lesen.js';
|
|
@@ -197,7 +200,9 @@ export async function previewGoodsReceipt(transport, request) {
|
|
|
197
200
|
delete p.idempotencyKey;
|
|
198
201
|
schluessel(name, p, { pflicht: false });
|
|
199
202
|
eingangZahlen(name, p);
|
|
200
|
-
|
|
203
|
+
// Ein Probelauf schreibt nichts: nach einem Zeitlimit bleibt er `rejected`,
|
|
204
|
+
// obwohl `receiveGoods` sonst Wirkung hat.
|
|
205
|
+
const daten = await transport(name, { ...p, dryRun: true }, undefined, undefined, { hasEffect: false });
|
|
201
206
|
return { preview: liste(name, daten, 'preview', vorschauZeile) };
|
|
202
207
|
}
|
|
203
208
|
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'`.
|