@kreiseck/kasseneck-api 1.7.1 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/CHANGELOG.md +113 -0
  2. package/README.md +170 -1
  3. package/dist/cjs/client/api.d.ts +5 -3
  4. package/dist/cjs/client/api.js +1 -0
  5. package/dist/cjs/client/aufrufe.d.ts +9 -7
  6. package/dist/cjs/client/aufrufe.js +60 -2
  7. package/dist/cjs/client/errors.js +3 -0
  8. package/dist/cjs/client/index.d.ts +2 -2
  9. package/dist/cjs/client/index.js +3 -1
  10. package/dist/cjs/client/reports.d.ts +26 -0
  11. package/dist/cjs/client/reports.js +47 -0
  12. package/dist/cjs/client/transport.d.ts +27 -3
  13. package/dist/cjs/client/transport.js +29 -3
  14. package/dist/cjs/index.d.ts +1 -1
  15. package/dist/cjs/index.js +4 -2
  16. package/dist/cjs/inventory/api.d.ts +21 -2
  17. package/dist/cjs/inventory/api.js +22 -3
  18. package/dist/cjs/inventory/fehler.d.ts +6 -0
  19. package/dist/cjs/inventory/fehler.js +12 -0
  20. package/dist/cjs/inventory/index.d.ts +6 -4
  21. package/dist/cjs/inventory/index.js +33 -3
  22. package/dist/cjs/inventory/inventur.d.ts +104 -0
  23. package/dist/cjs/inventory/inventur.js +245 -0
  24. package/dist/cjs/inventory/lesen.d.ts +20 -1
  25. package/dist/cjs/inventory/lesen.js +307 -0
  26. package/dist/cjs/inventory/typen.d.ts +410 -1
  27. package/dist/cjs/inventory/vertrag.d.ts +94 -8
  28. package/dist/cjs/inventory/vertrag.js +118 -5
  29. package/dist/cjs/invoice/index.d.ts +1 -1
  30. package/dist/cjs/invoice/typen.d.ts +12 -0
  31. package/dist/cjs/invoice/vertrag.d.ts +1 -1
  32. package/dist/cjs/invoice/vertrag.js +3 -0
  33. package/dist/cjs/models/cancellation.d.ts +1 -1
  34. package/dist/cjs/models/cancellation.js +3 -0
  35. package/dist/cjs/models/payment-errors.d.ts +1 -1
  36. package/dist/cjs/models/payment-errors.js +3 -0
  37. package/dist/cjs/models/receipt-email.d.ts +1 -1
  38. package/dist/cjs/models/receipt-email.js +3 -0
  39. package/dist/cjs/models/receipt-errors.d.ts +1 -1
  40. package/dist/cjs/models/receipt-errors.js +3 -0
  41. package/dist/cjs/pos/errors.d.ts +4 -3
  42. package/dist/cjs/pos/errors.js +24 -2
  43. package/dist/cjs/pos/index.d.ts +4 -1
  44. package/dist/cjs/pos/index.js +9 -2
  45. package/dist/cjs/pos/inventur.d.ts +104 -0
  46. package/dist/cjs/pos/inventur.js +117 -0
  47. package/dist/cjs/pos/texte.d.ts +82 -0
  48. package/dist/cjs/pos/texte.js +35 -0
  49. package/dist/cjs/register/errors.d.ts +1 -1
  50. package/dist/cjs/register/errors.js +3 -0
  51. package/dist/cjs/stored/vokabular.d.ts +1 -1
  52. package/dist/cjs/stored/vokabular.js +1 -1
  53. package/dist/cjs/version.d.ts +1 -1
  54. package/dist/cjs/version.js +1 -1
  55. package/dist/esm/client/api.d.ts +5 -3
  56. package/dist/esm/client/api.js +2 -1
  57. package/dist/esm/client/aufrufe.d.ts +9 -7
  58. package/dist/esm/client/aufrufe.js +60 -2
  59. package/dist/esm/client/errors.js +3 -0
  60. package/dist/esm/client/index.d.ts +2 -2
  61. package/dist/esm/client/index.js +2 -2
  62. package/dist/esm/client/reports.d.ts +26 -0
  63. package/dist/esm/client/reports.js +46 -0
  64. package/dist/esm/client/transport.d.ts +27 -3
  65. package/dist/esm/client/transport.js +28 -3
  66. package/dist/esm/index.d.ts +1 -1
  67. package/dist/esm/index.js +1 -1
  68. package/dist/esm/inventory/api.d.ts +21 -2
  69. package/dist/esm/inventory/api.js +23 -4
  70. package/dist/esm/inventory/fehler.d.ts +6 -0
  71. package/dist/esm/inventory/fehler.js +11 -0
  72. package/dist/esm/inventory/index.d.ts +6 -4
  73. package/dist/esm/inventory/index.js +5 -3
  74. package/dist/esm/inventory/inventur.d.ts +104 -0
  75. package/dist/esm/inventory/inventur.js +226 -0
  76. package/dist/esm/inventory/lesen.d.ts +20 -1
  77. package/dist/esm/inventory/lesen.js +301 -0
  78. package/dist/esm/inventory/typen.d.ts +410 -1
  79. package/dist/esm/inventory/vertrag.d.ts +94 -8
  80. package/dist/esm/inventory/vertrag.js +117 -4
  81. package/dist/esm/invoice/index.d.ts +1 -1
  82. package/dist/esm/invoice/typen.d.ts +12 -0
  83. package/dist/esm/invoice/vertrag.d.ts +1 -1
  84. package/dist/esm/invoice/vertrag.js +3 -0
  85. package/dist/esm/models/cancellation.d.ts +1 -1
  86. package/dist/esm/models/cancellation.js +3 -0
  87. package/dist/esm/models/payment-errors.d.ts +1 -1
  88. package/dist/esm/models/payment-errors.js +3 -0
  89. package/dist/esm/models/receipt-email.d.ts +1 -1
  90. package/dist/esm/models/receipt-email.js +3 -0
  91. package/dist/esm/models/receipt-errors.d.ts +1 -1
  92. package/dist/esm/models/receipt-errors.js +3 -0
  93. package/dist/esm/pos/errors.d.ts +4 -3
  94. package/dist/esm/pos/errors.js +24 -2
  95. package/dist/esm/pos/index.d.ts +4 -1
  96. package/dist/esm/pos/index.js +2 -1
  97. package/dist/esm/pos/inventur.d.ts +104 -0
  98. package/dist/esm/pos/inventur.js +109 -0
  99. package/dist/esm/pos/texte.d.ts +82 -0
  100. package/dist/esm/pos/texte.js +35 -0
  101. package/dist/esm/register/errors.d.ts +1 -1
  102. package/dist/esm/register/errors.js +3 -0
  103. package/dist/esm/stored/vokabular.d.ts +1 -1
  104. package/dist/esm/stored/vokabular.js +1 -1
  105. package/dist/esm/version.d.ts +1 -1
  106. package/dist/esm/version.js +1 -1
  107. package/fixtures/hobex-hps-codes.json +1 -1
  108. package/fixtures/invoice-api.schema.json +1 -1
  109. package/fixtures/invoice-texts.json +1 -1
  110. package/fixtures/pos-texts.json +94 -1
  111. package/fixtures/stocktake-quantity-cases.json +55 -0
  112. package/fixtures/surface.json +157 -8
  113. package/fixtures/v3/antworten/belege.json +1 -1
  114. package/fixtures/v3/antworten/belegmail.json +1 -1
  115. package/fixtures/v3/antworten/kasse-belege.json +1 -1
  116. package/fixtures/v3/antworten/kasse.json +2958 -3
  117. package/fixtures/v3/antworten/lager.json +1727 -3
  118. package/fixtures/v3/antworten/rechnungen.json +14 -6
  119. package/fixtures/v3/antworten/storno.json +1 -1
  120. package/fixtures/v3/stored/belege.json +1 -1
  121. package/fixtures/v3/stored/kasse.json +414 -3
  122. package/fixtures/v3/stored/rechnungen.json +1 -1
  123. package/fixtures/v3/v3-vokabular.json +530 -8
  124. package/fixtures/v3/zahlbetrag-faelle.json +1 -1
  125. package/package.json +1 -1
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Inventur der Lager-API (Lager-Kern Stufe 3): anlegen, zaehlen, Zaehlungen
3
+ * stornieren, pruefen, nachzaehlen, abschliessen, abbrechen, Inventurprotokoll
4
+ * holen; dazu die Listen der Inventuren, Positionen und Zaehlungen.
5
+ *
6
+ * Ablauf: `createStocktake` → `recordStocktakeCount` (beliebig oft, auch von
7
+ * mehreren Geraeten; je Position addiert) → `reviewStocktake` (erst jetzt Soll
8
+ * und Differenz) → bei Bedarf `recountStocktake` und erneut `reviewStocktake`
9
+ * → `closeStocktake` → `getStocktakePdf`. Pruefen und Abschliessen rechnet der
10
+ * Server im Hintergrund: die Antwort traegt den Zwischenstand
11
+ * (`review.complete: false` bzw. `status: 'closing'`), `getStocktake` den
12
+ * Fortgang.
13
+ *
14
+ * **Blind:** vor `review` traegt keine Antwort ein Soll; `blind: false` zeigt
15
+ * beim Zaehlen nur den heutigen Buchbestand (`bookStockNow`), nie das Soll
16
+ * zur Referenzzeit.
17
+ *
18
+ * Rechte wie in Stufe 5b: Lesen mit jedem Schluessel, alles Schreibende (auch
19
+ * Zaehlen) mit dem Konto-Schalter „Lager-API schreiben“ (Test-Schluessel
20
+ * immer), sonst `inventory_api_not_enabled`; Werte und das Protokoll mit
21
+ * Werten nur mit `lagerApi.kosten`.
22
+ *
23
+ * **Vor dem Senden geprueft wird nur, was ohne Netz sicher falsch ist:**
24
+ * `idempotencyKey` (Pflicht bei jedem Schreiben, 1–120 Zeichen), fehlende
25
+ * Kennungen (`stocktakeId`, `articleId`, `countId`, `locationId`), `scope`
26
+ * kein Objekt, eine Menge, die keine Ganzzahl ist (Tausendstel), ein leerer
27
+ * Grund, `items` beim Nachzaehlen leer oder ohne `articleId`,
28
+ * `serialNumbers` keine Liste, `uncountedAsZero` kein Wahrheitswert. Alles
29
+ * Fachliche (Umfang, Stichtag, Seriennummern, Zustand) prueft der Server.
30
+ *
31
+ * **Wiederholen** wie bei jedem Schreiben: nach `outcome: 'unknown'` denselben
32
+ * Aufruf mit **demselben** `idempotencyKey`. Eine Zaehlung wirkt dann genau
33
+ * einmal (das Zaehldokument ist selbst der Nachweis); ein neuer Schluessel
34
+ * zaehlte die Ware ein zweites Mal.
35
+ */
36
+ import type { ApiCall, InternerPdfOderDatenTransport, InternerTransport } from '../client/aufrufe.js';
37
+ import type { CancelStocktakeRequest, CloseStocktakeRequest, CloseStocktakeResult, CreateStocktakeRequest, RecordStocktakeCountRequest, RecountStocktakeRequest, ReviewStocktakeRequest, Stocktake, StocktakeCount, StocktakeCountListQuery, StocktakeCountPage, StocktakeCountResult, StocktakeItem, StocktakeItemListQuery, StocktakeItemPage, StocktakeListQuery, StocktakePage, StocktakePdf, VoidStocktakeCountRequest } from './typen.js';
38
+ type Params = Record<string, unknown>;
39
+ /**
40
+ * Legt eine Inventur an. Je Standort hoechstens eine offene
41
+ * (`stocktake_location_busy`, `data.stocktakeId` nennt sie); Umfang `groups`
42
+ * bzw. `articles` nur mit bestandsgefuehrten Artikeln (`article_not_tracked`).
43
+ * Jede Inventur beginnt in `counting`.
44
+ */
45
+ export declare function createStocktake(transport: InternerTransport, request: CreateStocktakeRequest): Promise<Stocktake>;
46
+ /**
47
+ * Inventuren des Kontos. Ohne `updatedSince` zuletzt geaenderte zuerst; mit
48
+ * `updatedSince` aufsteigend nach `updatedAt` und inklusive (Abgleich: das
49
+ * groesste gesehene `updatedAt` als naechstes `updatedSince`). Filter
50
+ * `status` und `locationId`.
51
+ */
52
+ export declare function listStocktakes(transport: InternerTransport, query?: StocktakeListQuery): Promise<StocktakePage>;
53
+ /** Alle Inventuren der Abfrage, Seite fuer Seite, in der Reihenfolge von [listStocktakes]. */
54
+ export declare function iterateStocktakes(transport: InternerTransport, query?: StocktakeListQuery): AsyncGenerator<Stocktake, void, undefined>;
55
+ /** Eine Inventur samt `progress.counted` (gezaehlte Positionen). */
56
+ export declare function getStocktake(transport: InternerTransport, stocktakeId: string): Promise<Stocktake>;
57
+ /** Positionen einer Inventur nach Kennung; `openOnly` = ungezaehlt bzw. in `review` zum Nachzaehlen offen. */
58
+ export declare function listStocktakeItems(transport: InternerTransport, query: StocktakeItemListQuery): Promise<StocktakeItemPage>;
59
+ export declare function iterateStocktakeItems(transport: InternerTransport, query: StocktakeItemListQuery): AsyncGenerator<StocktakeItem, void, undefined>;
60
+ /** Zaehlungen einer Inventur, neueste zuerst, auch stornierte; mit `articleId` nur die des Artikels. */
61
+ export declare function listStocktakeCounts(transport: InternerTransport, query: StocktakeCountListQuery): Promise<StocktakeCountPage>;
62
+ export declare function iterateStocktakeCounts(transport: InternerTransport, query: StocktakeCountListQuery): AsyncGenerator<StocktakeCount, void, undefined>;
63
+ /** Pruefung einer Zaehlung vor dem Senden, geteilt mit dem Kassenweg. Paketintern. */
64
+ export declare function zaehlungPruefen(name: ApiCall, p: Params): void;
65
+ /** Pruefung eines Stornos vor dem Senden, geteilt mit dem Kassenweg. Paketintern. */
66
+ export declare function stornoPruefen(name: ApiCall, p: Params): void;
67
+ /**
68
+ * Eine Zaehlung. Antwort: die Zaehlung und ihre Position danach (Summe der
69
+ * Runde in `item.quantity`). Gezaehlt wird in `counting`, in `review` nur an
70
+ * Positionen, die zum Nachzaehlen frei sind (sonst `stocktake_not_open`).
71
+ */
72
+ export declare function recordStocktakeCount(transport: InternerTransport, request: RecordStocktakeCountRequest): Promise<StocktakeCountResult>;
73
+ /** Storniert eine Zaehlung mit Grund; die Position wird aus den uebrigen Zaehlungen neu summiert. */
74
+ export declare function voidStocktakeCount(transport: InternerTransport, request: VoidStocktakeCountRequest): Promise<StocktakeCountResult>;
75
+ /**
76
+ * Pruefen: `counting` → `review`, in `review` neu rechnen (nach dem
77
+ * Nachzaehlen). Die Antwort kommt sofort mit `review.complete: false`; Soll
78
+ * und Differenz stehen an den Positionen, sobald `complete` `true` ist.
79
+ */
80
+ export declare function reviewStocktake(transport: InternerTransport, request: ReviewStocktakeRequest): Promise<Stocktake>;
81
+ /** Nachzaehlen: je genannter Position eine neue Runde; danach zaehlen und erneut [reviewStocktake]. */
82
+ export declare function recountStocktake(transport: InternerTransport, request: RecountStocktakeRequest): Promise<Stocktake>;
83
+ /**
84
+ * Abschliessen (nur aus `review`, sonst `stocktake_not_in_review`; offene
85
+ * Nachzaehlungen ergeben `stocktake_recount_open`). Der Server bucht in
86
+ * Teilen weiter; die Antwort traegt meist `status: 'closing'`. Ein erneuter
87
+ * Aufruf waehrend `closing` stoesst den Abschluss wieder an.
88
+ */
89
+ export declare function closeStocktake(transport: InternerTransport, request: CloseStocktakeRequest): Promise<CloseStocktakeResult>;
90
+ /** Abbrechen mit Grund (aus `counting` oder `review`); der Standort ist danach frei. */
91
+ export declare function cancelStocktake(transport: InternerTransport, request: CancelStocktakeRequest): Promise<Stocktake>;
92
+ /**
93
+ * Das Inventurprotokoll (PDF), erst nach dem Abschluss (`stocktake_not_closed`,
94
+ * auch fuer eine abgebrochene Inventur). Mit `lagerApi.kosten` die Fassung mit
95
+ * Werten, sonst die nur mit Mengen. Bis 9 MiB kommt die Datei selbst
96
+ * (`kind: 'pdf'`), darueber ein signierter Lese-Link fuer 15 Minuten
97
+ * (`kind: 'download'`); die geladene Datei an `download.sha256` pruefen.
98
+ *
99
+ * Als freie Funktion braucht sie den Transport aus `createPdfOrDataTransport`
100
+ * (Paketwurzel): ein JSON-Transport laese die Datei als Text, ein reiner
101
+ * Binaer-Transport kennt den Link nicht. [createInventoryClient] bindet ihn selbst.
102
+ */
103
+ export declare function getStocktakePdf(transport: InternerPdfOderDatenTransport, stocktakeId: string): Promise<StocktakePdf>;
104
+ export {};
@@ -0,0 +1,245 @@
1
+ "use strict";
2
+ /**
3
+ * Inventur der Lager-API (Lager-Kern Stufe 3): anlegen, zaehlen, Zaehlungen
4
+ * stornieren, pruefen, nachzaehlen, abschliessen, abbrechen, Inventurprotokoll
5
+ * holen; dazu die Listen der Inventuren, Positionen und Zaehlungen.
6
+ *
7
+ * Ablauf: `createStocktake` → `recordStocktakeCount` (beliebig oft, auch von
8
+ * mehreren Geraeten; je Position addiert) → `reviewStocktake` (erst jetzt Soll
9
+ * und Differenz) → bei Bedarf `recountStocktake` und erneut `reviewStocktake`
10
+ * → `closeStocktake` → `getStocktakePdf`. Pruefen und Abschliessen rechnet der
11
+ * Server im Hintergrund: die Antwort traegt den Zwischenstand
12
+ * (`review.complete: false` bzw. `status: 'closing'`), `getStocktake` den
13
+ * Fortgang.
14
+ *
15
+ * **Blind:** vor `review` traegt keine Antwort ein Soll; `blind: false` zeigt
16
+ * beim Zaehlen nur den heutigen Buchbestand (`bookStockNow`), nie das Soll
17
+ * zur Referenzzeit.
18
+ *
19
+ * Rechte wie in Stufe 5b: Lesen mit jedem Schluessel, alles Schreibende (auch
20
+ * Zaehlen) mit dem Konto-Schalter „Lager-API schreiben“ (Test-Schluessel
21
+ * immer), sonst `inventory_api_not_enabled`; Werte und das Protokoll mit
22
+ * Werten nur mit `lagerApi.kosten`.
23
+ *
24
+ * **Vor dem Senden geprueft wird nur, was ohne Netz sicher falsch ist:**
25
+ * `idempotencyKey` (Pflicht bei jedem Schreiben, 1–120 Zeichen), fehlende
26
+ * Kennungen (`stocktakeId`, `articleId`, `countId`, `locationId`), `scope`
27
+ * kein Objekt, eine Menge, die keine Ganzzahl ist (Tausendstel), ein leerer
28
+ * Grund, `items` beim Nachzaehlen leer oder ohne `articleId`,
29
+ * `serialNumbers` keine Liste, `uncountedAsZero` kein Wahrheitswert. Alles
30
+ * Fachliche (Umfang, Stichtag, Seriennummern, Zustand) prueft der Server.
31
+ *
32
+ * **Wiederholen** wie bei jedem Schreiben: nach `outcome: 'unknown'` denselben
33
+ * Aufruf mit **demselben** `idempotencyKey`. Eine Zaehlung wirkt dann genau
34
+ * einmal (das Zaehldokument ist selbst der Nachweis); ein neuer Schluessel
35
+ * zaehlte die Ware ein zweites Mal.
36
+ */
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ exports.createStocktake = createStocktake;
39
+ exports.listStocktakes = listStocktakes;
40
+ exports.iterateStocktakes = iterateStocktakes;
41
+ exports.getStocktake = getStocktake;
42
+ exports.listStocktakeItems = listStocktakeItems;
43
+ exports.iterateStocktakeItems = iterateStocktakeItems;
44
+ exports.listStocktakeCounts = listStocktakeCounts;
45
+ exports.iterateStocktakeCounts = iterateStocktakeCounts;
46
+ exports.zaehlungPruefen = zaehlungPruefen;
47
+ exports.stornoPruefen = stornoPruefen;
48
+ exports.recordStocktakeCount = recordStocktakeCount;
49
+ exports.voidStocktakeCount = voidStocktakeCount;
50
+ exports.reviewStocktake = reviewStocktake;
51
+ exports.recountStocktake = recountStocktake;
52
+ exports.closeStocktake = closeStocktake;
53
+ exports.cancelStocktake = cancelStocktake;
54
+ exports.getStocktakePdf = getStocktakePdf;
55
+ const endpunkte_js_1 = require("./endpunkte.js");
56
+ const lesen_js_1 = require("./lesen.js");
57
+ const schreiben_js_1 = require("./schreiben.js");
58
+ const istObjekt = (w) => w !== null && typeof w === 'object' && !Array.isArray(w);
59
+ const kopfAus = (name, daten) => (0, lesen_js_1.inventur)({ name, pfad: 'stocktake' }, (0, lesen_js_1.objekt)(daten)?.stocktake);
60
+ /** Ein Grund (Storno, Nachzaehlen, Abbruch): nicht leer. Die Laenge prueft der Server. */
61
+ function grund(name, w) {
62
+ if (typeof w !== 'string' || w.trim() === '')
63
+ throw (0, endpunkte_js_1.anfragefehler)(name, 'reason fehlt (Grund mit 1 bis 500 Zeichen)');
64
+ }
65
+ /** Schreibende Anfrage mit `stocktakeId`: Schluessel und Kennung geprueft, flach wie gesendet. */
66
+ function schreibend(name, request) {
67
+ const p = (0, schreiben_js_1.anfrage)(name, request);
68
+ (0, schreiben_js_1.schluessel)(name, p, { pflicht: true });
69
+ (0, endpunkte_js_1.kennung)(name, 'stocktakeId', p.stocktakeId);
70
+ return p;
71
+ }
72
+ /** Eine Liste unter einer Inventur: `stocktakeId` Pflicht, sonst wie jede Abfrage. */
73
+ function abfrageMitInventur(name, query) {
74
+ if (!istObjekt(query))
75
+ throw (0, endpunkte_js_1.anfragefehler)(name, 'Abfrage mit stocktakeId erwartet');
76
+ const p = (0, endpunkte_js_1.abfrage)(name, query);
77
+ (0, endpunkte_js_1.kennung)(name, 'stocktakeId', p.stocktakeId);
78
+ return p;
79
+ }
80
+ // ---- Anlegen und Lesen -------------------------------------------------------------
81
+ /**
82
+ * Legt eine Inventur an. Je Standort hoechstens eine offene
83
+ * (`stocktake_location_busy`, `data.stocktakeId` nennt sie); Umfang `groups`
84
+ * bzw. `articles` nur mit bestandsgefuehrten Artikeln (`article_not_tracked`).
85
+ * Jede Inventur beginnt in `counting`.
86
+ */
87
+ async function createStocktake(transport, request) {
88
+ const name = 'createStocktake';
89
+ const p = (0, schreiben_js_1.anfrage)(name, request);
90
+ (0, schreiben_js_1.schluessel)(name, p, { pflicht: true });
91
+ (0, endpunkte_js_1.kennung)(name, 'locationId', p.locationId);
92
+ if (!istObjekt(p.scope))
93
+ throw (0, endpunkte_js_1.anfragefehler)(name, 'scope fehlt oder ist kein Objekt { type, groupIds?, articleIds? }');
94
+ return kopfAus(name, await transport(name, p));
95
+ }
96
+ /**
97
+ * Inventuren des Kontos. Ohne `updatedSince` zuletzt geaenderte zuerst; mit
98
+ * `updatedSince` aufsteigend nach `updatedAt` und inklusive (Abgleich: das
99
+ * groesste gesehene `updatedAt` als naechstes `updatedSince`). Filter
100
+ * `status` und `locationId`.
101
+ */
102
+ async function listStocktakes(transport, query) {
103
+ const name = 'listStocktakes';
104
+ const daten = await transport(name, (0, endpunkte_js_1.abfrage)(name, query));
105
+ return { stocktakes: (0, lesen_js_1.liste)(name, daten, 'stocktakes', lesen_js_1.inventur), nextCursor: (0, lesen_js_1.naechsterCursor)(name, daten) };
106
+ }
107
+ /** Alle Inventuren der Abfrage, Seite fuer Seite, in der Reihenfolge von [listStocktakes]. */
108
+ function iterateStocktakes(transport, query) {
109
+ const { cursor, ...rest } = query ?? {};
110
+ return (0, endpunkte_js_1.seitenweise)('listStocktakes', cursor, async (c) => {
111
+ const s = await listStocktakes(transport, { ...rest, cursor: c });
112
+ return { eintraege: s.stocktakes, nextCursor: s.nextCursor };
113
+ });
114
+ }
115
+ /** Eine Inventur samt `progress.counted` (gezaehlte Positionen). */
116
+ async function getStocktake(transport, stocktakeId) {
117
+ const name = 'getStocktake';
118
+ return kopfAus(name, await transport(name, { stocktakeId: (0, endpunkte_js_1.kennung)(name, 'stocktakeId', stocktakeId) }));
119
+ }
120
+ /** Positionen einer Inventur nach Kennung; `openOnly` = ungezaehlt bzw. in `review` zum Nachzaehlen offen. */
121
+ async function listStocktakeItems(transport, query) {
122
+ const name = 'listStocktakeItems';
123
+ const daten = await transport(name, abfrageMitInventur(name, query));
124
+ return { items: (0, lesen_js_1.liste)(name, daten, 'items', lesen_js_1.inventurPosition), nextCursor: (0, lesen_js_1.naechsterCursor)(name, daten) };
125
+ }
126
+ function iterateStocktakeItems(transport, query) {
127
+ const { cursor, ...rest } = query;
128
+ return (0, endpunkte_js_1.seitenweise)('listStocktakeItems', cursor, async (c) => {
129
+ const s = await listStocktakeItems(transport, { ...rest, cursor: c });
130
+ return { eintraege: s.items, nextCursor: s.nextCursor };
131
+ });
132
+ }
133
+ /** Zaehlungen einer Inventur, neueste zuerst, auch stornierte; mit `articleId` nur die des Artikels. */
134
+ async function listStocktakeCounts(transport, query) {
135
+ const name = 'listStocktakeCounts';
136
+ const daten = await transport(name, abfrageMitInventur(name, query));
137
+ return { counts: (0, lesen_js_1.liste)(name, daten, 'counts', lesen_js_1.inventurZaehlung), nextCursor: (0, lesen_js_1.naechsterCursor)(name, daten) };
138
+ }
139
+ function iterateStocktakeCounts(transport, query) {
140
+ const { cursor, ...rest } = query;
141
+ return (0, endpunkte_js_1.seitenweise)('listStocktakeCounts', cursor, async (c) => {
142
+ const s = await listStocktakeCounts(transport, { ...rest, cursor: c });
143
+ return { eintraege: s.counts, nextCursor: s.nextCursor };
144
+ });
145
+ }
146
+ // ---- Zaehlen und Stornieren ------------------------------------------------------
147
+ /** Pruefung einer Zaehlung vor dem Senden, geteilt mit dem Kassenweg. Paketintern. */
148
+ function zaehlungPruefen(name, p) {
149
+ (0, endpunkte_js_1.kennung)(name, 'articleId', p.articleId);
150
+ (0, schreiben_js_1.ganz)(name, 'quantity', p.quantity, { pflicht: true });
151
+ if (p.serialNumbers !== undefined && p.serialNumbers !== null && !Array.isArray(p.serialNumbers)) {
152
+ throw (0, endpunkte_js_1.anfragefehler)(name, 'serialNumbers muss eine Liste sein');
153
+ }
154
+ }
155
+ /** Pruefung eines Stornos vor dem Senden, geteilt mit dem Kassenweg. Paketintern. */
156
+ function stornoPruefen(name, p) {
157
+ (0, endpunkte_js_1.kennung)(name, 'countId', p.countId);
158
+ grund(name, p.reason);
159
+ }
160
+ /**
161
+ * Eine Zaehlung. Antwort: die Zaehlung und ihre Position danach (Summe der
162
+ * Runde in `item.quantity`). Gezaehlt wird in `counting`, in `review` nur an
163
+ * Positionen, die zum Nachzaehlen frei sind (sonst `stocktake_not_open`).
164
+ */
165
+ async function recordStocktakeCount(transport, request) {
166
+ const name = 'recordStocktakeCount';
167
+ const p = schreibend(name, request);
168
+ zaehlungPruefen(name, p);
169
+ return (0, lesen_js_1.zaehlungMitPosition)(name, await transport(name, p));
170
+ }
171
+ /** Storniert eine Zaehlung mit Grund; die Position wird aus den uebrigen Zaehlungen neu summiert. */
172
+ async function voidStocktakeCount(transport, request) {
173
+ const name = 'voidStocktakeCount';
174
+ const p = schreibend(name, request);
175
+ stornoPruefen(name, p);
176
+ return (0, lesen_js_1.zaehlungMitPosition)(name, await transport(name, p));
177
+ }
178
+ // ---- Pruefen bis Abbruch ------------------------------------------------------------
179
+ /**
180
+ * Pruefen: `counting` → `review`, in `review` neu rechnen (nach dem
181
+ * Nachzaehlen). Die Antwort kommt sofort mit `review.complete: false`; Soll
182
+ * und Differenz stehen an den Positionen, sobald `complete` `true` ist.
183
+ */
184
+ async function reviewStocktake(transport, request) {
185
+ const name = 'reviewStocktake';
186
+ return kopfAus(name, await transport(name, schreibend(name, request)));
187
+ }
188
+ /** Nachzaehlen: je genannter Position eine neue Runde; danach zaehlen und erneut [reviewStocktake]. */
189
+ async function recountStocktake(transport, request) {
190
+ const name = 'recountStocktake';
191
+ const p = schreibend(name, request);
192
+ if (!Array.isArray(p.items) || p.items.length === 0)
193
+ throw (0, endpunkte_js_1.anfragefehler)(name, 'items fehlt oder ist leer');
194
+ p.items.forEach((x, i) => {
195
+ if (!istObjekt(x))
196
+ throw (0, endpunkte_js_1.anfragefehler)(name, `items[${i}] muss ein Objekt sein`);
197
+ (0, endpunkte_js_1.kennung)(name, `items[${i}].articleId`, x.articleId);
198
+ });
199
+ grund(name, p.reason);
200
+ return kopfAus(name, await transport(name, p));
201
+ }
202
+ /**
203
+ * Abschliessen (nur aus `review`, sonst `stocktake_not_in_review`; offene
204
+ * Nachzaehlungen ergeben `stocktake_recount_open`). Der Server bucht in
205
+ * Teilen weiter; die Antwort traegt meist `status: 'closing'`. Ein erneuter
206
+ * Aufruf waehrend `closing` stoesst den Abschluss wieder an.
207
+ */
208
+ async function closeStocktake(transport, request) {
209
+ const name = 'closeStocktake';
210
+ const p = schreibend(name, request);
211
+ if (p.uncountedAsZero !== undefined && typeof p.uncountedAsZero !== 'boolean') {
212
+ throw (0, endpunkte_js_1.anfragefehler)(name, 'uncountedAsZero muss true oder false sein');
213
+ }
214
+ const daten = await transport(name, p);
215
+ return { stocktake: kopfAus(name, daten), warnings: (0, lesen_js_1.inventurWarnungen)({ name, pfad: 'warnings' }, (0, lesen_js_1.objekt)(daten)?.warnings) };
216
+ }
217
+ /** Abbrechen mit Grund (aus `counting` oder `review`); der Standort ist danach frei. */
218
+ async function cancelStocktake(transport, request) {
219
+ const name = 'cancelStocktake';
220
+ const p = schreibend(name, request);
221
+ grund(name, p.reason);
222
+ return kopfAus(name, await transport(name, p));
223
+ }
224
+ // ---- Protokoll ------------------------------------------------------------------
225
+ /**
226
+ * Das Inventurprotokoll (PDF), erst nach dem Abschluss (`stocktake_not_closed`,
227
+ * auch fuer eine abgebrochene Inventur). Mit `lagerApi.kosten` die Fassung mit
228
+ * Werten, sonst die nur mit Mengen. Bis 9 MiB kommt die Datei selbst
229
+ * (`kind: 'pdf'`), darueber ein signierter Lese-Link fuer 15 Minuten
230
+ * (`kind: 'download'`); die geladene Datei an `download.sha256` pruefen.
231
+ *
232
+ * Als freie Funktion braucht sie den Transport aus `createPdfOrDataTransport`
233
+ * (Paketwurzel): ein JSON-Transport laese die Datei als Text, ein reiner
234
+ * Binaer-Transport kennt den Link nicht. [createInventoryClient] bindet ihn selbst.
235
+ */
236
+ async function getStocktakePdf(transport, stocktakeId) {
237
+ const name = 'getStocktakePdf';
238
+ const ergebnis = await transport(name, { stocktakeId: (0, endpunkte_js_1.kennung)(name, 'stocktakeId', stocktakeId) });
239
+ if ('pdf' in ergebnis)
240
+ return { kind: 'pdf', pdf: ergebnis.pdf };
241
+ const link = (0, lesen_js_1.objekt)(ergebnis.data)?.download;
242
+ if (link === undefined || link === null)
243
+ throw (0, lesen_js_1.antwortfehler)(name, 'Antwort ist weder ein PDF noch ein Lese-Link (data.download fehlt)');
244
+ return { kind: 'download', download: (0, lesen_js_1.protokollLink)(name, link) };
245
+ }
@@ -12,7 +12,7 @@
12
12
  * wenn der Server sie sendet: „fehlt“ heisst dort „kein Recht“, nicht „leer“.
