@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,278 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Leser der Lager-Antworten: aus dem Draht `/v3` werden die Modelle in
|
|
3
|
+
* `typen.ts`. Paketintern, nicht Teil der Oberflaeche.
|
|
4
|
+
*
|
|
5
|
+
* Regel wie beim Lager an der Kasse (`pos/lager.ts`): eine Menge, ein Betrag
|
|
6
|
+
* oder eine Folgenummer ist eine Ganzzahl, sonst endet der Aufruf mit
|
|
7
|
+
* `KasseneckValidationError` (`scope: 'response'`). Ein Ersatzwert wie `0`
|
|
8
|
+
* waere eine falsche Aussage („kein Bestand“ statt „Antwort kaputt“). Texte
|
|
9
|
+
* sind nachsichtiger: ein fehlender oder fremder Wert wird `null`.
|
|
10
|
+
*
|
|
11
|
+
* Optionale Felder (Einkaufswerte, `externalIds` …) erscheinen im Modell nur,
|
|
12
|
+
* wenn der Server sie sendet: „fehlt“ heisst dort „kein Recht“, nicht „leer“.
|
|
13
|
+
*/
|
|
14
|
+
import { KasseneckValidationError } from '../client/errors.js';
|
|
15
|
+
import { LOCATION_TYPES } from './vertrag.js';
|
|
16
|
+
const hat = (o, k) => Object.prototype.hasOwnProperty.call(o, k);
|
|
17
|
+
export function antwortfehler(name, grund) {
|
|
18
|
+
return new KasseneckValidationError(name, grund, 'response');
|
|
19
|
+
}
|
|
20
|
+
export function objekt(w) {
|
|
21
|
+
return w !== null && typeof w === 'object' && !Array.isArray(w) ? w : null;
|
|
22
|
+
}
|
|
23
|
+
/** Ein Eintrag, der ein Objekt sein muss. */
|
|
24
|
+
function eintrag(ort, w) {
|
|
25
|
+
const o = objekt(w);
|
|
26
|
+
if (!o)
|
|
27
|
+
throw antwortfehler(ort.name, `Antwort ist unbrauchbar (data.${ort.pfad} ist kein Objekt)`);
|
|
28
|
+
return o;
|
|
29
|
+
}
|
|
30
|
+
const text = (w) => (typeof w === 'string' ? w : null);
|
|
31
|
+
/** Eine Kennung, die da sein muss; ohne sie ist der Eintrag nicht zuzuordnen. */
|
|
32
|
+
function kennung(ort, feld, w) {
|
|
33
|
+
if (typeof w !== 'string' || w === '') {
|
|
34
|
+
throw antwortfehler(ort.name, `Antwort enthaelt keine Kennung (data.${ort.pfad}.${feld} fehlt)`);
|
|
35
|
+
}
|
|
36
|
+
return w;
|
|
37
|
+
}
|
|
38
|
+
/** Eine Ganzzahl, die da sein muss. */
|
|
39
|
+
function ganzzahl(ort, feld, w) {
|
|
40
|
+
if (typeof w !== 'number' || !Number.isSafeInteger(w)) {
|
|
41
|
+
throw antwortfehler(ort.name, `Antwort enthaelt keine ganze Zahl (data.${ort.pfad}.${feld})`);
|
|
42
|
+
}
|
|
43
|
+
return w;
|
|
44
|
+
}
|
|
45
|
+
/** Eine Ganzzahl oder `null`; fehlt der Wert, gilt `null`. */
|
|
46
|
+
function ganzzahlOderNull(ort, feld, w) {
|
|
47
|
+
if (w === undefined || w === null)
|
|
48
|
+
return null;
|
|
49
|
+
return ganzzahl(ort, feld, w);
|
|
50
|
+
}
|
|
51
|
+
/** Eine Textabbildung (`externalIds`, `metadata`, `variantAttributes`): nur Texteintraege. */
|
|
52
|
+
function textAbbildung(w) {
|
|
53
|
+
const o = objekt(w);
|
|
54
|
+
if (!o)
|
|
55
|
+
return undefined;
|
|
56
|
+
const raus = {};
|
|
57
|
+
for (const [k, v] of Object.entries(o))
|
|
58
|
+
if (typeof v === 'string')
|
|
59
|
+
raus[k] = v;
|
|
60
|
+
return raus;
|
|
61
|
+
}
|
|
62
|
+
// ---- Artikel ------------------------------------------------------------------
|
|
63
|
+
export function artikel(ort, w) {
|
|
64
|
+
const a = eintrag(ort, w);
|
|
65
|
+
let standorte = [];
|
|
66
|
+
if (a.stockLocationIds !== undefined && a.stockLocationIds !== null) {
|
|
67
|
+
if (!Array.isArray(a.stockLocationIds) || !a.stockLocationIds.every((s) => typeof s === 'string')) {
|
|
68
|
+
throw antwortfehler(ort.name, `Antwort ist unbrauchbar (data.${ort.pfad}.stockLocationIds ist keine Liste von Kennungen)`);
|
|
69
|
+
}
|
|
70
|
+
standorte = [...a.stockLocationIds];
|
|
71
|
+
}
|
|
72
|
+
const vatRate = a.vatRate;
|
|
73
|
+
if (vatRate !== undefined && vatRate !== null && (typeof vatRate !== 'number' || !Number.isFinite(vatRate))) {
|
|
74
|
+
throw antwortfehler(ort.name, `Antwort enthaelt keinen USt-Satz (data.${ort.pfad}.vatRate)`);
|
|
75
|
+
}
|
|
76
|
+
const raus = {
|
|
77
|
+
id: kennung(ort, 'id', a.id),
|
|
78
|
+
name: text(a.name),
|
|
79
|
+
unitPriceCents: ganzzahlOderNull(ort, 'unitPriceCents', a.unitPriceCents),
|
|
80
|
+
vatRate: typeof vatRate === 'number' ? vatRate : null,
|
|
81
|
+
unit: text(a.unit),
|
|
82
|
+
number: text(a.number),
|
|
83
|
+
ean: text(a.ean),
|
|
84
|
+
internalCode: text(a.internalCode),
|
|
85
|
+
groupId: text(a.groupId),
|
|
86
|
+
revenueGroupId: text(a.revenueGroupId),
|
|
87
|
+
stockTracked: a.stockTracked === true,
|
|
88
|
+
stockLocationIds: standorte,
|
|
89
|
+
minStock: ganzzahlOderNull(ort, 'minStock', a.minStock),
|
|
90
|
+
active: a.active !== false,
|
|
91
|
+
createdAt: text(a.createdAt),
|
|
92
|
+
updatedAt: text(a.updatedAt),
|
|
93
|
+
};
|
|
94
|
+
for (const feld of ['externalIds', 'metadata', 'variantAttributes']) {
|
|
95
|
+
const abb = textAbbildung(a[feld]);
|
|
96
|
+
if (abb)
|
|
97
|
+
raus[feld] = abb;
|
|
98
|
+
}
|
|
99
|
+
if (typeof a.variantGroupId === 'string')
|
|
100
|
+
raus.variantGroupId = a.variantGroupId;
|
|
101
|
+
// Nur mit dem Recht `costs`; ohne fehlt das Feld ganz.
|
|
102
|
+
if (hat(a, 'purchasePriceMicros'))
|
|
103
|
+
raus.purchasePriceMicros = ganzzahlOderNull(ort, 'purchasePriceMicros', a.purchasePriceMicros);
|
|
104
|
+
return raus;
|
|
105
|
+
}
|
|
106
|
+
// ---- Standorte ------------------------------------------------------------------
|
|
107
|
+
const TYPEN = new Set(LOCATION_TYPES);
|
|
108
|
+
const textOderNull = (w) => (typeof w === 'string' && w !== '' ? w : null);
|
|
109
|
+
export function standort(ort, w) {
|
|
110
|
+
const s = eintrag(ort, w);
|
|
111
|
+
const a = objekt(s.address);
|
|
112
|
+
const teile = a ? { street: textOderNull(a.street), zip: textOderNull(a.zip), city: textOderNull(a.city), country: textOderNull(a.country) } : null;
|
|
113
|
+
return {
|
|
114
|
+
id: kennung(ort, 'id', s.id),
|
|
115
|
+
name: typeof s.name === 'string' ? s.name : '',
|
|
116
|
+
type: typeof s.type === 'string' && TYPEN.has(s.type) ? s.type : null,
|
|
117
|
+
// Eine Adresse ohne einen einzigen Teil ist keine Adresse.
|
|
118
|
+
address: teile && Object.values(teile).some((t) => t !== null) ? teile : null,
|
|
119
|
+
licensePlate: textOderNull(s.licensePlate),
|
|
120
|
+
active: s.active !== false,
|
|
121
|
+
virtual: s.virtual === true,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
// ---- Bestand ------------------------------------------------------------------
|
|
125
|
+
export function bestand(ort, w) {
|
|
126
|
+
const b = eintrag(ort, w);
|
|
127
|
+
return {
|
|
128
|
+
articleId: kennung(ort, 'articleId', b.articleId),
|
|
129
|
+
locationId: kennung(ort, 'locationId', b.locationId),
|
|
130
|
+
onHand: ganzzahl(ort, 'onHand', b.onHand),
|
|
131
|
+
reserved: ganzzahl(ort, 'reserved', b.reserved),
|
|
132
|
+
available: ganzzahl(ort, 'available', b.available),
|
|
133
|
+
defective: ganzzahl(ort, 'defective', b.defective),
|
|
134
|
+
sequence: ganzzahl(ort, 'sequence', b.sequence),
|
|
135
|
+
updatedAt: text(b.updatedAt),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
export function wert(ort, w) {
|
|
139
|
+
const v = eintrag(ort, w);
|
|
140
|
+
return {
|
|
141
|
+
articleId: kennung(ort, 'articleId', v.articleId),
|
|
142
|
+
stockValueCents: ganzzahl(ort, 'stockValueCents', v.stockValueCents),
|
|
143
|
+
averageCostMicros: ganzzahlOderNull(ort, 'averageCostMicros', v.averageCostMicros),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
// ---- Bewegungen ------------------------------------------------------------------
|
|
147
|
+
function los(ort, w) {
|
|
148
|
+
const l = eintrag(ort, w);
|
|
149
|
+
const raus = {
|
|
150
|
+
lotId: text(l.lotId),
|
|
151
|
+
quantity: ganzzahl(ort, 'quantity', l.quantity),
|
|
152
|
+
expiresOn: text(l.expiresOn),
|
|
153
|
+
batch: text(l.batch),
|
|
154
|
+
serialNumber: text(l.serialNumber),
|
|
155
|
+
receivedAt: text(l.receivedAt),
|
|
156
|
+
};
|
|
157
|
+
if (hat(l, 'valueCents'))
|
|
158
|
+
raus.valueCents = ganzzahlOderNull(ort, 'valueCents', l.valueCents);
|
|
159
|
+
return raus;
|
|
160
|
+
}
|
|
161
|
+
export function bewegung(ort, w) {
|
|
162
|
+
const b = eintrag(ort, w);
|
|
163
|
+
const nachher = objekt(b.stockAfter);
|
|
164
|
+
const quelle = objekt(b.source);
|
|
165
|
+
const lose = b.lots === undefined || b.lots === null ? [] : b.lots;
|
|
166
|
+
if (!Array.isArray(lose))
|
|
167
|
+
throw antwortfehler(ort.name, `Antwort ist unbrauchbar (data.${ort.pfad}.lots ist keine Liste)`);
|
|
168
|
+
const nachherOrt = { name: ort.name, pfad: `${ort.pfad}.stockAfter` };
|
|
169
|
+
const raus = {
|
|
170
|
+
id: kennung(ort, 'id', b.id),
|
|
171
|
+
type: text(b.type),
|
|
172
|
+
articleId: text(b.articleId),
|
|
173
|
+
locationId: text(b.locationId),
|
|
174
|
+
condition: text(b.condition),
|
|
175
|
+
quantityDelta: ganzzahl(ort, 'quantityDelta', b.quantityDelta),
|
|
176
|
+
stockAfter: nachher
|
|
177
|
+
? { sellable: ganzzahl(nachherOrt, 'sellable', nachher.sellable), defective: ganzzahl(nachherOrt, 'defective', nachher.defective) }
|
|
178
|
+
: null,
|
|
179
|
+
operationId: text(b.operationId),
|
|
180
|
+
source: quelle
|
|
181
|
+
? {
|
|
182
|
+
type: text(quelle.type),
|
|
183
|
+
id: text(quelle.id),
|
|
184
|
+
register: text(quelle.register),
|
|
185
|
+
position: typeof quelle.position === 'number' && Number.isSafeInteger(quelle.position) ? quelle.position : null,
|
|
186
|
+
}
|
|
187
|
+
: null,
|
|
188
|
+
viennaDay: text(b.viennaDay),
|
|
189
|
+
time: text(b.time),
|
|
190
|
+
lots: lose.map((l, i) => los({ name: ort.name, pfad: `${ort.pfad}.lots[${i}]` }, l)),
|
|
191
|
+
};
|
|
192
|
+
if (hat(b, 'valueDeltaCents'))
|
|
193
|
+
raus.valueDeltaCents = ganzzahlOderNull(ort, 'valueDeltaCents', b.valueDeltaCents);
|
|
194
|
+
if (hat(b, 'consumedValueCents'))
|
|
195
|
+
raus.consumedValueCents = ganzzahlOderNull(ort, 'consumedValueCents', b.consumedValueCents);
|
|
196
|
+
return raus;
|
|
197
|
+
}
|
|
198
|
+
// ---- Webhooks ------------------------------------------------------------------
|
|
199
|
+
const zahlOderNull = (w) => (typeof w === 'number' && Number.isFinite(w) ? w : null);
|
|
200
|
+
export function webhook(ort, w) {
|
|
201
|
+
const h = eintrag(ort, w);
|
|
202
|
+
const z = objekt(h.lastDelivery);
|
|
203
|
+
return {
|
|
204
|
+
id: kennung(ort, 'id', h.id),
|
|
205
|
+
url: typeof h.url === 'string' ? h.url : '',
|
|
206
|
+
events: Array.isArray(h.events) ? h.events.filter((e) => typeof e === 'string') : [],
|
|
207
|
+
active: h.active !== false,
|
|
208
|
+
description: text(h.description),
|
|
209
|
+
createdAt: text(h.createdAt),
|
|
210
|
+
lastDelivery: z ? { at: text(z.at), status: text(z.status), statusCode: zahlOderNull(z.statusCode) } : null,
|
|
211
|
+
consecutiveFailures: typeof h.consecutiveFailures === 'number' && Number.isSafeInteger(h.consecutiveFailures) ? h.consecutiveFailures : 0,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
export function zustellung(ort, w) {
|
|
215
|
+
const z = eintrag(ort, w);
|
|
216
|
+
return {
|
|
217
|
+
deliveryId: kennung(ort, 'deliveryId', z.deliveryId),
|
|
218
|
+
webhookId: text(z.webhookId),
|
|
219
|
+
event: text(z.event),
|
|
220
|
+
eventId: text(z.eventId),
|
|
221
|
+
status: text(z.status),
|
|
222
|
+
attempts: typeof z.attempts === 'number' && Number.isSafeInteger(z.attempts) ? z.attempts : 0,
|
|
223
|
+
statusCode: zahlOderNull(z.statusCode),
|
|
224
|
+
response: text(z.response),
|
|
225
|
+
error: text(z.error),
|
|
226
|
+
createdAt: text(z.createdAt),
|
|
227
|
+
lastAttemptAt: text(z.lastAttemptAt),
|
|
228
|
+
nextAttemptAt: text(z.nextAttemptAt),
|
|
229
|
+
test: z.test === true,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
export function probeZustellung(ort, w, webhookId) {
|
|
233
|
+
const z = eintrag(ort, w);
|
|
234
|
+
return {
|
|
235
|
+
deliveryId: kennung(ort, 'deliveryId', z.deliveryId),
|
|
236
|
+
webhookId: typeof z.webhookId === 'string' && z.webhookId ? z.webhookId : webhookId,
|
|
237
|
+
status: text(z.status),
|
|
238
|
+
statusCode: zahlOderNull(z.statusCode),
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
// ---- Ereignisse ------------------------------------------------------------------
|
|
242
|
+
export function bestandGeaendert(ort, w) {
|
|
243
|
+
const d = eintrag(ort, w);
|
|
244
|
+
const ursache = d.cause;
|
|
245
|
+
if (typeof ursache !== 'string' || ursache === '')
|
|
246
|
+
throw antwortfehler(ort.name, `Ereignis ohne Ursache (${ort.pfad}.cause)`);
|
|
247
|
+
return { ...bestand(ort, d), cause: ursache, movementId: textOderNull(d.movementId) };
|
|
248
|
+
}
|
|
249
|
+
export function unterMindestbestand(ort, w) {
|
|
250
|
+
const d = eintrag(ort, w);
|
|
251
|
+
return {
|
|
252
|
+
articleId: kennung(ort, 'articleId', d.articleId),
|
|
253
|
+
locationId: kennung(ort, 'locationId', d.locationId),
|
|
254
|
+
available: ganzzahl(ort, 'available', d.available),
|
|
255
|
+
minStock: ganzzahl(ort, 'minStock', d.minStock),
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
// ---- Listen ------------------------------------------------------------------
|
|
259
|
+
/** Eine zugesagte Liste `data.<feld>`, Eintrag fuer Eintrag gelesen. */
|
|
260
|
+
export function liste(name, daten, feld, lesen) {
|
|
261
|
+
const roh = objekt(daten)?.[feld];
|
|
262
|
+
if (!Array.isArray(roh)) {
|
|
263
|
+
const grund = roh === undefined || roh === null
|
|
264
|
+
? `Antwort enthaelt keine Liste (data.${feld} fehlt)`
|
|
265
|
+
: `Antwort ist unbrauchbar (data.${feld} ist keine Liste)`;
|
|
266
|
+
throw antwortfehler(name, grund);
|
|
267
|
+
}
|
|
268
|
+
return roh.map((e, i) => lesen({ name, pfad: `${feld}[${i}]` }, e));
|
|
269
|
+
}
|
|
270
|
+
/** Der Cursor der naechsten Seite; `null` am Ende. Etwas anderes als Text oder `null` ist kaputt. */
|
|
271
|
+
export function naechsterCursor(name, daten) {
|
|
272
|
+
const c = objekt(daten)?.nextCursor;
|
|
273
|
+
if (c === undefined || c === null)
|
|
274
|
+
return null;
|
|
275
|
+
if (typeof c !== 'string' || c === '')
|
|
276
|
+
throw antwortfehler(name, 'Antwort ist unbrauchbar (data.nextCursor)');
|
|
277
|
+
return c;
|
|
278
|
+
}
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Die Modelle der Lager-API, so wie sie am Draht `/v3` stehen.
|
|
3
|
+
*
|
|
4
|
+
* **Ganzzahlen mit fester Skala:** Mengen in Tausendstel der Basiseinheit
|
|
5
|
+
* (`1000` = 1 Stueck, `250` = 0,250 kg), Geld in Cent, Einkaufspreise in
|
|
6
|
+
* Mikro-Euro (`1_000_000` = 1 €). Nichts davon wird geteilt oder gerundet;
|
|
7
|
+
* eine Bruchzahl in einer Antwort ist ein Antwortfehler
|
|
8
|
+
* (`KasseneckValidationError`, `scope: 'response'`), nie ein Ersatzwert.
|
|
9
|
+
*
|
|
10
|
+
* Zeitpunkte sind ISO 8601 in UTC (`2026-10-06T08:15:00.000Z`), Tage (Wiener
|
|
11
|
+
* Tag) `YYYY-MM-DD`.
|
|
12
|
+
*/
|
|
13
|
+
import type { InventoryWebhookEventType, LocationType, StockChangeCause, StockCondition, StockMovementSource, StockMovementType, WebhookDeliveryStatus } from './vertrag.js';
|
|
14
|
+
/**
|
|
15
|
+
* Ein Artikel, wie `getArticle`, `listArticles`, `lookupArticleByCode` und die
|
|
16
|
+
* Ereignisse `article.*` ihn senden.
|
|
17
|
+
*
|
|
18
|
+
* Optionale Felder fehlen ganz, wenn der Server sie nicht sendet:
|
|
19
|
+
* `purchasePriceMicros` nur mit dem Recht `costs` (Konto-Schalter
|
|
20
|
+
* `lagerApi.kosten`, sonst fehlt das Feld, nicht `null`), `externalIds`,
|
|
21
|
+
* `metadata`, `variantGroupId` und `variantAttributes` nur, wenn der Artikel
|
|
22
|
+
* sie traegt.
|
|
23
|
+
*/
|
|
24
|
+
export interface Article {
|
|
25
|
+
id: string;
|
|
26
|
+
name: string | null;
|
|
27
|
+
unitPriceCents: number | null;
|
|
28
|
+
/** USt-Satz in Prozent, z. B. `20`, `10`, `4.9`. */
|
|
29
|
+
vatRate: number | null;
|
|
30
|
+
unit: string | null;
|
|
31
|
+
number: string | null;
|
|
32
|
+
ean: string | null;
|
|
33
|
+
internalCode: string | null;
|
|
34
|
+
groupId: string | null;
|
|
35
|
+
revenueGroupId: string | null;
|
|
36
|
+
stockTracked: boolean;
|
|
37
|
+
/** Standorte, an denen der Artikel gefuehrt wird; leer = nur der Standard-Standort. */
|
|
38
|
+
stockLocationIds: string[];
|
|
39
|
+
/**
|
|
40
|
+
* Mindestbestand des Artikels in Tausendstel; `null` = keiner. Warnungen,
|
|
41
|
+
* `belowMinimum` und `stock.below_minimum` richten sich nach dem Mindestbestand je
|
|
42
|
+
* Standort, nicht nach diesem Wert.
|
|
43
|
+
*/
|
|
44
|
+
minStock: number | null;
|
|
45
|
+
active: boolean;
|
|
46
|
+
externalIds?: Record<string, string>;
|
|
47
|
+
metadata?: Record<string, string>;
|
|
48
|
+
variantGroupId?: string;
|
|
49
|
+
variantAttributes?: Record<string, string>;
|
|
50
|
+
createdAt: string | null;
|
|
51
|
+
updatedAt: string | null;
|
|
52
|
+
/**
|
|
53
|
+
* Einkaufspreis je Basiseinheit in Mikro-Euro (Wiederbeschaffungs- vor
|
|
54
|
+
* letztem vor Standard-Einkaufspreis); `null` = keiner hinterlegt. Fehlt
|
|
55
|
+
* ganz ohne das Recht `costs`.
|
|
56
|
+
*/
|
|
57
|
+
purchasePriceMicros?: number | null;
|
|
58
|
+
}
|
|
59
|
+
export interface ArticleListQuery {
|
|
60
|
+
/**
|
|
61
|
+
* Nur Artikel, die seitdem geaendert wurden (inklusive). Die Liste ist nach
|
|
62
|
+
* `updatedAt` aufsteigend sortiert: wer sich das `updatedAt` des letzten
|
|
63
|
+
* Treffers merkt und damit wieder fragt, verliert nichts.
|
|
64
|
+
*/
|
|
65
|
+
updatedSince?: string | Date;
|
|
66
|
+
groupId?: string;
|
|
67
|
+
variantGroupId?: string;
|
|
68
|
+
active?: boolean;
|
|
69
|
+
stockTracked?: boolean;
|
|
70
|
+
/** 1–200, Vorgabe des Servers 50. */
|
|
71
|
+
limit?: number;
|
|
72
|
+
/** `nextCursor` der vorigen Seite. */
|
|
73
|
+
cursor?: string;
|
|
74
|
+
}
|
|
75
|
+
export interface ArticlePage {
|
|
76
|
+
articles: Article[];
|
|
77
|
+
/** `null` = letzte Seite. */
|
|
78
|
+
nextCursor: string | null;
|
|
79
|
+
}
|
|
80
|
+
/** Ein Artikel per Code (`number`, `ean`, `internalCode`) oder per eigener Kennung. */
|
|
81
|
+
export type ArticleLookup = string | {
|
|
82
|
+
code: string;
|
|
83
|
+
} | {
|
|
84
|
+
externalSystem: string;
|
|
85
|
+
externalId: string;
|
|
86
|
+
};
|
|
87
|
+
export interface LocationAddress {
|
|
88
|
+
street: string | null;
|
|
89
|
+
zip: string | null;
|
|
90
|
+
city: string | null;
|
|
91
|
+
country: string | null;
|
|
92
|
+
}
|
|
93
|
+
export interface Location {
|
|
94
|
+
id: string;
|
|
95
|
+
name: string;
|
|
96
|
+
/** `null`: ein Typ, den diese Paketversion nicht kennt. */
|
|
97
|
+
type: LocationType | null;
|
|
98
|
+
address: LocationAddress | null;
|
|
99
|
+
/** Kennzeichen, nur bei `vehicle`. */
|
|
100
|
+
licensePlate: string | null;
|
|
101
|
+
/** `false` = aufgeloest. */
|
|
102
|
+
active: boolean;
|
|
103
|
+
/** `true` = Hauptstandort, den der Server ohne eigenes Dokument ergaenzt. */
|
|
104
|
+
virtual: boolean;
|
|
105
|
+
}
|
|
106
|
+
/** Bestand eines Artikels an einem Standort, Mengen in Tausendstel. */
|
|
107
|
+
export interface StockLevel {
|
|
108
|
+
articleId: string;
|
|
109
|
+
locationId: string;
|
|
110
|
+
/** Verkaufbare Menge am Standort. */
|
|
111
|
+
onHand: number;
|
|
112
|
+
/** Reserviert (Checkout im Shop). */
|
|
113
|
+
reserved: number;
|
|
114
|
+
/** `onHand - reserved`, vom Server gerechnet; darf negativ sein (die Kasse verkauft trotzdem). */
|
|
115
|
+
available: number;
|
|
116
|
+
defective: number;
|
|
117
|
+
/**
|
|
118
|
+
* Steigt bei jedem Schreiben dieses Bestands um 1. Einen gespeicherten Stand
|
|
119
|
+
* nur ueberschreiben, wenn `sequence` groesser ist: so richten doppelte oder
|
|
120
|
+
* verspaetete Ereignisse nichts an.
|
|
121
|
+
*/
|
|
122
|
+
sequence: number;
|
|
123
|
+
updatedAt: string | null;
|
|
124
|
+
}
|
|
125
|
+
/** Lagerwert eines Artikels, nur mit dem Recht `costs`. */
|
|
126
|
+
export interface StockValue {
|
|
127
|
+
articleId: string;
|
|
128
|
+
stockValueCents: number;
|
|
129
|
+
/** Durchschnittlicher Einstandspreis je Basiseinheit in Mikro-Euro; `null` bei Menge 0. */
|
|
130
|
+
averageCostMicros: number | null;
|
|
131
|
+
}
|
|
132
|
+
export interface StockResult {
|
|
133
|
+
stock: StockLevel[];
|
|
134
|
+
/** `null` ohne das Recht `costs` (der Server laesst das Feld weg), sonst die Werte. */
|
|
135
|
+
values: StockValue[] | null;
|
|
136
|
+
}
|
|
137
|
+
export interface StockListQuery {
|
|
138
|
+
locationId?: string;
|
|
139
|
+
articleId?: string;
|
|
140
|
+
/**
|
|
141
|
+
* `true`: nur Zeilen, deren `onHand` unter dem Mindestbestand ihres Standorts liegt
|
|
142
|
+
* (dieselbe Regel wie `stock.below_minimum`; `minStock` des Artikels zaehlt nicht).
|
|
143
|
+
*/
|
|
144
|
+
belowMinimum?: boolean;
|
|
145
|
+
/** Nur Zeilen, die sich seitdem geaendert haben (inklusive), nach `updatedAt` aufsteigend. */
|
|
146
|
+
changedSince?: string | Date;
|
|
147
|
+
limit?: number;
|
|
148
|
+
cursor?: string;
|
|
149
|
+
}
|
|
150
|
+
export interface StockPage extends StockResult {
|
|
151
|
+
nextCursor: string | null;
|
|
152
|
+
}
|
|
153
|
+
export interface StockMovementLot {
|
|
154
|
+
lotId: string | null;
|
|
155
|
+
quantity: number;
|
|
156
|
+
expiresOn: string | null;
|
|
157
|
+
batch: string | null;
|
|
158
|
+
serialNumber: string | null;
|
|
159
|
+
receivedAt: string | null;
|
|
160
|
+
/** Nur mit dem Recht `costs`. */
|
|
161
|
+
valueCents?: number | null;
|
|
162
|
+
}
|
|
163
|
+
export interface StockMovementSourceRef {
|
|
164
|
+
type: StockMovementSource | (string & {}) | null;
|
|
165
|
+
/** Kennung des Belegs, der Rechnung o. Ae. */
|
|
166
|
+
id: string | null;
|
|
167
|
+
/** Kasse, an der verkauft wurde. */
|
|
168
|
+
register: string | null;
|
|
169
|
+
/** Position im Beleg bzw. in der Rechnung. */
|
|
170
|
+
position: number | null;
|
|
171
|
+
}
|
|
172
|
+
/** Eine Zeile des Lagerprotokolls; neueste zuerst. */
|
|
173
|
+
export interface StockMovement {
|
|
174
|
+
id: string;
|
|
175
|
+
type: StockMovementType | (string & {}) | null;
|
|
176
|
+
articleId: string | null;
|
|
177
|
+
locationId: string | null;
|
|
178
|
+
condition: StockCondition | (string & {}) | null;
|
|
179
|
+
/** Mengenaenderung in Tausendstel (Abgang negativ). */
|
|
180
|
+
quantityDelta: number;
|
|
181
|
+
/** Bestand am Standort nach der Bewegung. */
|
|
182
|
+
stockAfter: {
|
|
183
|
+
sellable: number;
|
|
184
|
+
defective: number;
|
|
185
|
+
} | null;
|
|
186
|
+
operationId: string | null;
|
|
187
|
+
source: StockMovementSourceRef | null;
|
|
188
|
+
/** Wiener Tag `YYYY-MM-DD`. */
|
|
189
|
+
viennaDay: string | null;
|
|
190
|
+
time: string | null;
|
|
191
|
+
lots: StockMovementLot[];
|
|
192
|
+
/** Nur mit dem Recht `costs`. */
|
|
193
|
+
valueDeltaCents?: number | null;
|
|
194
|
+
/** Nur mit dem Recht `costs`. */
|
|
195
|
+
consumedValueCents?: number | null;
|
|
196
|
+
}
|
|
197
|
+
export interface StockMovementQuery {
|
|
198
|
+
/** Nur nach `articleId` **oder** `locationId` filtern, nicht beides. */
|
|
199
|
+
articleId?: string;
|
|
200
|
+
locationId?: string;
|
|
201
|
+
from?: string | Date;
|
|
202
|
+
to?: string | Date;
|
|
203
|
+
type?: StockMovementType;
|
|
204
|
+
source?: StockMovementSource;
|
|
205
|
+
limit?: number;
|
|
206
|
+
cursor?: string;
|
|
207
|
+
}
|
|
208
|
+
export interface StockMovementPage {
|
|
209
|
+
movements: StockMovement[];
|
|
210
|
+
nextCursor: string | null;
|
|
211
|
+
}
|
|
212
|
+
export interface InventoryWebhook {
|
|
213
|
+
id: string;
|
|
214
|
+
url: string;
|
|
215
|
+
events: (InventoryWebhookEventType | (string & {}))[];
|
|
216
|
+
active: boolean;
|
|
217
|
+
description: string | null;
|
|
218
|
+
createdAt: string | null;
|
|
219
|
+
/** Die letzte Zustellung; `null`, solange keine versucht wurde. */
|
|
220
|
+
lastDelivery: {
|
|
221
|
+
at: string | null;
|
|
222
|
+
status: WebhookDeliveryStatus | (string & {}) | null;
|
|
223
|
+
statusCode: number | null;
|
|
224
|
+
} | null;
|
|
225
|
+
/** Fehlversuche in Folge (wie bei Partner-Webhooks); steigt der Wert, stimmt beim Empfaenger etwas nicht. */
|
|
226
|
+
consecutiveFailures: number;
|
|
227
|
+
}
|
|
228
|
+
export interface CreateInventoryWebhookOptions {
|
|
229
|
+
/** Vollstaendige `https://`-Adresse, hoechstens 500 Zeichen. */
|
|
230
|
+
url: string;
|
|
231
|
+
/** Mindestens eines. */
|
|
232
|
+
events: (InventoryWebhookEventType | (string & {}))[];
|
|
233
|
+
/** Hoechstens 120 Zeichen. */
|
|
234
|
+
description?: string;
|
|
235
|
+
}
|
|
236
|
+
export interface InventoryWebhookPatch {
|
|
237
|
+
url?: string;
|
|
238
|
+
events?: (InventoryWebhookEventType | (string & {}))[];
|
|
239
|
+
active?: boolean;
|
|
240
|
+
/** `null` loescht die Beschreibung. */
|
|
241
|
+
description?: string | null;
|
|
242
|
+
}
|
|
243
|
+
export interface InventoryWebhookWithSecret {
|
|
244
|
+
webhook: InventoryWebhook;
|
|
245
|
+
/**
|
|
246
|
+
* Das Secret fuer [verifyInventoryWebhookSignature]. **Es kommt genau einmal**, bei
|
|
247
|
+
* `createWebhook` bzw. `rotateWebhookSecret`; danach gibt der Server es nie
|
|
248
|
+
* wieder aus. Nach einem Wechsel gilt sofort nur das neue.
|
|
249
|
+
*/
|
|
250
|
+
secret: string;
|
|
251
|
+
}
|
|
252
|
+
export interface InventoryWebhookList {
|
|
253
|
+
webhooks: InventoryWebhook[];
|
|
254
|
+
/** Die Ereignisse, die dieses Konto abonnieren kann. */
|
|
255
|
+
events: string[];
|
|
256
|
+
}
|
|
257
|
+
export interface InventoryWebhookTestDelivery {
|
|
258
|
+
/** Kennung der Zustellung (Kopfzeile `X-Kasseneck-Delivery`), wie bei Partner-Webhooks. */
|
|
259
|
+
deliveryId: string;
|
|
260
|
+
webhookId: string;
|
|
261
|
+
status: WebhookDeliveryStatus | (string & {}) | null;
|
|
262
|
+
statusCode: number | null;
|
|
263
|
+
}
|
|
264
|
+
export interface InventoryWebhookTestResult {
|
|
265
|
+
eventId: string;
|
|
266
|
+
event: string;
|
|
267
|
+
deliveries: InventoryWebhookTestDelivery[];
|
|
268
|
+
}
|
|
269
|
+
export interface InventoryWebhookDelivery {
|
|
270
|
+
/** Kennung der Zustellung (Kopfzeile `X-Kasseneck-Delivery`), wie bei Partner-Webhooks. */
|
|
271
|
+
deliveryId: string;
|
|
272
|
+
webhookId: string | null;
|
|
273
|
+
event: string | null;
|
|
274
|
+
eventId: string | null;
|
|
275
|
+
/** `dropped`: der Webhook wurde vor der Faelligkeit deaktiviert oder geloescht. */
|
|
276
|
+
status: WebhookDeliveryStatus | (string & {}) | null;
|
|
277
|
+
attempts: number;
|
|
278
|
+
statusCode: number | null;
|
|
279
|
+
/** Auszug der Antwort des Empfaengers, hoechstens 500 Zeichen. */
|
|
280
|
+
response: string | null;
|
|
281
|
+
error: string | null;
|
|
282
|
+
createdAt: string | null;
|
|
283
|
+
lastAttemptAt: string | null;
|
|
284
|
+
nextAttemptAt: string | null;
|
|
285
|
+
test: boolean;
|
|
286
|
+
}
|
|
287
|
+
/** Nutzlast von `stock.changed`: der aktuelle Stand, nicht die Aenderung. */
|
|
288
|
+
export interface StockChangedEventData extends StockLevel {
|
|
289
|
+
cause: StockChangeCause | (string & {});
|
|
290
|
+
/** Die Bewegung, aus der `cause` stammt; `null` bei `other` ohne Bewegung. */
|
|
291
|
+
movementId: string | null;
|
|
292
|
+
}
|
|
293
|
+
/** Nutzlast von `stock.below_minimum`: nur beim Unterschreiten, nicht bei jedem weiteren Sinken. */
|
|
294
|
+
export interface StockBelowMinimumEventData {
|
|
295
|
+
articleId: string;
|
|
296
|
+
locationId: string;
|
|
297
|
+
available: number;
|
|
298
|
+
/**
|
|
299
|
+
* Der Mindestbestand des Standorts in Tausendstel – die unterschrittene Schwelle,
|
|
300
|
+
* gemessen am Bestand `onHand`. Der `minStock` des Artikels allein loest nie aus.
|
|
301
|
+
*/
|
|
302
|
+
minStock: number;
|
|
303
|
+
}
|
|
304
|
+
export interface InventoryWebhookEnvelope<T extends InventoryWebhookEventType, D> {
|
|
305
|
+
/** `evt_…`: darauf entdoppeln. */
|
|
306
|
+
id: string;
|
|
307
|
+
type: T;
|
|
308
|
+
/** Millisekunden seit 1970 (UTC). */
|
|
309
|
+
createdAt: number;
|
|
310
|
+
/** Das Konto, dessen Lager das Ereignis betrifft. */
|
|
311
|
+
accountId: string;
|
|
312
|
+
/**
|
|
313
|
+
* `true` nur bei einer Probe aus `sendWebhookTest` (erfundene Nutzlast).
|
|
314
|
+
* An den Anfang jedes Handlers: `if (event.test) return;`
|
|
315
|
+
*/
|
|
316
|
+
test: boolean;
|
|
317
|
+
data: D;
|
|
318
|
+
}
|
|
319
|
+
export type InventoryWebhookEvent = InventoryWebhookEnvelope<'stock.changed', StockChangedEventData> | InventoryWebhookEnvelope<'stock.below_minimum', StockBelowMinimumEventData> | InventoryWebhookEnvelope<'article.created', Article> | InventoryWebhookEnvelope<'article.updated', Article> | InventoryWebhookEnvelope<'article.deactivated', Article>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Die Modelle der Lager-API, so wie sie am Draht `/v3` stehen.
|
|
3
|
+
*
|
|
4
|
+
* **Ganzzahlen mit fester Skala:** Mengen in Tausendstel der Basiseinheit
|
|
5
|
+
* (`1000` = 1 Stueck, `250` = 0,250 kg), Geld in Cent, Einkaufspreise in
|
|
6
|
+
* Mikro-Euro (`1_000_000` = 1 €). Nichts davon wird geteilt oder gerundet;
|
|
7
|
+
* eine Bruchzahl in einer Antwort ist ein Antwortfehler
|
|
8
|
+
* (`KasseneckValidationError`, `scope: 'response'`), nie ein Ersatzwert.
|
|
9
|
+
*
|
|
10
|
+
* Zeitpunkte sind ISO 8601 in UTC (`2026-10-06T08:15:00.000Z`), Tage (Wiener
|
|
11
|
+
* Tag) `YYYY-MM-DD`.
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
|
@@ -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];
|