@kreiseck/kasseneck-api 1.2.2 → 1.4.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 (81) hide show
  1. package/CHANGELOG.md +99 -0
  2. package/README.md +119 -3
  3. package/dist/cjs/client/aufrufe.d.ts +2 -2
  4. package/dist/cjs/client/aufrufe.js +30 -0
  5. package/dist/cjs/inventory/api.d.ts +45 -0
  6. package/dist/cjs/inventory/api.js +38 -0
  7. package/dist/cjs/inventory/auth.d.ts +17 -0
  8. package/dist/cjs/inventory/auth.js +27 -0
  9. package/dist/cjs/inventory/endpunkte.d.ts +71 -0
  10. package/dist/cjs/inventory/endpunkte.js +285 -0
  11. package/dist/cjs/inventory/fehler.d.ts +33 -0
  12. package/dist/cjs/inventory/fehler.js +47 -0
  13. package/dist/cjs/inventory/index.d.ts +19 -0
  14. package/dist/cjs/inventory/index.js +64 -0
  15. package/dist/cjs/inventory/lesen.d.ts +38 -0
  16. package/dist/cjs/inventory/lesen.js +294 -0
  17. package/dist/cjs/inventory/typen.d.ts +319 -0
  18. package/dist/cjs/inventory/typen.js +14 -0
  19. package/dist/cjs/inventory/vertrag.d.ts +76 -0
  20. package/dist/cjs/inventory/vertrag.js +166 -0
  21. package/dist/cjs/inventory/webhook.d.ts +50 -0
  22. package/dist/cjs/inventory/webhook.js +110 -0
  23. package/dist/cjs/pos/artikel.d.ts +20 -0
  24. package/dist/cjs/pos/artikel.js +8 -0
  25. package/dist/cjs/pos/index.d.ts +1 -1
  26. package/dist/cjs/pos/index.js +2 -1
  27. package/dist/cjs/pos/texte.d.ts +41 -0
  28. package/dist/cjs/pos/texte.js +29 -1
  29. package/dist/cjs/stored/vokabular.d.ts +1 -1
  30. package/dist/cjs/stored/vokabular.js +1 -1
  31. package/dist/cjs/version.d.ts +1 -1
  32. package/dist/cjs/version.js +1 -1
  33. package/dist/esm/client/aufrufe.d.ts +2 -2
  34. package/dist/esm/client/aufrufe.js +30 -0
  35. package/dist/esm/inventory/api.d.ts +45 -0
  36. package/dist/esm/inventory/api.js +35 -0
  37. package/dist/esm/inventory/auth.d.ts +17 -0
  38. package/dist/esm/inventory/auth.js +24 -0
  39. package/dist/esm/inventory/endpunkte.d.ts +71 -0
  40. package/dist/esm/inventory/endpunkte.js +266 -0
  41. package/dist/esm/inventory/fehler.d.ts +33 -0
  42. package/dist/esm/inventory/fehler.js +40 -0
  43. package/dist/esm/inventory/index.d.ts +19 -0
  44. package/dist/esm/inventory/index.js +18 -0
  45. package/dist/esm/inventory/lesen.d.ts +38 -0
  46. package/dist/esm/inventory/lesen.js +278 -0
  47. package/dist/esm/inventory/typen.d.ts +319 -0
  48. package/dist/esm/inventory/typen.js +13 -0
  49. package/dist/esm/inventory/vertrag.d.ts +76 -0
  50. package/dist/esm/inventory/vertrag.js +163 -0
  51. package/dist/esm/inventory/webhook.d.ts +50 -0
  52. package/dist/esm/inventory/webhook.js +101 -0
  53. package/dist/esm/pos/artikel.d.ts +20 -0
  54. package/dist/esm/pos/artikel.js +8 -0
  55. package/dist/esm/pos/index.d.ts +1 -1
  56. package/dist/esm/pos/index.js +1 -1
  57. package/dist/esm/pos/texte.d.ts +41 -0
  58. package/dist/esm/pos/texte.js +28 -0
  59. package/dist/esm/stored/vokabular.d.ts +1 -1
  60. package/dist/esm/stored/vokabular.js +1 -1
  61. package/dist/esm/version.d.ts +1 -1
  62. package/dist/esm/version.js +1 -1
  63. package/fixtures/hobex-hps-codes.json +1 -1
  64. package/fixtures/invoice-api.schema.json +1 -1
  65. package/fixtures/invoice-texts.json +1 -1
  66. package/fixtures/pos-texts.json +36 -1
  67. package/fixtures/surface.json +161 -3
  68. package/fixtures/v3/README.md +9 -1
  69. package/fixtures/v3/antworten/belege.json +2 -2
  70. package/fixtures/v3/antworten/belegmail.json +2 -2
  71. package/fixtures/v3/antworten/kasse-belege.json +2 -2
  72. package/fixtures/v3/antworten/kasse.json +3 -3
  73. package/fixtures/v3/antworten/lager.json +1520 -0
  74. package/fixtures/v3/antworten/rechnungen.json +2 -2
  75. package/fixtures/v3/antworten/storno.json +2 -2
  76. package/fixtures/v3/stored/belege.json +2 -2
  77. package/fixtures/v3/stored/kasse.json +404 -4
  78. package/fixtures/v3/stored/rechnungen.json +2 -2
  79. package/fixtures/v3/v3-vokabular.json +423 -6
  80. package/fixtures/v3/zahlbetrag-faelle.json +2 -2
  81. package/package.json +14 -2
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Der Vertrag der Lager-API (Backend Stufe 5a) als Daten: Endpunkte,
3
+ * Wertkataloge, Ereignisse und Fehlercodes, englisch wie am Draht `/v3`.
4
+ *
5
+ * Quelle ist der Vertrags-Export des Backends (`fixtures/v3/v3-vokabular.json`):
6
+ * `endpoints.public`, die Kataloge `STANDORT_TYP`, `BEWEGUNG_ART`,
7
+ * `BEWEGUNG_QUELLE`, `LAGER_ZUSTAND`, `LAGER_URSACHE`, `ZUSTELLUNG` und
8
+ * `events`. `test/inventory.test.ts` haelt jede Liste deckungsgleich mit
9
+ * dieser Datei; nichts hier wird geraten.
10
+ */
11
+ /** Die 14 Endpunkte, in der Reihenfolge von `endpoints.public`. */
12
+ export declare const INVENTORY_ENDPOINTS: readonly ["getArticle", "listArticles", "lookupArticleByCode", "listLocations", "getStock", "listStock", "listStockMovements", "createWebhook", "updateWebhook", "deleteWebhook", "listWebhooks", "sendWebhookTest", "rotateWebhookSecret", "listWebhookDeliveries"];
13
+ export type InventoryEndpoint = (typeof INVENTORY_ENDPOINTS)[number];
14
+ /** Art eines Standorts (Katalog `STANDORT_TYP`). */
15
+ export declare const LOCATION_TYPES: readonly ["warehouse", "store", "vehicle", "other"];
16
+ export type LocationType = (typeof LOCATION_TYPES)[number];
17
+ /**
18
+ * Art einer Lagerbewegung (Katalog `BEWEGUNG_ART`); zugleich der Filter `type`.
19
+ * `goods_receipt` ist der Wareneingang, `takeover` der uebernommene Anfangsbestand
20
+ * (auch per Import). `receipt` gibt es hier nicht: das ist der Kassenbeleg (Quelle).
21
+ */
22
+ export declare const STOCK_MOVEMENT_TYPES: readonly ["sale", "goods_receipt", "loss", "return", "transfer_out", "transfer_in", "condition_out", "condition_in", "stocktake", "adjustment", "takeover", "reversal", "revaluation", "method_change"];
23
+ export type StockMovementType = (typeof STOCK_MOVEMENT_TYPES)[number];
24
+ /**
25
+ * Woher eine Bewegung kommt (Katalog `BEWEGUNG_QUELLE`); zugleich der Filter
26
+ * `source`. `receipt` ist der Kassenbeleg wie ueberall in der API (der
27
+ * Wareneingang ist die Bewegungsart `goods_receipt`).
28
+ */
29
+ export declare const STOCK_MOVEMENT_SOURCES: readonly ["receipt", "invoice", "cancellation", "credit_note", "panel", "register", "api", "stocktake", "system"];
30
+ export type StockMovementSource = (typeof STOCK_MOVEMENT_SOURCES)[number];
31
+ /** Zustand der Ware an einer Bewegung (Katalog `LAGER_ZUSTAND`). */
32
+ export declare const STOCK_CONDITIONS: readonly ["sellable", "defective"];
33
+ export type StockCondition = (typeof STOCK_CONDITIONS)[number];
34
+ /**
35
+ * Ursache eines `stock.changed` (Katalog `LAGER_URSACHE`), abgeleitet aus der
36
+ * juengsten Bewegung mit Mengenwirkung. `other`: keine Regel passt oder es
37
+ * gibt keine Bewegung (dann ist `movementId` `null`).
38
+ */
39
+ export declare const STOCK_CHANGE_CAUSES: readonly ["sale", "invoice", "credit_note", "cancellation", "goods_receipt", "transfer", "loss", "condition", "reversal", "reservation", "stocktake", "takeover", "other"];
40
+ export type StockChangeCause = (typeof STOCK_CHANGE_CAUSES)[number];
41
+ /** Stand einer Zustellung (Katalog `ZUSTELLUNG`, derselbe wie bei Partner-Webhooks). */
42
+ export declare const WEBHOOK_DELIVERY_STATUSES: readonly ["delivered", "pending", "failed", "dropped"];
43
+ export type WebhookDeliveryStatus = (typeof WEBHOOK_DELIVERY_STATUSES)[number];
44
+ /**
45
+ * Die Ereignisse, die ein Konto-Webhook abonnieren kann (Stufe 5a). Spaetere
46
+ * Stufen ergaenzen `reservation.*` und `variant_group.*`.
47
+ */
48
+ export declare const INVENTORY_WEBHOOK_EVENTS: readonly ["stock.changed", "stock.below_minimum", "article.created", "article.updated", "article.deactivated"];
49
+ export type InventoryWebhookEventType = (typeof INVENTORY_WEBHOOK_EVENTS)[number];
50
+ /**
51
+ * Die Felder der Huelle jeder Zustellung, in der Reihenfolge am Draht. Statt
52
+ * `partnerId` (Partner-Webhooks) traegt sie `accountId`; `test` steht nur auf
53
+ * Probesendungen.
54
+ */
55
+ export declare const INVENTORY_WEBHOOK_ENVELOPE_FIELDS: readonly ["id", "type", "createdAt", "accountId", "test", "data"];
56
+ /** Hoechstzahl der Webhooks je Konto (`webhook_limit`, wie bei Partner-Webhooks). */
57
+ export declare const INVENTORY_WEBHOOK_LIMIT = 5;
58
+ /** Groesstes `limit` einer Liste; ohne Angabe liefert der Server 50. */
59
+ export declare const INVENTORY_LIST_LIMIT_MAX = 200;
60
+ /**
61
+ * Die Codes, die die Lager-Endpunkte selbst senden. `validation` traegt
62
+ * `errors: [{ field, message }]`, `rate_limited` traegt `retryAfterSec`
63
+ * (dazu die Kopfzeile `Retry-After`) – auch bei `sendWebhookTest` nach 20
64
+ * Probesendungen je Wiener Kalendertag (dann bis Mitternacht in Wien).
65
+ */
66
+ export declare const INVENTORY_ERROR_CODES: readonly ["validation", "invalid_cursor", "article_not_found", "webhook_not_found", "webhook_limit", "invalid_webhook_url", "event_not_subscribed", "webhook_inactive", "inventory_api_not_enabled", "module_inactive", "rate_limited", "server_error"];
67
+ export type InventoryErrorCode = (typeof INVENTORY_ERROR_CODES)[number];
68
+ /**
69
+ * Codes, die Anmeldung und Rand auf jedem Lager-Aufruf erzeugen koennen,
70
+ * soweit sie nicht schon in [INVENTORY_ERROR_CODES] stehen: `errorCodes.auth`
71
+ * ohne die des Partner-Zugangs und `errorCodes.edge` (sortiert), zuletzt
72
+ * `route_missing` (Code des Pakets). Dieselbe Ableitung wie bei der
73
+ * Rechnungs-API.
74
+ */
75
+ export declare const INVENTORY_REQUEST_ERROR_CODES: readonly ["account_not_found", "admin_required", "api_not_approved", "cashregister_not_assigned", "cashregister_not_found", "cashregister_token_invalid", "cashregister_token_missing", "dialect_mismatch", "internal_translation_error", "live_not_enabled", "method_not_allowed", "mfa_required", "not_found", "register_user_no_business", "register_user_not_allowed", "register_user_not_found", "response_translation_failed", "session_expired", "session_other_cashregister", "unauthorized", "user_disabled", "user_verification_failed", "route_missing"];
76
+ export type InventoryRequestErrorCode = (typeof INVENTORY_REQUEST_ERROR_CODES)[number];
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ /**
3
+ * Der Vertrag der Lager-API (Backend Stufe 5a) als Daten: Endpunkte,
4
+ * Wertkataloge, Ereignisse und Fehlercodes, englisch wie am Draht `/v3`.
5
+ *
6
+ * Quelle ist der Vertrags-Export des Backends (`fixtures/v3/v3-vokabular.json`):
7
+ * `endpoints.public`, die Kataloge `STANDORT_TYP`, `BEWEGUNG_ART`,
8
+ * `BEWEGUNG_QUELLE`, `LAGER_ZUSTAND`, `LAGER_URSACHE`, `ZUSTELLUNG` und
9
+ * `events`. `test/inventory.test.ts` haelt jede Liste deckungsgleich mit
10
+ * dieser Datei; nichts hier wird geraten.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.INVENTORY_REQUEST_ERROR_CODES = exports.INVENTORY_ERROR_CODES = exports.INVENTORY_LIST_LIMIT_MAX = exports.INVENTORY_WEBHOOK_LIMIT = exports.INVENTORY_WEBHOOK_ENVELOPE_FIELDS = exports.INVENTORY_WEBHOOK_EVENTS = exports.WEBHOOK_DELIVERY_STATUSES = exports.STOCK_CHANGE_CAUSES = exports.STOCK_CONDITIONS = exports.STOCK_MOVEMENT_SOURCES = exports.STOCK_MOVEMENT_TYPES = exports.LOCATION_TYPES = exports.INVENTORY_ENDPOINTS = void 0;
14
+ /** Die 14 Endpunkte, in der Reihenfolge von `endpoints.public`. */
15
+ exports.INVENTORY_ENDPOINTS = [
16
+ 'getArticle',
17
+ 'listArticles',
18
+ 'lookupArticleByCode',
19
+ 'listLocations',
20
+ 'getStock',
21
+ 'listStock',
22
+ 'listStockMovements',
23
+ 'createWebhook',
24
+ 'updateWebhook',
25
+ 'deleteWebhook',
26
+ 'listWebhooks',
27
+ 'sendWebhookTest',
28
+ 'rotateWebhookSecret',
29
+ 'listWebhookDeliveries',
30
+ ];
31
+ /** Art eines Standorts (Katalog `STANDORT_TYP`). */
32
+ exports.LOCATION_TYPES = ['warehouse', 'store', 'vehicle', 'other'];
33
+ /**
34
+ * Art einer Lagerbewegung (Katalog `BEWEGUNG_ART`); zugleich der Filter `type`.
35
+ * `goods_receipt` ist der Wareneingang, `takeover` der uebernommene Anfangsbestand
36
+ * (auch per Import). `receipt` gibt es hier nicht: das ist der Kassenbeleg (Quelle).
37
+ */
38
+ exports.STOCK_MOVEMENT_TYPES = [
39
+ 'sale',
40
+ 'goods_receipt',
41
+ 'loss',
42
+ 'return',
43
+ 'transfer_out',
44
+ 'transfer_in',
45
+ 'condition_out',
46
+ 'condition_in',
47
+ 'stocktake',
48
+ 'adjustment',
49
+ 'takeover',
50
+ 'reversal',
51
+ 'revaluation',
52
+ 'method_change',
53
+ ];
54
+ /**
55
+ * Woher eine Bewegung kommt (Katalog `BEWEGUNG_QUELLE`); zugleich der Filter
56
+ * `source`. `receipt` ist der Kassenbeleg wie ueberall in der API (der
57
+ * Wareneingang ist die Bewegungsart `goods_receipt`).
58
+ */
59
+ exports.STOCK_MOVEMENT_SOURCES = [
60
+ 'receipt',
61
+ 'invoice',
62
+ 'cancellation',
63
+ 'credit_note',
64
+ 'panel',
65
+ 'register',
66
+ 'api',
67
+ 'stocktake',
68
+ 'system',
69
+ ];
70
+ /** Zustand der Ware an einer Bewegung (Katalog `LAGER_ZUSTAND`). */
71
+ exports.STOCK_CONDITIONS = ['sellable', 'defective'];
72
+ /**
73
+ * Ursache eines `stock.changed` (Katalog `LAGER_URSACHE`), abgeleitet aus der
74
+ * juengsten Bewegung mit Mengenwirkung. `other`: keine Regel passt oder es
75
+ * gibt keine Bewegung (dann ist `movementId` `null`).
76
+ */
77
+ exports.STOCK_CHANGE_CAUSES = [
78
+ 'sale',
79
+ 'invoice',
80
+ 'credit_note',
81
+ 'cancellation',
82
+ 'goods_receipt',
83
+ 'transfer',
84
+ 'loss',
85
+ 'condition',
86
+ 'reversal',
87
+ 'reservation',
88
+ 'stocktake',
89
+ 'takeover',
90
+ 'other',
91
+ ];
92
+ /** Stand einer Zustellung (Katalog `ZUSTELLUNG`, derselbe wie bei Partner-Webhooks). */
93
+ exports.WEBHOOK_DELIVERY_STATUSES = ['delivered', 'pending', 'failed', 'dropped'];
94
+ /**
95
+ * Die Ereignisse, die ein Konto-Webhook abonnieren kann (Stufe 5a). Spaetere
96
+ * Stufen ergaenzen `reservation.*` und `variant_group.*`.
97
+ */
98
+ exports.INVENTORY_WEBHOOK_EVENTS = [
99
+ 'stock.changed',
100
+ 'stock.below_minimum',
101
+ 'article.created',
102
+ 'article.updated',
103
+ 'article.deactivated',
104
+ ];
105
+ /**
106
+ * Die Felder der Huelle jeder Zustellung, in der Reihenfolge am Draht. Statt
107
+ * `partnerId` (Partner-Webhooks) traegt sie `accountId`; `test` steht nur auf
108
+ * Probesendungen.
109
+ */
110
+ exports.INVENTORY_WEBHOOK_ENVELOPE_FIELDS = ['id', 'type', 'createdAt', 'accountId', 'test', 'data'];
111
+ /** Hoechstzahl der Webhooks je Konto (`webhook_limit`, wie bei Partner-Webhooks). */
112
+ exports.INVENTORY_WEBHOOK_LIMIT = 5;
113
+ /** Groesstes `limit` einer Liste; ohne Angabe liefert der Server 50. */
114
+ exports.INVENTORY_LIST_LIMIT_MAX = 200;
115
+ /**
116
+ * Die Codes, die die Lager-Endpunkte selbst senden. `validation` traegt
117
+ * `errors: [{ field, message }]`, `rate_limited` traegt `retryAfterSec`
118
+ * (dazu die Kopfzeile `Retry-After`) – auch bei `sendWebhookTest` nach 20
119
+ * Probesendungen je Wiener Kalendertag (dann bis Mitternacht in Wien).
120
+ */
121
+ exports.INVENTORY_ERROR_CODES = [
122
+ 'validation',
123
+ 'invalid_cursor',
124
+ 'article_not_found',
125
+ 'webhook_not_found',
126
+ 'webhook_limit',
127
+ 'invalid_webhook_url',
128
+ 'event_not_subscribed',
129
+ 'webhook_inactive',
130
+ 'inventory_api_not_enabled',
131
+ 'module_inactive',
132
+ 'rate_limited',
133
+ 'server_error',
134
+ ];
135
+ /**
136
+ * Codes, die Anmeldung und Rand auf jedem Lager-Aufruf erzeugen koennen,
137
+ * soweit sie nicht schon in [INVENTORY_ERROR_CODES] stehen: `errorCodes.auth`
138
+ * ohne die des Partner-Zugangs und `errorCodes.edge` (sortiert), zuletzt
139
+ * `route_missing` (Code des Pakets). Dieselbe Ableitung wie bei der
140
+ * Rechnungs-API.
141
+ */
142
+ exports.INVENTORY_REQUEST_ERROR_CODES = [
143
+ 'account_not_found',
144
+ 'admin_required',
145
+ 'api_not_approved',
146
+ 'cashregister_not_assigned',
147
+ 'cashregister_not_found',
148
+ 'cashregister_token_invalid',
149
+ 'cashregister_token_missing',
150
+ 'dialect_mismatch',
151
+ 'internal_translation_error',
152
+ 'live_not_enabled',
153
+ 'method_not_allowed',
154
+ 'mfa_required',
155
+ 'not_found',
156
+ 'register_user_no_business',
157
+ 'register_user_not_allowed',
158
+ 'register_user_not_found',
159
+ 'response_translation_failed',
160
+ 'session_expired',
161
+ 'session_other_cashregister',
162
+ 'unauthorized',
163
+ 'user_disabled',
164
+ 'user_verification_failed',
165
+ 'route_missing',
166
+ ];
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Eingehende Konto-Webhooks der Lager-API: Signatur pruefen, Ereignis lesen.
3
+ *
4
+ * Dasselbe Verfahren wie bei Partner-Webhooks (Backend
5
+ * `gemeinsam/webhook-core.js`, `signaturKopf`/`pruefeSignatur`): Kopf
6
+ * `X-Kasseneck-Signature: t=<unix-sekunden>,v1=<hex>` mit
7
+ * `v1 = HMAC-SHA256(secret, "<t>.<roher Rumpf>")`, Zeitfenster 300 Sekunden in
8
+ * beide Richtungen, zeitkonstanter Vergleich, mehrere `v1=`-Anteile erlaubt.
9
+ * Die Pruefung selbst liegt in `partner/webhook-signatur.ts` und wird hier nur
10
+ * mit der Form `(secret, kopf, rumpf, optionen)` angeboten.
11
+ *
12
+ * Reihenfolge im Empfaenger: **erst pruefen, dann lesen**, und dabei den
13
+ * **rohen** Rumpf nehmen (in Express `express.raw({ type: '*\/*' })` vor jedem
14
+ * JSON-Parser).
15
+ */
16
+ import type { InventoryWebhookEvent } from './typen.js';
17
+ export { WEBHOOK_SIGNATURE_HEADER, WEBHOOK_EVENT_HEADER, WEBHOOK_DELIVERY_HEADER, WEBHOOK_TOLERANCE_SEC, } from '../partner/webhook-signatur.js';
18
+ export interface VerifyInventoryWebhookOptions {
19
+ /** Erlaubte Abweichung des Zeitstempels in Sekunden, in beide Richtungen; Vorgabe 300. */
20
+ toleranceSec?: number;
21
+ /** Jetzt: ein `Date` oder Millisekunden seit 1970 (wie `Date.now()`). Vorgabe: die Systemuhr. */
22
+ now?: Date | number;
23
+ }
24
+ /**
25
+ * Prueft die Signatur einer Zustellung. `true` nur, wenn Kopf, Zeitfenster
26
+ * und HMAC stimmen; jede schlechte Eingabe und jede Ausnahme ist `false`,
27
+ * nie ein Wurf.
28
+ *
29
+ * **Asynchron**, weil die Pruefung WebCrypto (`crypto.subtle`) benutzt: das
30
+ * Paket hat keine Laufzeitabhaengigkeit und laeuft auch im Browser.
31
+ *
32
+ * @param secret das Secret aus `createWebhook`/`rotateWebhookSecret`; eine
33
+ * Liste erlaubt den Wechsel (es reicht, wenn eines passt)
34
+ * @param header der Wert von `X-Kasseneck-Signature`, unveraendert
35
+ * @param rawBody der **rohe** Rumpf (Text oder Bytes), nicht `JSON.parse` + `stringify`
36
+ */
37
+ export declare function verifyInventoryWebhookSignature(secret: string | readonly string[], header: string | null | undefined, rawBody: string | Uint8Array, options?: VerifyInventoryWebhookOptions): Promise<boolean>;
38
+ /**
39
+ * Liest eine Zustellung als typisiertes Ereignis. Vorher die Signatur pruefen
40
+ * ([verifyInventoryWebhookSignature]).
41
+ *
42
+ * - Ein Ereignis, das diese Paketversion nicht kennt (etwa `reservation.*`
43
+ * einer spaeteren Stufe), ergibt `null`: mit 2xx antworten und uebergehen.
44
+ * - Ein Rumpf, der keine Huelle ist, oder eine Bruchzahl in einer Menge wirft
45
+ * `KasseneckValidationError` (`scope: 'response'`).
46
+ *
47
+ * **Entdoppeln** auf `event.id`; **Stand statt Aenderung**: einen gespeicherten
48
+ * Bestand nur ueberschreiben, wenn `data.sequence` groesser ist.
49
+ */
50
+ export declare function parseInventoryWebhookEvent(rawBody: string | Uint8Array): InventoryWebhookEvent | null;
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ /**
3
+ * Eingehende Konto-Webhooks der Lager-API: Signatur pruefen, Ereignis lesen.
4
+ *
5
+ * Dasselbe Verfahren wie bei Partner-Webhooks (Backend
6
+ * `gemeinsam/webhook-core.js`, `signaturKopf`/`pruefeSignatur`): Kopf
7
+ * `X-Kasseneck-Signature: t=<unix-sekunden>,v1=<hex>` mit
8
+ * `v1 = HMAC-SHA256(secret, "<t>.<roher Rumpf>")`, Zeitfenster 300 Sekunden in
9
+ * beide Richtungen, zeitkonstanter Vergleich, mehrere `v1=`-Anteile erlaubt.
10
+ * Die Pruefung selbst liegt in `partner/webhook-signatur.ts` und wird hier nur
11
+ * mit der Form `(secret, kopf, rumpf, optionen)` angeboten.
12
+ *
13
+ * Reihenfolge im Empfaenger: **erst pruefen, dann lesen**, und dabei den
14
+ * **rohen** Rumpf nehmen (in Express `express.raw({ type: '*\/*' })` vor jedem
15
+ * JSON-Parser).
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.WEBHOOK_TOLERANCE_SEC = exports.WEBHOOK_DELIVERY_HEADER = exports.WEBHOOK_EVENT_HEADER = exports.WEBHOOK_SIGNATURE_HEADER = void 0;
19
+ exports.verifyInventoryWebhookSignature = verifyInventoryWebhookSignature;
20
+ exports.parseInventoryWebhookEvent = parseInventoryWebhookEvent;
21
+ const errors_js_1 = require("../client/errors.js");
22
+ const webhook_signatur_js_1 = require("../partner/webhook-signatur.js");
23
+ const lesen_js_1 = require("./lesen.js");
24
+ const vertrag_js_1 = require("./vertrag.js");
25
+ var webhook_signatur_js_2 = require("../partner/webhook-signatur.js");
26
+ Object.defineProperty(exports, "WEBHOOK_SIGNATURE_HEADER", { enumerable: true, get: function () { return webhook_signatur_js_2.WEBHOOK_SIGNATURE_HEADER; } });
27
+ Object.defineProperty(exports, "WEBHOOK_EVENT_HEADER", { enumerable: true, get: function () { return webhook_signatur_js_2.WEBHOOK_EVENT_HEADER; } });
28
+ Object.defineProperty(exports, "WEBHOOK_DELIVERY_HEADER", { enumerable: true, get: function () { return webhook_signatur_js_2.WEBHOOK_DELIVERY_HEADER; } });
29
+ Object.defineProperty(exports, "WEBHOOK_TOLERANCE_SEC", { enumerable: true, get: function () { return webhook_signatur_js_2.WEBHOOK_TOLERANCE_SEC; } });
30
+ /**
31
+ * Prueft die Signatur einer Zustellung. `true` nur, wenn Kopf, Zeitfenster
32
+ * und HMAC stimmen; jede schlechte Eingabe und jede Ausnahme ist `false`,
33
+ * nie ein Wurf.
34
+ *
35
+ * **Asynchron**, weil die Pruefung WebCrypto (`crypto.subtle`) benutzt: das
36
+ * Paket hat keine Laufzeitabhaengigkeit und laeuft auch im Browser.
37
+ *
38
+ * @param secret das Secret aus `createWebhook`/`rotateWebhookSecret`; eine
39
+ * Liste erlaubt den Wechsel (es reicht, wenn eines passt)
40
+ * @param header der Wert von `X-Kasseneck-Signature`, unveraendert
41
+ * @param rawBody der **rohe** Rumpf (Text oder Bytes), nicht `JSON.parse` + `stringify`
42
+ */
43
+ async function verifyInventoryWebhookSignature(secret, header, rawBody, options = {}) {
44
+ try {
45
+ const jetzt = options.now instanceof Date ? options.now.getTime() : options.now;
46
+ const nowSec = typeof jetzt === 'number' && Number.isFinite(jetzt) ? Math.floor(jetzt / 1000) : undefined;
47
+ const r = await (0, webhook_signatur_js_1.verifyWebhookSignature)({
48
+ secret,
49
+ signatureHeader: header,
50
+ body: rawBody,
51
+ ...(nowSec === undefined ? {} : { nowSec }),
52
+ ...(options.toleranceSec === undefined ? {} : { toleranceSec: options.toleranceSec }),
53
+ });
54
+ return r.ok;
55
+ }
56
+ catch {
57
+ return false;
58
+ }
59
+ }
60
+ const BEKANNT = new Set(vertrag_js_1.INVENTORY_WEBHOOK_EVENTS);
61
+ function kaputt(grund) {
62
+ return new errors_js_1.KasseneckValidationError('parseInventoryWebhookEvent', grund, 'response');
63
+ }
64
+ /**
65
+ * Liest eine Zustellung als typisiertes Ereignis. Vorher die Signatur pruefen
66
+ * ([verifyInventoryWebhookSignature]).
67
+ *
68
+ * - Ein Ereignis, das diese Paketversion nicht kennt (etwa `reservation.*`
69
+ * einer spaeteren Stufe), ergibt `null`: mit 2xx antworten und uebergehen.
70
+ * - Ein Rumpf, der keine Huelle ist, oder eine Bruchzahl in einer Menge wirft
71
+ * `KasseneckValidationError` (`scope: 'response'`).
72
+ *
73
+ * **Entdoppeln** auf `event.id`; **Stand statt Aenderung**: einen gespeicherten
74
+ * Bestand nur ueberschreiben, wenn `data.sequence` groesser ist.
75
+ */
76
+ function parseInventoryWebhookEvent(rawBody) {
77
+ const text = typeof rawBody === 'string' ? rawBody : new TextDecoder('utf-8').decode(rawBody);
78
+ let roh;
79
+ try {
80
+ roh = JSON.parse(text);
81
+ }
82
+ catch {
83
+ throw kaputt('Rumpf ist kein JSON');
84
+ }
85
+ const e = (0, lesen_js_1.objekt)(roh);
86
+ if (!e)
87
+ throw kaputt('Rumpf ist kein Ereignis (kein Objekt)');
88
+ const { id, type, createdAt, accountId, data } = e;
89
+ if (typeof id !== 'string' || id === '' || typeof type !== 'string' || type === '')
90
+ throw kaputt('Ereignis ohne id oder type');
91
+ if (typeof createdAt !== 'number' || !Number.isFinite(createdAt))
92
+ throw kaputt('Ereignis ohne createdAt');
93
+ if (typeof accountId !== 'string' || accountId === '')
94
+ throw kaputt('Ereignis ohne accountId');
95
+ if (!BEKANNT.has(type))
96
+ return null;
97
+ const ort = { name: 'parseInventoryWebhookEvent', pfad: 'data' };
98
+ if (!(0, lesen_js_1.objekt)(data))
99
+ throw kaputt('Ereignis ohne data');
100
+ // Nur ein ausdrueckliches `true` ist eine Probe; im Zweifel der Ernstfall.
101
+ const huelle = { id, type: type, createdAt, accountId, test: e.test === true };
102
+ switch (huelle.type) {
103
+ case 'stock.changed':
104
+ return { ...huelle, type: huelle.type, data: (0, lesen_js_1.bestandGeaendert)(ort, data) };
105
+ case 'stock.below_minimum':
106
+ return { ...huelle, type: huelle.type, data: (0, lesen_js_1.unterMindestbestand)(ort, data) };
107
+ default:
108
+ return { ...huelle, type: huelle.type, data: (0, lesen_js_1.artikel)(ort, data) };
109
+ }
110
+ }
@@ -72,6 +72,22 @@ export interface PosArticle {
72
72
  * (`fromPosArticlePayload`) setzt das Feld immer (`null` oder Liste).
73
73
  */
74
74
  stockLocationIds?: string[] | null;
75
+ /**
76
+ * Artikelnummer des Betriebs; null = keine. Diese und die drei folgenden
77
+ * Felder (Scanner-Suche, Lager) sind optional wie `stockLocationIds`, der
78
+ * Leser setzt sie immer. Texte kommen unveraendert durch (fuehrende Nullen,
79
+ * Schreibweise); nur ein leerer Text (auch reiner Leerraum) wird `null`.
80
+ */
81
+ number?: string | null;
82
+ /** EAN/GTIN, wie gespeichert; null = keine. */
83
+ ean?: string | null;
84
+ /** Interner Code des Betriebs (eigener Barcode/QR); null = keiner. */
85
+ internalCode?: string | null;
86
+ /**
87
+ * Bestandsgefuehrt (Lager-Modul). `null`, wenn die Antwort keine Angabe
88
+ * traegt (aeltere Backends) -- dann nicht aus anderen Feldern ableiten.
89
+ */
90
+ stockTracked?: boolean | null;
75
91
  }