13
13
  */
14
14
  import { KasseneckValidationError } from '../client/errors.js';
15
- import type { Article, GoodsReceiptPreviewLine, InventoryShortfall, InventoryWebhook, InventoryWebhookDelivery, InventoryWebhookTestDelivery, Location, Reservation, StockBelowMinimumEventData, StockChangedEventData, StockLevel, StockMovement, StockOperation, StockValue, VariantGroup } from './typen.js';
15
+ import type { Article, GoodsReceiptPreviewLine, InventoryShortfall, InventoryWebhook, InventoryWebhookDelivery, InventoryWebhookTestDelivery, Location, Reservation, StockBelowMinimumEventData, StockChangedEventData, StockLevel, StockMovement, StockOperation, StockValue, Stocktake, StocktakeCount, StocktakeCountResult, StocktakeItem, StocktakePdfDownload, StocktakeWarning, VariantGroup } from './typen.js';
16
16
  type Roh = Record<string, unknown>;
17
17
  /** Ein Leser bekommt den Vorgang (fuer die Meldung) und den Pfad im Rumpf. */
18
18
  export interface Ort {
@@ -44,6 +44,25 @@ export declare function fehlmengen(roh: unknown): InventoryShortfall[];
44
44
  * bzw. „keine Varianten“).
45
45
  */
