@kreiseck/kasseneck-api 1.3.0 → 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.
- package/CHANGELOG.md +68 -0
- package/README.md +112 -1
- package/dist/cjs/client/aufrufe.d.ts +2 -2
- package/dist/cjs/client/aufrufe.js +30 -0
- package/dist/cjs/inventory/api.d.ts +45 -0
- package/dist/cjs/inventory/api.js +38 -0
- package/dist/cjs/inventory/auth.d.ts +17 -0
- package/dist/cjs/inventory/auth.js +27 -0
- package/dist/cjs/inventory/endpunkte.d.ts +71 -0
- package/dist/cjs/inventory/endpunkte.js +285 -0
- package/dist/cjs/inventory/fehler.d.ts +33 -0
- package/dist/cjs/inventory/fehler.js +47 -0
- package/dist/cjs/inventory/index.d.ts +19 -0
- package/dist/cjs/inventory/index.js +64 -0
- package/dist/cjs/inventory/lesen.d.ts +38 -0
- package/dist/cjs/inventory/lesen.js +294 -0
- package/dist/cjs/inventory/typen.d.ts +319 -0
- package/dist/cjs/inventory/typen.js +14 -0
- package/dist/cjs/inventory/vertrag.d.ts +76 -0
- package/dist/cjs/inventory/vertrag.js +166 -0
- package/dist/cjs/inventory/webhook.d.ts +50 -0
- package/dist/cjs/inventory/webhook.js +110 -0
- package/dist/cjs/stored/vokabular.d.ts +1 -1
- package/dist/cjs/stored/vokabular.js +1 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/client/aufrufe.d.ts +2 -2
- package/dist/esm/client/aufrufe.js +30 -0
- package/dist/esm/inventory/api.d.ts +45 -0
- package/dist/esm/inventory/api.js +35 -0
- package/dist/esm/inventory/auth.d.ts +17 -0
- package/dist/esm/inventory/auth.js +24 -0
- package/dist/esm/inventory/endpunkte.d.ts +71 -0
- package/dist/esm/inventory/endpunkte.js +266 -0
- package/dist/esm/inventory/fehler.d.ts +33 -0
- package/dist/esm/inventory/fehler.js +40 -0
- package/dist/esm/inventory/index.d.ts +19 -0
- package/dist/esm/inventory/index.js +18 -0
- package/dist/esm/inventory/lesen.d.ts +38 -0
- package/dist/esm/inventory/lesen.js +278 -0
- package/dist/esm/inventory/typen.d.ts +319 -0
- package/dist/esm/inventory/typen.js +13 -0
- package/dist/esm/inventory/vertrag.d.ts +76 -0
- package/dist/esm/inventory/vertrag.js +163 -0
- package/dist/esm/inventory/webhook.d.ts +50 -0
- package/dist/esm/inventory/webhook.js +101 -0
- package/dist/esm/stored/vokabular.d.ts +1 -1
- package/dist/esm/stored/vokabular.js +1 -1
- 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 +161 -3
- package/fixtures/v3/README.md +9 -1
- package/fixtures/v3/antworten/belege.json +2 -2
- package/fixtures/v3/antworten/belegmail.json +2 -2
- package/fixtures/v3/antworten/kasse-belege.json +2 -2
- package/fixtures/v3/antworten/kasse.json +3 -3
- package/fixtures/v3/antworten/lager.json +1520 -0
- package/fixtures/v3/antworten/rechnungen.json +2 -2
- package/fixtures/v3/antworten/storno.json +2 -2
- package/fixtures/v3/stored/belege.json +2 -2
- package/fixtures/v3/stored/kasse.json +404 -4
- package/fixtures/v3/stored/rechnungen.json +2 -2
- package/fixtures/v3/v3-vokabular.json +423 -6
- package/fixtures/v3/zahlbetrag-faelle.json +2 -2
- 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
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Fingerabdruck des Vertrags-Exports, aus dem diese Datei stammt (`_quelle.sha256`). */
|
|
2
|
-
export declare const VOKABULAR_QUELLE = "
|
|
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 = "
|
|
7
|
+
exports.VOKABULAR_QUELLE = "79931a40ccaea45777da4713bba475c2f74e1fe7d6264f294cecd321964f9ded";
|
|
8
8
|
/** Schema je Endpunkt (aussen -> innen) und Wertverweise auf die Kataloge. */
|
|
9
9
|
exports.SCHEMAS = {
|
|
10
10
|
"getReceipt": {
|
package/dist/cjs/version.d.ts
CHANGED
package/dist/cjs/version.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* umhuellt, muss ihn weiterhin absetzen koennen.
|
|
14
14
|
*/
|
|
15
15
|
import type { TransportBodyFields } from './transport.js';
|
|
16
|
-
export declare const ALL_CALLS: readonly ["activateCashregister", "cancelInvoice", "cancelReceipt", "createCreditNote", "createCustomer", "createCustomerCashregister", "createPartnerCustomer", "checkPartnerCustomerEmail", "createPartnerWebhook", "createPaymentLinkStripe", "createPrintJob", "createReceipt", "deletePartnerWebhook", "downloadDailyReport", "downloadReport", "endRegisterSession", "financeWebService", "generateFullReceiptId", "getCustomer", "getCustomerCredentials", "getCustomerSignatureStatus", "getFirstReceiptDate", "getInvoice", "getInvoicePdf", "getInvoiceSetupStatus", "getInvoiceXml", "getKasseSettings", "getPartnerCustomer", "getPartnerInfo", "getPrintJob", "getReceipt", "getReportV2", "hobexPayApi", "hobexRefundApi", "issueInvoice", "listCustomerCashregisters", "listInvoices", "listBrands", "listMyArticleGroups", "listMyArticles", "listMyCashregisters", "listMyPrinters", "listMyReceipts", "listMyStock", "listMyStockLocations", "listMyTipRecipients", "listPartnerCustomers", "listPartnerWebhookDeliveries", "listPartnerWebhooks", "listRegisterUsersForDevice", "listRegisterSessionsForDevice", "pairRegisterDevice", "recordInvoicePayment", "registerPinLogin", "registerUserLogin", "renewRegisterSession", "reportCustomerContract", "requestCustomerSignature", "searchCustomers", "sendPartnerCustomerFonLink", "sendPartnerWebhookTest", "sendReceiptEmail", "setMyCashregisterStockLocation", "setMyKasseLogo", "setMyKasseSettings", "setMyRegisterDeviceSettings", "stripeCaptureIntent", "unpairRegisterDevice", "rotatePartnerWebhookSecret", "updateCustomer", "updatePartnerWebhook"];
|
|
16
|
+
export declare const ALL_CALLS: readonly ["activateCashregister", "cancelInvoice", "cancelReceipt", "createCreditNote", "createCustomer", "createCustomerCashregister", "createPartnerCustomer", "checkPartnerCustomerEmail", "createPartnerWebhook", "createPaymentLinkStripe", "createPrintJob", "createReceipt", "deletePartnerWebhook", "downloadDailyReport", "downloadReport", "endRegisterSession", "financeWebService", "generateFullReceiptId", "getCustomer", "getCustomerCredentials", "getCustomerSignatureStatus", "getFirstReceiptDate", "getInvoice", "getInvoicePdf", "getInvoiceSetupStatus", "getInvoiceXml", "getKasseSettings", "getPartnerCustomer", "getPartnerInfo", "getPrintJob", "getReceipt", "getReportV2", "hobexPayApi", "hobexRefundApi", "issueInvoice", "listCustomerCashregisters", "listInvoices", "listBrands", "listMyArticleGroups", "listMyArticles", "listMyCashregisters", "listMyPrinters", "listMyReceipts", "listMyStock", "listMyStockLocations", "listMyTipRecipients", "listPartnerCustomers", "listPartnerWebhookDeliveries", "listPartnerWebhooks", "listRegisterUsersForDevice", "listRegisterSessionsForDevice", "pairRegisterDevice", "recordInvoicePayment", "registerPinLogin", "registerUserLogin", "renewRegisterSession", "reportCustomerContract", "requestCustomerSignature", "searchCustomers", "sendPartnerCustomerFonLink", "sendPartnerWebhookTest", "sendReceiptEmail", "setMyCashregisterStockLocation", "setMyKasseLogo", "setMyKasseSettings", "setMyRegisterDeviceSettings", "stripeCaptureIntent", "unpairRegisterDevice", "rotatePartnerWebhookSecret", "updateCustomer", "updatePartnerWebhook", "getArticle", "listArticles", "lookupArticleByCode", "listLocations", "getStock", "listStock", "listStockMovements", "createWebhook", "updateWebhook", "deleteWebhook", "listWebhooks", "sendWebhookTest", "rotateWebhookSecret", "listWebhookDeliveries"];
|
|
17
17
|
export type ApiCall = typeof ALL_CALLS[number];
|
|
18
18
|
/**
|
|
19
19
|
* Die oeffentlichen Endpunkte unter `/v3` (`https://api.kasseneck.at/v3/<name>`),
|
|
@@ -21,7 +21,7 @@ export type ApiCall = typeof ALL_CALLS[number];
|
|
|
21
21
|
* (`fixtures/v3/v3-vokabular.json`, `endpoints.public`, umbenannt nach
|
|
22
22
|
* `names`). Ein Test haelt beide Listen deckungsgleich.
|
|
23
23
|
*/
|
|
24
|
-
export declare const PUBLIC_CALLS: readonly ["createReceipt", "getReceipt", "cancelReceipt", "sendReceiptEmail", "generateFullReceiptId", "downloadReceipt", "getFirstReceiptDate", "getReportV2", "downloadReport", "downloadDailyReport", "createPaymentLinkStripe", "stripeCaptureIntent", "hobexPayApi", "hobexRefundApi", "hobexGetStatus", "financeWebService", "listMyTipRecipients", "getPartnerInfo", "createPartnerCustomer", "checkPartnerCustomerEmail", "listPartnerCustomers", "getPartnerCustomer", "sendPartnerCustomerFonLink", "createPartnerWebhook", "updatePartnerWebhook", "deletePartnerWebhook", "listPartnerWebhooks", "sendPartnerWebhookTest", "rotatePartnerWebhookSecret", "listPartnerWebhookDeliveries", "requestCustomerSignature", "getCustomerSignatureStatus", "createCustomerCashregister", "activateCashregister", "listCustomerCashregisters", "getCustomerCredentials", "reportCustomerContract", "getPartnerBilling", "getPartnerBillingMonth", "createCustomer", "getCustomer", "updateCustomer", "searchCustomers", "issueInvoice", "cancelInvoice", "createCreditNote", "getInvoice", "listInvoices", "getInvoicePdf", "getInvoiceXml", "getInvoiceSetupStatus", "listBrands", "recordInvoicePayment", "createInvoiceItem", "updateInvoiceItem", "withdrawInvoiceItem", "getInvoiceItem", "listInvoiceItems", "setCustomerMandate", "revokeCustomerMandate"];
|
|
24
|
+
export declare const PUBLIC_CALLS: readonly ["createReceipt", "getReceipt", "cancelReceipt", "sendReceiptEmail", "generateFullReceiptId", "downloadReceipt", "getFirstReceiptDate", "getReportV2", "downloadReport", "downloadDailyReport", "createPaymentLinkStripe", "stripeCaptureIntent", "hobexPayApi", "hobexRefundApi", "hobexGetStatus", "financeWebService", "listMyTipRecipients", "getPartnerInfo", "createPartnerCustomer", "checkPartnerCustomerEmail", "listPartnerCustomers", "getPartnerCustomer", "sendPartnerCustomerFonLink", "createPartnerWebhook", "updatePartnerWebhook", "deletePartnerWebhook", "listPartnerWebhooks", "sendPartnerWebhookTest", "rotatePartnerWebhookSecret", "listPartnerWebhookDeliveries", "requestCustomerSignature", "getCustomerSignatureStatus", "createCustomerCashregister", "activateCashregister", "listCustomerCashregisters", "getCustomerCredentials", "reportCustomerContract", "getPartnerBilling", "getPartnerBillingMonth", "createCustomer", "getCustomer", "updateCustomer", "searchCustomers", "issueInvoice", "cancelInvoice", "createCreditNote", "getInvoice", "listInvoices", "getInvoicePdf", "getInvoiceXml", "getInvoiceSetupStatus", "listBrands", "recordInvoicePayment", "createInvoiceItem", "updateInvoiceItem", "withdrawInvoiceItem", "getInvoiceItem", "listInvoiceItems", "setCustomerMandate", "revokeCustomerMandate", "getArticle", "listArticles", "lookupArticleByCode", "listLocations", "getStock", "listStock", "listStockMovements", "createWebhook", "updateWebhook", "deleteWebhook", "listWebhooks", "sendWebhookTest", "rotateWebhookSecret", "listWebhookDeliveries"];
|
|
25
25
|
/**
|
|
26
26
|
* Die Endpunkte des Kassenwegs (`https://kasse.kasseneck.at/api/v3/<name>`,
|
|
27
27
|
* Web-Kasse: gleicher Ursprung `/api/v3`), in der Reihenfolge von
|
|
@@ -70,6 +70,21 @@ export const ALL_CALLS = [
|
|
|
70
70
|
'rotatePartnerWebhookSecret',
|
|
71
71
|
'updateCustomer',
|
|
72
72
|
'updatePartnerWebhook',
|
|
73
|
+
// Lager-API (Stufe 5a, ./inventory)
|
|
74
|
+
'getArticle',
|
|
75
|
+
'listArticles',
|
|
76
|
+
'lookupArticleByCode',
|
|
77
|
+
'listLocations',
|
|
78
|
+
'getStock',
|
|
79
|
+
'listStock',
|
|
80
|
+
'listStockMovements',
|
|
81
|
+
'createWebhook',
|
|
82
|
+
'updateWebhook',
|
|
83
|
+
'deleteWebhook',
|
|
84
|
+
'listWebhooks',
|
|
85
|
+
'sendWebhookTest',
|
|
86
|
+
'rotateWebhookSecret',
|
|
87
|
+
'listWebhookDeliveries',
|
|
73
88
|
];
|
|
74
89
|
/**
|
|
75
90
|
* Die oeffentlichen Endpunkte unter `/v3` (`https://api.kasseneck.at/v3/<name>`),
|
|
@@ -141,6 +156,21 @@ export const PUBLIC_CALLS = [
|
|
|
141
156
|
'listInvoiceItems',
|
|
142
157
|
'setCustomerMandate',
|
|
143
158
|
'revokeCustomerMandate',
|
|
159
|
+
// Lager-API lesen und Konto-Webhooks (Backend Stufe 5a), umhuellt in `./inventory`.
|
|
160
|
+
'getArticle',
|
|
161
|
+
'listArticles',
|
|
162
|
+
'lookupArticleByCode',
|
|
163
|
+
'listLocations',
|
|
164
|
+
'getStock',
|
|
165
|
+
'listStock',
|
|
166
|
+
'listStockMovements',
|
|
167
|
+
'createWebhook',
|
|
168
|
+
'updateWebhook',
|
|
169
|
+
'deleteWebhook',
|
|
170
|
+
'listWebhooks',
|
|
171
|
+
'sendWebhookTest',
|
|
172
|
+
'rotateWebhookSecret',
|
|
173
|
+
'listWebhookDeliveries',
|
|
144
174
|
];
|
|
145
175
|
/**
|
|
146
176
|
* Die Endpunkte des Kassenwegs (`https://kasse.kasseneck.at/api/v3/<name>`,
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fassade ueber den Aufrufen der Lager-API: Schluessel einmal binden, dann
|
|
3
|
+
* rufen. Wie [createInvoiceApi] bewusst keine Klasse; die Aufrufe sind freie
|
|
4
|
+
* Funktionen (endpunkte.ts) und bleiben einzeln importierbar.
|
|
5
|
+
*/
|
|
6
|
+
import { type FetchLike } from '../client/transport.js';
|
|
7
|
+
import type { Article, ArticleListQuery, ArticleLookup, ArticlePage, CreateInventoryWebhookOptions, InventoryWebhook, InventoryWebhookDelivery, InventoryWebhookList, InventoryWebhookPatch, InventoryWebhookTestResult, InventoryWebhookWithSecret, Location, StockLevel, StockListQuery, StockMovement, StockMovementPage, StockMovementQuery, StockPage, StockResult } from './typen.js';
|
|
8
|
+
import type { InventoryWebhookEventType } from './vertrag.js';
|
|
9
|
+
export interface InventoryClientOptions {
|
|
10
|
+
/** `api_key` des Kontos (`kr_live_…` / `kr_test_…`). Gehoert auf einen Server. */
|
|
11
|
+
apiKey: string;
|
|
12
|
+
/** Abweichende Basis-URL (eigener Proxy); muss auf `/v3` enden. Vorgabe `https://api.kasseneck.at/v3`. */
|
|
13
|
+
baseUrl?: string;
|
|
14
|
+
/** Zeitlimit je Aufruf in Millisekunden. */
|
|
15
|
+
timeoutMs?: number;
|
|
16
|
+
/** Eigene `fetch`-Umsetzung (Tests, Proxys). */
|
|
17
|
+
fetch?: FetchLike;
|
|
18
|
+
}
|
|
19
|
+
export interface InventoryClient {
|
|
20
|
+
getArticle(articleId: string): Promise<Article>;
|
|
21
|
+
listArticles(query?: ArticleListQuery): Promise<ArticlePage>;
|
|
22
|
+
/** Alle Artikel der Abfrage ueber `nextCursor`: `for await (const a of client.iterateArticles())`. */
|
|
23
|
+
iterateArticles(query?: ArticleListQuery): AsyncGenerator<Article, void, undefined>;
|
|
24
|
+
lookupArticleByCode(lookup: ArticleLookup): Promise<Article>;
|
|
25
|
+
listLocations(): Promise<Location[]>;
|
|
26
|
+
getStock(articleId: string): Promise<StockResult>;
|
|
27
|
+
listStock(query?: StockListQuery): Promise<StockPage>;
|
|
28
|
+
iterateStock(query?: StockListQuery): AsyncGenerator<StockLevel, void, undefined>;
|
|
29
|
+
listStockMovements(query?: StockMovementQuery): Promise<StockMovementPage>;
|
|
30
|
+
iterateStockMovements(query?: StockMovementQuery): AsyncGenerator<StockMovement, void, undefined>;
|
|
31
|
+
createWebhook(options: CreateInventoryWebhookOptions): Promise<InventoryWebhookWithSecret>;
|
|
32
|
+
updateWebhook(webhookId: string, patch: InventoryWebhookPatch): Promise<InventoryWebhook>;
|
|
33
|
+
deleteWebhook(webhookId: string): Promise<{
|
|
34
|
+
webhookId: string;
|
|
35
|
+
deleted: boolean;
|
|
36
|
+
}>;
|
|
37
|
+
listWebhooks(): Promise<InventoryWebhookList>;
|
|
38
|
+
sendWebhookTest(webhookId: string, event: InventoryWebhookEventType | (string & {})): Promise<InventoryWebhookTestResult>;
|
|
39
|
+
rotateWebhookSecret(webhookId: string): Promise<InventoryWebhookWithSecret>;
|
|
40
|
+
listWebhookDeliveries(options?: {
|
|
41
|
+
webhookId?: string;
|
|
42
|
+
limit?: number;
|
|
43
|
+
}): Promise<InventoryWebhookDelivery[]>;
|
|
44
|
+
}
|
|
45
|
+
export declare function createInventoryClient(options: InventoryClientOptions): InventoryClient;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fassade ueber den Aufrufen der Lager-API: Schluessel einmal binden, dann
|
|
3
|
+
* rufen. Wie [createInvoiceApi] bewusst keine Klasse; die Aufrufe sind freie
|
|
4
|
+
* Funktionen (endpunkte.ts) und bleiben einzeln importierbar.
|
|
5
|
+
*/
|
|
6
|
+
import { createTransport } from '../client/transport.js';
|
|
7
|
+
import { inventoryKeyAuth } from './auth.js';
|
|
8
|
+
import { createWebhook, deleteWebhook, getArticle, getStock, iterateArticles, iterateStock, iterateStockMovements, listArticles, listLocations, listStock, listStockMovements, listWebhookDeliveries, listWebhooks, lookupArticleByCode, rotateWebhookSecret, sendWebhookTest, updateWebhook, } from './endpunkte.js';
|
|
9
|
+
export function createInventoryClient(options) {
|
|
10
|
+
const rufen = createTransport({
|
|
11
|
+
auth: inventoryKeyAuth({ apiKey: options.apiKey }),
|
|
12
|
+
baseUrl: options.baseUrl,
|
|
13
|
+
timeoutMs: options.timeoutMs,
|
|
14
|
+
fetch: options.fetch,
|
|
15
|
+
});
|
|
16
|
+
return {
|
|
17
|
+
getArticle: (id) => getArticle(rufen, id),
|
|
18
|
+
listArticles: (q) => listArticles(rufen, q),
|
|
19
|
+
iterateArticles: (q) => iterateArticles(rufen, q),
|
|
20
|
+
lookupArticleByCode: (l) => lookupArticleByCode(rufen, l),
|
|
21
|
+
listLocations: () => listLocations(rufen),
|
|
22
|
+
getStock: (id) => getStock(rufen, id),
|
|
23
|
+
listStock: (q) => listStock(rufen, q),
|
|
24
|
+
iterateStock: (q) => iterateStock(rufen, q),
|
|
25
|
+
listStockMovements: (q) => listStockMovements(rufen, q),
|
|
26
|
+
iterateStockMovements: (q) => iterateStockMovements(rufen, q),
|
|
27
|
+
createWebhook: (o) => createWebhook(rufen, o),
|
|
28
|
+
updateWebhook: (id, patch) => updateWebhook(rufen, id, patch),
|
|
29
|
+
deleteWebhook: (id) => deleteWebhook(rufen, id),
|
|
30
|
+
listWebhooks: () => listWebhooks(rufen),
|
|
31
|
+
sendWebhookTest: (id, event) => sendWebhookTest(rufen, id, event),
|
|
32
|
+
rotateWebhookSecret: (id) => rotateWebhookSecret(rufen, id),
|
|
33
|
+
listWebhookDeliveries: (o) => listWebhookDeliveries(rufen, o),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anmeldung fuer die Lager-API: der `api_key` des Kontos als Bearer, ohne
|
|
3
|
+
* `cashregister-token` (gelesen wird am Konto, nicht an einer Kasse).
|
|
4
|
+
*
|
|
5
|
+
* **Der Schluessel gehoert auf einen Server**, etwa in das Backend eines
|
|
6
|
+
* Online-Shops, nie in ein Browser-Buendel.
|
|
7
|
+
*
|
|
8
|
+
* Geprueft wird nur, was ohne Netz sicher falsch ist: ein leerer Wert, ein
|
|
9
|
+
* Partner-Schluessel (`pk_…`) oder ein Kassen-Token (`cb_…`). Die Meldung
|
|
10
|
+
* nennt nie den Wert, nur seine Art.
|
|
11
|
+
*/
|
|
12
|
+
import type { KasseneckAuth } from '../client/auth.js';
|
|
13
|
+
export interface InventoryKeyAuthOptions {
|
|
14
|
+
/** `api_key` des Kontos, z. B. `kr_live_…` oder `kr_test_…`. */
|
|
15
|
+
apiKey: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function inventoryKeyAuth(options: InventoryKeyAuthOptions): KasseneckAuth;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anmeldung fuer die Lager-API: der `api_key` des Kontos als Bearer, ohne
|
|
3
|
+
* `cashregister-token` (gelesen wird am Konto, nicht an einer Kasse).
|
|
4
|
+
*
|
|
5
|
+
* **Der Schluessel gehoert auf einen Server**, etwa in das Backend eines
|
|
6
|
+
* Online-Shops, nie in ein Browser-Buendel.
|
|
7
|
+
*
|
|
8
|
+
* Geprueft wird nur, was ohne Netz sicher falsch ist: ein leerer Wert, ein
|
|
9
|
+
* Partner-Schluessel (`pk_…`) oder ein Kassen-Token (`cb_…`). Die Meldung
|
|
10
|
+
* nennt nie den Wert, nur seine Art.
|
|
11
|
+
*/
|
|
12
|
+
import { KasseneckAuthError } from '../client/errors.js';
|
|
13
|
+
export function inventoryKeyAuth(options) {
|
|
14
|
+
const schluessel = typeof options?.apiKey === 'string' ? options.apiKey.trim() : '';
|
|
15
|
+
if (!schluessel)
|
|
16
|
+
throw new KasseneckAuthError('inventoryKeyAuth: apiKey fehlt');
|
|
17
|
+
if (/^pk_(live|test)_/i.test(schluessel)) {
|
|
18
|
+
throw new KasseneckAuthError('inventoryKeyAuth: das ist ein Partner-Schluessel (pk_…); die Lager-API nimmt den api_key des Kontos (kr_…)');
|
|
19
|
+
}
|
|
20
|
+
if (/^cb_(live|test)_/i.test(schluessel)) {
|
|
21
|
+
throw new KasseneckAuthError('inventoryKeyAuth: das ist ein Kassen-Token (cb_…); die Lager-API nimmt den api_key des Kontos (kr_…)');
|
|
22
|
+
}
|
|
23
|
+
return () => ({ headers: { Authorization: `Bearer ${schluessel}` }, params: {} });
|
|
24
|
+
}
|