76
92
  /** Deckelt eine gewuenschte Menge an der Hoechstmenge des Artikels (null = keine Grenze). */
77
93
  export declare function allowedQuantity(a: Pick<PosArticle, 'maxQuantity'>, wanted: number): number;
@@ -93,6 +109,10 @@ export interface PosArticlePayload {
93
109
  askQuantity?: boolean | null;
94
110
  maxQuantity?: number | null;
95
111
  stockLocationIds?: string[] | null;
112
+ number?: string | null;
113
+ ean?: string | null;
114
+ internalCode?: string | null;
115
+ stockTracked?: boolean | null;
96
116
  }
97
117
  export declare function fromPosArticlePayload(p: PosArticlePayload): PosArticle;
98
118
  /**
@@ -56,6 +56,10 @@ function quantityDefaults(a) {
56
56
  function allowedQuantity(a, wanted) {
57
57
  return a.maxQuantity != null && a.maxQuantity > 0 ? Math.min(wanted, a.maxQuantity) : wanted;
58
58
  }
59
+ /** Ein Text mit Inhalt, unveraendert; leer, nur Leerraum oder kein Text -> null. */
60
+ function textOderNull(wert) {
61
+ return typeof wert === 'string' && wert.trim() !== '' ? wert : null;
62
+ }
59
63
  function fromPosArticlePayload(p) {
60
64
  return {
61
65
  id: p.id ?? '',
@@ -74,6 +78,10 @@ function fromPosArticlePayload(p) {
74
78
  stockLocationIds: Array.isArray(p.stockLocationIds)
75
79
  ? p.stockLocationIds.filter((s) => typeof s === 'string' && s !== '')
76
80
  : null,
81
+ number: textOderNull(p.number),
82
+ ean: textOderNull(p.ean),
83
+ internalCode: textOderNull(p.internalCode),
84
+ stockTracked: typeof p.stockTracked === 'boolean' ? p.stockTracked : null,
77
85
  };
78
86
  }
79
87
  /**
@@ -15,4 +15,4 @@ export { type NetworkPrinter, type PrintJob, type PrintJobStatus, PRINT_JOB_STAT
15
15
  export { listMyTipRecipients } from './trinkgeld.js';
16
16
  export { STOCK_LOCATION_TYPES, type StockLocationType, type StockLocation, type StockLocationAddress, type StockLevel, type StockValue, type StockList, type ListMyStockOptions, type SetMyCashregisterStockLocationOptions, type CashregisterStockLocation, listMyStockLocations, listMyStock, setMyCashregisterStockLocation, } from './lager.js';
17
17
  export { RETURN_DISPOSITIONS, isReturnDisposition, type ReturnDisposition } from '../models/cancellation.js';
18
- export { MESSAGES, ERROR_RULES, ERROR_CODE_RULES, ERROR_OUTCOME_RULES, CALLS_WITH_EFFECT, findErrorRule, messageOutcome, messageText, messageAppliesTo, RECEIPT_EMAIL_ERROR_MESSAGES, receiptEmailErrorMessage, CANCELLATION_PAYMENT_ERROR_MESSAGES, cancellationPaymentErrorMessage, LABELS, labelText, type TextEntry, type MessageKey, type ErrorKind, type ErrorRule, type ErrorRuleDetail, type Surface, type ReceiptEmailMessageCode, type CancellationPaymentMessageCode, type LabelKey, } from './texte.js';
18
+ export { MESSAGES, ERROR_RULES, ERROR_CODE_RULES, ERROR_OUTCOME_RULES, CALLS_WITH_EFFECT, findErrorRule, messageOutcome, messageText, messageAppliesTo, RECEIPT_EMAIL_ERROR_MESSAGES, receiptEmailErrorMessage, CANCELLATION_PAYMENT_ERROR_MESSAGES, cancellationPaymentErrorMessage, LABELS, labelText, RETURN_DISPOSITION_LABELS, type TextEntry, type MessageKey, type ErrorKind, type ErrorRule, type ErrorRuleDetail, type Surface, type ReceiptEmailMessageCode, type CancellationPaymentMessageCode, type LabelKey, } from './texte.js';
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getPosSettings = exports.allowedQuantity = exports.quantityDefaults = exports.quantityRuleForUnit = exports.QUANTITY_RULES = exports.listMyArticles = exports.listMyArticleGroups = exports.fromPosArticlePayload = exports.fromArticleGroupPayload = exports.DONE_SCREEN_SECONDS = exports.WATERMARK_SCALE = exports.LOGO_SCALE = exports.WATERMARK_STRENGTH = exports.WATERMARK_SIDE = exports.DISCOUNT = exports.AUTO_LOGOUT_MINUTES = exports.TILE_STYLE = exports.SETTINGS_FONT_SIZE = exports.LOGO_SIZE = exports.QR_MODE = exports.DRAWER_AUTO_OPEN = exports.CUT = exports.CODE_PAGE = exports.PAPER_SIZE = exports.TERMINAL_TYPE = exports.TERMINAL_VIA = exports.PRINTER_TYPE = exports.TILE_HEIGHT = exports.CATEGORY_POSITION = exports.LAYOUT = exports.RECEIPT_OUTPUT = exports.CARD_PROVIDER = exports.CHECKOUT_MODE = exports.TIP_MODE = exports.QUANTITY = exports.WATERMARK = exports.FONT_SIZE = exports.THEME = exports.posShortcutConflict = exports.POS_SHORTCUT_SHARED_PAIRS = exports.posSettingsChanges = exports.unknownPosSettingValues = exports.sanitizePosSettings = exports.mergePosSettings = exports.POS_DEVICE_VALUES = exports.POS_BUSINESS_VALUES = exports.POS_DEVICE_DEFAULTS = exports.POS_BUSINESS_DEFAULTS = exports.POS_SHORTCUT_DEFAULTS = exports.POS_SHORTCUT_ACTIONS = void 0;
4
- exports.labelText = exports.LABELS = exports.cancellationPaymentErrorMessage = exports.CANCELLATION_PAYMENT_ERROR_MESSAGES = exports.receiptEmailErrorMessage = exports.RECEIPT_EMAIL_ERROR_MESSAGES = exports.messageAppliesTo = exports.messageText = exports.messageOutcome = exports.findErrorRule = exports.CALLS_WITH_EFFECT = exports.ERROR_OUTCOME_RULES = exports.ERROR_CODE_RULES = exports.ERROR_RULES = exports.MESSAGES = exports.isReturnDisposition = exports.RETURN_DISPOSITIONS = exports.setMyCashregisterStockLocation = exports.listMyStock = exports.listMyStockLocations = exports.STOCK_LOCATION_TYPES = exports.listMyTipRecipients = exports.getPrintJob = exports.createPrintJob = exports.listMyPrinters = exports.isPrintJobFinished = exports.PRINT_JOB_SOURCES = exports.PRINT_JOB_STATUSES = exports.stockViewOf = exports.receiptsScopeOf = exports.cancelScopeOf = exports.distributeDiscount = exports.posFieldErrors = exports.isPosError = exports.posErrorCode = exports.isPosErrorCode = exports.POS_ERROR_CODES = exports.posSettingsFromWire = exports.setMyPosLogo = exports.setMyRegisterDeviceSettings = exports.setMyPosSettings = void 0;
4
+ exports.RETURN_DISPOSITION_LABELS = exports.labelText = exports.LABELS = exports.cancellationPaymentErrorMessage = exports.CANCELLATION_PAYMENT_ERROR_MESSAGES = exports.receiptEmailErrorMessage = exports.RECEIPT_EMAIL_ERROR_MESSAGES = exports.messageAppliesTo = exports.messageText = exports.messageOutcome = exports.findErrorRule = exports.CALLS_WITH_EFFECT = exports.ERROR_OUTCOME_RULES = exports.ERROR_CODE_RULES = exports.ERROR_RULES = exports.MESSAGES = exports.isReturnDisposition = exports.RETURN_DISPOSITIONS = exports.setMyCashregisterStockLocation = exports.listMyStock = exports.listMyStockLocations = exports.STOCK_LOCATION_TYPES = exports.listMyTipRecipients = exports.getPrintJob = exports.createPrintJob = exports.listMyPrinters = exports.isPrintJobFinished = exports.PRINT_JOB_SOURCES = exports.PRINT_JOB_STATUSES = exports.stockViewOf = exports.receiptsScopeOf = exports.cancelScopeOf = exports.distributeDiscount = exports.posFieldErrors = exports.isPosError = exports.posErrorCode = exports.isPosErrorCode = exports.POS_ERROR_CODES = exports.posSettingsFromWire = exports.setMyPosLogo = exports.setMyRegisterDeviceSettings = exports.setMyPosSettings = void 0;
5
5
  /**
6
6
  * Kachel-Kasse: Einstellungen, Artikelgruppen/Artikel fuer Kacheln,
7
7
  * Rabattverteilung, Drucker, Trinkgeld-Empfaenger, Lager (Standorte, Bestand,
@@ -116,3 +116,4 @@ Object.defineProperty(exports, "CANCELLATION_PAYMENT_ERROR_MESSAGES", { enumerab
116
116
  Object.defineProperty(exports, "cancellationPaymentErrorMessage", { enumerable: true, get: function () { return texte_js_1.cancellationPaymentErrorMessage; } });
117
117
  Object.defineProperty(exports, "LABELS", { enumerable: true, get: function () { return texte_js_1.LABELS; } });
118
118
  Object.defineProperty(exports, "labelText", { enumerable: true, get: function () { return texte_js_1.labelText; } });
119
+ Object.defineProperty(exports, "RETURN_DISPOSITION_LABELS", { enumerable: true, get: function () { return texte_js_1.RETURN_DISPOSITION_LABELS; } });
@@ -300,6 +300,9 @@ declare const MELDUNGEN_ROH: {
300
300
  readonly 'cancellation.cards_not_checked': {
301
301
  readonly text: "Noch ist nicht jede Karte abgehakt – bitte jede am Terminal gutschreiben. Ist das schon geschehen, zum Schließen noch einmal drücken.";
302
302
  };
303
+ readonly 'cancellation.input_rejected': {
304
+ readonly text: "Die Eingabe wurde abgelehnt – bitte das Storno neu beginnen.";
305
+ };
303
306
  readonly 'split.setting_hint': {
304
307
  readonly text: "Ein Tisch zahlt in Teilen: jede Zahlung bar oder mit Karte, mit eigenem Trinkgeld – am Ende ein Beleg für alles.";
305
308
  };
@@ -1015,9 +1018,47 @@ declare const BESCHRIFTUNGEN_ROH: {
1015
1018
  readonly 'codetable.other_row': {
1016
1019
  readonly text: "Andere Zeile";
1017
1020
  };
1021
+ readonly 'stock.all_articles': {
1022
+ readonly text: "Alle Artikel";
1023
+ };
1024
+ readonly 'stock.location': {
1025
+ readonly text: "Lager-Standort";
1026
+ };
1027
+ readonly 'stock.default_location': {
1028
+ readonly text: "Standard-Standort";
1029
+ };
1030
+ readonly 'stock.resolved': {
1031
+ readonly text: "aufgelöst";
1032
+ };
1033
+ readonly 'stock.where_to': {
1034
+ readonly text: "Wohin mit der Ware?";
1035
+ };
1036
+ readonly 'stock.available': {
1037
+ readonly text: "verfügbar";
1038
+ };
1039
+ readonly 'stock.return_restock': {
1040
+ readonly text: "Zurück ins Lager";
1041
+ };
1042
+ readonly 'stock.return_defective': {
1043
+ readonly text: "Defekt";
1044
+ };
1045
+ readonly 'stock.return_disposed': {
1046
+ readonly text: "Entsorgt";
1047
+ };
1018
1048
  };
1019
1049
  export type LabelKey = keyof typeof BESCHRIFTUNGEN_ROH;
1020
1050
  export declare const LABELS: Record<LabelKey, TextEntry>;
1051
+ /**
1052
+ * Rueckgabe beim Storno (`returnDisposition`): welche Beschriftung jede Wahl
1053
+ * traegt. Ein Objekt wie CANCELLATION_PAYMENT_ERROR_MESSAGES, keine Liste in
1054
+ * GROSSSCHRIFT (der Oberflaechen-Vertrag liest Listen als Enums ein); die
1055
+ * App liest die Zuordnung aus `fixtures/pos-texts.json`.
1056
+ */
1057
+ export declare const RETURN_DISPOSITION_LABELS: {
1058
+ readonly restock: "stock.return_restock";
1059
+ readonly defective: "stock.return_defective";
1060
+ readonly disposed: "stock.return_disposed";
1061
+ };
1021
1062
  /** Die Beschriftung zum Schluessel, Platzhalter ersetzt; fehlt ein Wert, wirft es wie `messageText`. */
1022
1063
  export declare function labelText(key: LabelKey, values?: Record<string, string | number>): string;
1023
1064
  /** Der Satz zum Schluessel, Platzhalter ersetzt. Fehlt ein Wert, wirft es — ein `{status}` am Tresen waere schlimmer. */
@@ -22,7 +22,7 @@
22
22
  * `placeholders` und `structure`).