46
46
  export declare function variantengruppe(ort: Ort, w: unknown): VariantGroup;
47
+ /** Hinweise einer Inventur; fehlt die Liste, gibt es keine. */
48
+ export declare function inventurWarnungen(ort: Ort, w: unknown): StocktakeWarning[];
49
+ /**
50
+ * Kopf einer Inventur. Was erst nach dem Abschluss kommt (Summen, Hinweise,
51
+ * Siegel, Pruefsumme, Protokoll), steht im Modell nur, wenn der Server es
52
+ * sendet; Werte nur mit dem Kosten-Recht.
53
+ */
54
+ export declare function inventur(ort: Ort, w: unknown): Stocktake;
55
+ /**
56
+ * Eine Position. Soll, Differenz und alles aus Pruefung und Abschluss stehen
57
+ * im Modell nur, wenn der Server sie sendet (blind: vor `review` nie).
58
+ */
59
+ export declare function inventurPosition(ort: Ort, w: unknown): StocktakeItem;
60
+ /** Eine Zaehlung: Menge, Runde und Kennungen muessen da sein. */
61
+ export declare function inventurZaehlung(ort: Ort, w: unknown): StocktakeCount;
62
+ /** Antwort von Zaehlen und Stornieren: beide Teile sind zugesagt. */
63
+ export declare function zaehlungMitPosition(name: string, daten: unknown): StocktakeCountResult;
64
+ /** Lese-Link auf ein grosses Inventurprotokoll; ohne Adresse, Ablauf, Groesse oder Pruefsumme ist er unbrauchbar. */
65
+ export declare function protokollLink(name: string, w: unknown): StocktakePdfDownload;
47
66
  /** Eine zugesagte Liste `data.<feld>`, Eintrag fuer Eintrag gelesen. */
48
67
  export declare function liste<T>(name: string, daten: unknown, feld: string, lesen: (ort: Ort, e: unknown) => T): T[];
49
68
  /** Der Cursor der naechsten Seite; `null` am Ende. Etwas anderes als Text oder `null` ist kaputt. */