23
23
  */
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.LABELS = exports.CANCELLATION_PAYMENT_ERROR_MESSAGES = exports.RECEIPT_EMAIL_ERROR_MESSAGES = exports.CALLS_WITH_EFFECT = exports.ERROR_OUTCOME_RULES = exports.ERROR_CODE_RULES = exports.ERROR_RULES = exports.MESSAGES = void 0;
25
+ exports.RETURN_DISPOSITION_LABELS = exports.LABELS = exports.CANCELLATION_PAYMENT_ERROR_MESSAGES = exports.RECEIPT_EMAIL_ERROR_MESSAGES = exports.CALLS_WITH_EFFECT = exports.ERROR_OUTCOME_RULES = exports.ERROR_CODE_RULES = exports.ERROR_RULES = exports.MESSAGES = void 0;
26
26
  exports.findErrorRule = findErrorRule;
27
27
  exports.messageOutcome = messageOutcome;
28
28
  exports.receiptEmailErrorMessage = receiptEmailErrorMessage;
@@ -172,6 +172,10 @@ const MELDUNGEN_ROH = {
172
172
  // nicht jede Karte abgehakt ist: einmal nachfragen -- eine vergessene
173
173
  // Gutschrift faellt sonst erst dem Gast auf.
174
174
  'cancellation.cards_not_checked': { text: 'Noch ist nicht jede Karte abgehakt – bitte jede am Terminal gutschreiben. Ist das schon geschehen, zum Schließen noch einmal drücken.' },
175
+ // Das Backend weist Grund, Notiz oder Positionen des Stornos zurueck
176
+ // (`unknown_reason`, `note_too_long`, `invalid_items`): am Server geschah
177
+ // nichts, der Kassier beginnt das Storno von vorn.
178
+ 'cancellation.input_rejected': { text: 'Die Eingabe wurde abgelehnt – bitte das Storno neu beginnen.' },
175
179
  // --- Getrennt zahlen -----------------------------------------------------
176
180
  // Ein Tisch zahlt in Teilen, ein Beleg fuer alles. Das Teure ist eine schon
177
181
  // belastete Karte: jeder Satz, der sie betrifft, nennt den Betrag, und keiner
@@ -598,8 +602,32 @@ const BESCHRIFTUNGEN_ROH = {
598
602
  'codetable.preview_title': { text: 'So steht es dann am Bon:' },
599
603
  'codetable.apply': { text: 'Übernehmen' },
600
604
  'codetable.other_row': { text: 'Andere Zeile' },
605
+ // --- Lager an der Kasse ----------------------------------------------------
606
+ // Standort-Auswahl, Bestandsanzeige und die Rueckgabe-Wahl beim Storno
607
+ // (`RETURN_DISPOSITION_LABELS`). „aufgelöst“ steht an einem Standort mit
608
+ // `active: false`, „verfügbar“ an der Menge `available`.
609
+ 'stock.all_articles': { text: 'Alle Artikel' },
610
+ 'stock.location': { text: 'Lager-Standort' },
611
+ 'stock.default_location': { text: 'Standard-Standort' },
612
+ 'stock.resolved': { text: 'aufgelöst' },
613
+ 'stock.where_to': { text: 'Wohin mit der Ware?' },
614
+ 'stock.available': { text: 'verfügbar' },
615
+ 'stock.return_restock': { text: 'Zurück ins Lager' },
616
+ 'stock.return_defective': { text: 'Defekt' },
617
+ 'stock.return_disposed': { text: 'Entsorgt' },
601
618
  };
602
619
  exports.LABELS = BESCHRIFTUNGEN_ROH;
620
+ /**
621
+ * Rueckgabe beim Storno (`returnDisposition`): welche Beschriftung jede Wahl
622
+ * traegt. Ein Objekt wie CANCELLATION_PAYMENT_ERROR_MESSAGES, keine Liste in
623
+ * GROSSSCHRIFT (der Oberflaechen-Vertrag liest Listen als Enums ein); die
624
+ * App liest die Zuordnung aus `fixtures/pos-texts.json`.
625
+ */
626
+ exports.RETURN_DISPOSITION_LABELS = {
627
+ restock: 'stock.return_restock',
628
+ defective: 'stock.return_defective',
629
+ disposed: 'stock.return_disposed',
630
+ };
603
631
  /** Die Beschriftung zum Schluessel, Platzhalter ersetzt; fehlt ein Wert, wirft es wie `messageText`. */
604
632
  function labelText(key, values = {}) {
605
633
  return ersetze(`labelText(${key})`, exports.LABELS[key].text, values);
@@ -1,5 +1,5 @@
1
1
  /** Fingerabdruck des Vertrags-Exports, aus dem diese Datei stammt (`_quelle.sha256`). */
2
- export declare const VOKABULAR_QUELLE = "b1049e2f65e9261cf8f729481d9ce1e5afda2cf620333f38ae6bf1afb36c8712";
2
+ export declare const VOKABULAR_QUELLE = "79931a40ccaea45777da4713bba475c2f74e1fe7d6264f294cecd321964f9ded";
3
3
  /** Schema-Notation des Vertrags: Blatt 'aussen': 'innen', Objekt { __: 'innen', ... }, Liste [ { __: 'innen', ... } ]. */
4
4
  export type SchemaEintrag = string | SchemaObjekt | readonly [SchemaObjekt];
5
5
  export interface SchemaObjekt {
@@ -4,7 +4,7 @@
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.KATALOGE = exports.ARTIKEL_FELDER = exports.SCHEMAS = exports.VOKABULAR_QUELLE = void 0;
6
6
  /** Fingerabdruck des Vertrags-Exports, aus dem diese Datei stammt (`_quelle.sha256`). */
7
- exports.VOKABULAR_QUELLE = "b1049e2f65e9261cf8f729481d9ce1e5afda2cf620333f38ae6bf1afb36c8712";
7
+ exports.VOKABULAR_QUELLE = "79931a40ccaea45777da4713bba475c2f74e1fe7d6264f294cecd321964f9ded";
8
8
  /** Schema je Endpunkt (aussen -> innen) und Wertverweise auf die Kataloge. */
9
9
  exports.SCHEMAS = {
10
10
  "getReceipt": {
@@ -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.2.2";
7
+ export declare const PACKAGE_VERSION = "1.4.0";
@@ -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.2.2';
10
+ exports.PACKAGE_VERSION = '1.4.0';