@kreiseck/kasseneck-api 1.4.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/CHANGELOG.md +166 -0
  2. package/README.md +255 -36
  3. package/dist/cjs/client/aufrufe.d.ts +58 -4
  4. package/dist/cjs/client/aufrufe.js +196 -1
  5. package/dist/cjs/client/errors.d.ts +32 -19
  6. package/dist/cjs/client/errors.js +28 -17
  7. package/dist/cjs/client/index.d.ts +2 -2
  8. package/dist/cjs/client/index.js +2 -1
  9. package/dist/cjs/client/transport.d.ts +27 -1
  10. package/dist/cjs/client/transport.js +25 -27
  11. package/dist/cjs/index.d.ts +1 -1
  12. package/dist/cjs/index.js +3 -2
  13. package/dist/cjs/inventory/api.d.ts +19 -3
  14. package/dist/cjs/inventory/api.js +18 -2
  15. package/dist/cjs/inventory/endpunkte.d.ts +22 -2
  16. package/dist/cjs/inventory/endpunkte.js +6 -1
  17. package/dist/cjs/inventory/fehler.d.ts +11 -1
  18. package/dist/cjs/inventory/fehler.js +19 -0
  19. package/dist/cjs/inventory/index.d.ts +6 -4
  20. package/dist/cjs/inventory/index.js +32 -2
  21. package/dist/cjs/inventory/lesen.d.ts +8 -1
  22. package/dist/cjs/inventory/lesen.js +131 -1
  23. package/dist/cjs/inventory/schreiben.d.ts +86 -0
  24. package/dist/cjs/inventory/schreiben.js +320 -0
  25. package/dist/cjs/inventory/typen.d.ts +371 -11
  26. package/dist/cjs/inventory/vertrag.d.ts +76 -16
  27. package/dist/cjs/inventory/vertrag.js +138 -13
  28. package/dist/cjs/inventory/webhook.d.ts +3 -1
  29. package/dist/cjs/inventory/webhook.js +7 -1
  30. package/dist/cjs/invoice/endpunkte.d.ts +6 -0
  31. package/dist/cjs/invoice/endpunkte.js +13 -2
  32. package/dist/cjs/invoice/index.d.ts +2 -2
  33. package/dist/cjs/invoice/index.js +2 -1
  34. package/dist/cjs/invoice/typen.d.ts +46 -2
  35. package/dist/cjs/invoice/vertrag.d.ts +19 -5
  36. package/dist/cjs/invoice/vertrag.js +37 -5
  37. package/dist/cjs/pos/texte.d.ts +11 -6
  38. package/dist/cjs/pos/texte.js +11 -6
  39. package/dist/cjs/stored/vokabular.d.ts +1 -1
  40. package/dist/cjs/stored/vokabular.js +5 -3
  41. package/dist/cjs/version.d.ts +1 -1
  42. package/dist/cjs/version.js +1 -1
  43. package/dist/esm/client/aufrufe.d.ts +58 -4
  44. package/dist/esm/client/aufrufe.js +194 -0
  45. package/dist/esm/client/errors.d.ts +32 -19
  46. package/dist/esm/client/errors.js +28 -17
  47. package/dist/esm/client/index.d.ts +2 -2
  48. package/dist/esm/client/index.js +1 -1
  49. package/dist/esm/client/transport.d.ts +27 -1
  50. package/dist/esm/client/transport.js +26 -28
  51. package/dist/esm/index.d.ts +1 -1
  52. package/dist/esm/index.js +1 -1
  53. package/dist/esm/inventory/api.d.ts +19 -3
  54. package/dist/esm/inventory/api.js +18 -2
  55. package/dist/esm/inventory/endpunkte.d.ts +22 -2
  56. package/dist/esm/inventory/endpunkte.js +6 -5
  57. package/dist/esm/inventory/fehler.d.ts +11 -1
  58. package/dist/esm/inventory/fehler.js +18 -1
  59. package/dist/esm/inventory/index.d.ts +6 -4
  60. package/dist/esm/inventory/index.js +5 -3
  61. package/dist/esm/inventory/lesen.d.ts +8 -1
  62. package/dist/esm/inventory/lesen.js +127 -1
  63. package/dist/esm/inventory/schreiben.d.ts +86 -0
  64. package/dist/esm/inventory/schreiben.js +303 -0
  65. package/dist/esm/inventory/typen.d.ts +371 -11
  66. package/dist/esm/inventory/vertrag.d.ts +76 -16
  67. package/dist/esm/inventory/vertrag.js +137 -12
  68. package/dist/esm/inventory/webhook.d.ts +3 -1
  69. package/dist/esm/inventory/webhook.js +8 -2
  70. package/dist/esm/invoice/endpunkte.d.ts +6 -0
  71. package/dist/esm/invoice/endpunkte.js +13 -2
  72. package/dist/esm/invoice/index.d.ts +2 -2
  73. package/dist/esm/invoice/index.js +1 -1
  74. package/dist/esm/invoice/typen.d.ts +46 -2
  75. package/dist/esm/invoice/vertrag.d.ts +19 -5
  76. package/dist/esm/invoice/vertrag.js +36 -4
  77. package/dist/esm/pos/texte.d.ts +11 -6
  78. package/dist/esm/pos/texte.js +11 -6
  79. package/dist/esm/stored/vokabular.d.ts +1 -1
  80. package/dist/esm/stored/vokabular.js +5 -3
  81. package/dist/esm/version.d.ts +1 -1
  82. package/dist/esm/version.js +1 -1
  83. package/fixtures/hobex-hps-codes.json +1 -1
  84. package/fixtures/invoice-api-examples/credit-error-reservation.json +26 -0
  85. package/fixtures/invoice-api-examples/issue-error-reservation-article.json +25 -0
  86. package/fixtures/invoice-api-examples/issue-error-vat-id-risk.json +26 -0
  87. package/fixtures/invoice-api-examples/issue-reservation.json +24 -0
  88. package/fixtures/invoice-api-examples/issue-vat-id-risk.json +28 -0
  89. package/fixtures/invoice-api.schema.json +15 -2
  90. package/fixtures/invoice-texts.json +1 -1
  91. package/fixtures/pos-texts.json +1 -1
  92. package/fixtures/surface.json +206 -9
  93. package/fixtures/v3/antworten/belege.json +2 -2
  94. package/fixtures/v3/antworten/belegmail.json +2 -2
  95. package/fixtures/v3/antworten/kasse-belege.json +2 -2
  96. package/fixtures/v3/antworten/kasse.json +3 -3
  97. package/fixtures/v3/antworten/lager.json +2491 -130
  98. package/fixtures/v3/antworten/rechnungen.json +267 -44
  99. package/fixtures/v3/antworten/storno.json +2 -2
  100. package/fixtures/v3/stored/belege.json +2 -2
  101. package/fixtures/v3/stored/kasse.json +3 -3
  102. package/fixtures/v3/stored/rechnungen.json +174 -18
  103. package/fixtures/v3/v3-vokabular.json +593 -23
  104. package/fixtures/v3/zahlbetrag-faelle.json +2 -2
  105. package/package.json +1 -1
@@ -10,7 +10,7 @@
10
10
  * Zeitpunkte sind ISO 8601 in UTC (`2026-10-06T08:15:00.000Z`), Tage (Wiener
11
11
  * Tag) `YYYY-MM-DD`.
12
12
  */
13
- import type { InventoryWebhookEventType, LocationType, StockChangeCause, StockCondition, StockMovementSource, StockMovementType, WebhookDeliveryStatus } from './vertrag.js';
13
+ import type { InventoryWarningCode, InventoryWebhookEventType, LandedCostAllocation, LandedCostType, LocationType, ReservationStatus, StockChangeCause, StockCondition, StockKind, StockLossReason, StockMovementSource, StockMovementType, WebhookDeliveryStatus, WithdrawalType } from './vertrag.js';
14
14
  /**
15
15
  * Ein Artikel, wie `getArticle`, `listArticles`, `lookupArticleByCode` und die
16
16
  * Ereignisse `article.*` ihn senden.
@@ -24,6 +24,8 @@ import type { InventoryWebhookEventType, LocationType, StockChangeCause, StockCo
24
24
  export interface Article {
25
25
  id: string;
26
26
  name: string | null;
27
+ /** Beschreibung (bis 2000 Zeichen); `null` = keine. Seit 1.5.0. */
28
+ description: string | null;
27
29
  unitPriceCents: number | null;
28
30
  /** USt-Satz in Prozent, z. B. `20`, `10`, `4.9`. */
29
31
  vatRate: number | null;
@@ -34,14 +36,26 @@ export interface Article {
34
36
  groupId: string | null;
35
37
  revenueGroupId: string | null;
36
38
  stockTracked: boolean;
39
+ /**
40
+ * `quantity` (Menge) oder `serial` (Einzelstueck); `null`, wenn der Server
41
+ * das Feld nicht sendet (vor Stufe 5b). Ein Wert, den diese Paketversion
42
+ * nicht kennt, bleibt als Text stehen. Seit 1.5.0.
43
+ */
44
+ stockKind: StockKind | (string & {}) | null;
37
45
  /** Standorte, an denen der Artikel gefuehrt wird; leer = nur der Standard-Standort. */
38
46
  stockLocationIds: string[];
39
47
  /**
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.
48
+ * **Altfeld.** Mindestbestand des Artikels in Tausendstel; `null` = keiner.
49
+ * Er loest nichts aus: Warnungen, `belowMinimum` und `stock.below_minimum`
50
+ * richten sich nach [minStockByLocation].
43
51
  */
44
52
  minStock: number | null;
53
+ /**
54
+ * Mindestbestand je Standort in Tausendstel (`{ haupt: 20000 }`), die
55
+ * Schwelle fuer `below_minimum`, gemessen am verfuegbaren Bestand
56
+ * (`onHand − reserved`). Leer = keiner. Seit 1.5.0.
57
+ */
58
+ minStockByLocation: Record<string, number>;
45
59
  active: boolean;
46
60
  externalIds?: Record<string, string>;
47
61
  metadata?: Record<string, string>;
@@ -138,8 +152,9 @@ export interface StockListQuery {
138
152
  locationId?: string;
139
153
  articleId?: string;
140
154
  /**
141
- * `true`: nur Zeilen, deren `onHand` unter dem Mindestbestand ihres Standorts liegt
142
- * (dieselbe Regel wie `stock.below_minimum`; `minStock` des Artikels zaehlt nicht).
155
+ * `true`: nur Zeilen, deren verfuegbarer Bestand (`available = onHand − reserved`)
156
+ * unter dem Mindestbestand ihres Standorts liegt (dieselbe Regel wie
157
+ * `stock.below_minimum`; `minStock` des Artikels zaehlt nicht).
143
158
  */
144
159
  belowMinimum?: boolean;
145
160
  /** Nur Zeilen, die sich seitdem geaendert haben (inklusive), nach `updatedAt` aufsteigend. */
@@ -176,12 +191,21 @@ export interface StockMovement {
176
191
  articleId: string | null;
177
192
  locationId: string | null;
178
193
  condition: StockCondition | (string & {}) | null;
179
- /** Mengenaenderung in Tausendstel (Abgang negativ). */
194
+ /** Mengenaenderung in Tausendstel (Abgang negativ); bei `reservation` immer 0. */
180
195
  quantityDelta: number;
181
- /** Bestand am Standort nach der Bewegung. */
196
+ /**
197
+ * Aenderung von `reserved` in Tausendstel: positiv beim Reservieren, negativ
198
+ * bei Freigabe, Ablauf und Einloesen; 0 bei allen anderen Bewegungen. Seit 1.5.0.
199
+ */
200
+ reservedDelta: number;
201
+ /**
202
+ * Bestand am Standort nach der Bewegung. `reserved` steht nur an
203
+ * Reservierungsbewegungen, sonst `null` (nicht erfasst, nicht „0“).
204
+ */
182
205
  stockAfter: {
183
206
  sellable: number;
184
207
  defective: number;
208
+ reserved: number | null;
185
209
  } | null;
186
210
  operationId: string | null;
187
211
  source: StockMovementSourceRef | null;
@@ -294,10 +318,12 @@ export interface StockChangedEventData extends StockLevel {
294
318
  export interface StockBelowMinimumEventData {
295
319
  articleId: string;
296
320
  locationId: string;
321
+ /** Verfuegbarer Bestand (`onHand − reserved`); eine Reservierung allein kann ausloesen. */
297
322
  available: number;
298
323
  /**
299
- * Der Mindestbestand des Standorts in Tausendstel – die unterschrittene Schwelle,
300
- * gemessen am Bestand `onHand`. Der `minStock` des Artikels allein loest nie aus.
324
+ * Der Mindestbestand des Standorts in Tausendstel (`minStockByLocation`) –
325
+ * die unterschrittene Schwelle, gemessen an `available`. Der `minStock` des
326
+ * Artikels allein loest nie aus.
301
327
  */
302
328
  minStock: number;
303
329
  }
@@ -316,4 +342,338 @@ export interface InventoryWebhookEnvelope<T extends InventoryWebhookEventType, D
316
342
  test: boolean;
317
343
  data: D;
318
344
  }
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>;
345
+ export type InventoryWebhookEvent = InventoryWebhookEnvelope<'stock.changed', StockChangedEventData> | InventoryWebhookEnvelope<'stock.below_minimum', StockBelowMinimumEventData> | InventoryWebhookEnvelope<'article.created', Article> | InventoryWebhookEnvelope<'article.updated', Article> | InventoryWebhookEnvelope<'article.deactivated', Article> | InventoryWebhookEnvelope<'reservation.expired', Reservation> | InventoryWebhookEnvelope<'reservation.released', Reservation> | InventoryWebhookEnvelope<'reservation.redeemed', Reservation>;
346
+ /**
347
+ * Die Felder eines Artikels beim Anlegen. Bei der Anlage heisst `null` „nicht
348
+ * angegeben“ (ausser bei `name`, der Pflicht ist).
349
+ */
350
+ export interface ArticleInput {
351
+ /** 1–200 Zeichen, getrimmt gespeichert. */
352
+ name: string;
353
+ /** Bis 2000 Zeichen. */
354
+ description?: string | null;
355
+ unitPriceCents?: number | null;
356
+ /** USt-Satz in Prozent (`20`, `13`, `10`, `4.9`, `0`, `19`). */
357
+ vatRate?: number | null;
358
+ /** 1–20 Zeichen; ohne Angabe die Vorgabe des Kontos. */
359
+ unit?: string | null;
360
+ /** Artikelnummer, 1–64 Zeichen. */
361
+ number?: string | null;
362
+ /**
363
+ * GTIN/EAN mit gueltiger Pruefziffer: der Artikel wird ein Fremdartikel mit
364
+ * diesem Code. Ohne `ean` vergibt der Server einen eigenen Code nach den
365
+ * Einstellungen des Kontos (`internalCode`). Ein Code, der schon einem
366
+ * anderen Artikel gehoert, ergibt `code_taken`.
367
+ */
368
+ ean?: string | null;
369
+ /** Artikelgruppe; unbekannt = `group_not_found`. */
370
+ groupId?: string | null;
371
+ /** Erloesgruppe; unbekannt = `revenue_group_not_found`. */
372
+ revenueGroupId?: string | null;
373
+ stockTracked?: boolean | null;
374
+ /** Hoechstens 50 Standorte; unbekannt = `location_not_found`. */
375
+ stockLocationIds?: string[] | null;
376
+ /** **Altfeld** ohne Wirkung auf Meldungen; Tausendstel in ganzen Einheiten (Vielfaches von 1000). */
377
+ minStock?: number | null;
378
+ /** Mindestbestand je Standort in Tausendstel, hoechstens 50 Standorte. */
379
+ minStockByLocation?: Record<string, number | null> | null;
380
+ stockKind?: StockKind | null;
381
+ /**
382
+ * Standard-Einkaufspreis je Basiseinheit in Mikro-Euro. Nur mit dem
383
+ * Konto-Recht `costs`, sonst `inventory_api_not_enabled` mit
384
+ * `errors: [{ field: 'purchasePriceMicros' }]`.
385
+ */
386
+ purchasePriceMicros?: number | null;
387
+ /**
388
+ * Eigene Kennungen je System (`{ shop: '1001' }`): hoechstens 10 Systeme
389
+ * `^[a-z0-9_]{1,32}$`, Werte 1–128 Zeichen, je System und Wert eindeutig im
390
+ * Konto (`external_id_taken`). Damit findet `lookupArticleByCode` den Artikel.
391
+ */
392
+ externalIds?: Record<string, string> | null;
393
+ /** Freie Merkmale, nie ausgewertet: hoechstens 20 Schluessel `^[a-zA-Z0-9_]{1,40}$`, Werte bis 500 Zeichen, zusammen 4 KB. */
394
+ metadata?: Record<string, string> | null;
395
+ }
396
+ export interface CreateArticleRequest extends ArticleInput {
397
+ idempotencyKey: string;
398
+ }
399
+ /**
400
+ * Eine Aenderung: nur die genannten Felder, mindestens eines. `null` leert ein
401
+ * optionales Feld (`description`, `unitPriceCents`, `vatRate`, `number`,
402
+ * `groupId`, `revenueGroupId`, `minStock`, `stockLocationIds`, `externalIds`,
403
+ * `metadata`, `minStockByLocation`, `purchasePriceMicros`). `name`, `unit`,
404
+ * `ean`, `stockTracked` und `stockKind` lassen sich nicht leeren.
405
+ *
406
+ * `externalIds` und `metadata` werden ganz ersetzt, `minStockByLocation` je
407
+ * Standort zusammengefuehrt (`{ haupt: null }` nimmt nur diesen Standort weg).
408
+ * Die EAN laesst sich nur bei Fremdartikeln wechseln; `stockKind` nach der
409
+ * ersten Bewegung nicht mehr (`stock_kind_locked`). Ein stillgelegter Artikel
410
+ * ergibt `article_inactive`.
411
+ */
412
+ export interface UpdateArticleRequest {
413
+ idempotencyKey: string;
414
+ articleId: string;
415
+ name?: string;
416
+ description?: string | null;
417
+ unitPriceCents?: number | null;
418
+ vatRate?: number | null;
419
+ unit?: string;
420
+ number?: string | null;
421
+ ean?: string;
422
+ groupId?: string | null;
423
+ revenueGroupId?: string | null;
424
+ stockTracked?: boolean;
425
+ stockLocationIds?: string[] | null;
426
+ minStock?: number | null;
427
+ minStockByLocation?: Record<string, number | null> | null;
428
+ stockKind?: StockKind;
429
+ purchasePriceMicros?: number | null;
430
+ externalIds?: Record<string, string> | null;
431
+ metadata?: Record<string, string> | null;
432
+ }
433
+ /**
434
+ * Stilllegen: `active: false`; Code und eigene Kennungen werden frei. Schon
435
+ * stillgelegt = dieselbe Antwort, nichts geschrieben. Den Bestand behaelt der
436
+ * Artikel, gebucht werden darf weiter.
437
+ */
438
+ export interface DeactivateArticleRequest {
439
+ idempotencyKey: string;
440
+ articleId: string;
441
+ }
442
+ /** Ein Hinweis einer Buchung: sie hat gewirkt, es gibt nur etwas zu wissen. */
443
+ export interface InventoryWarning {
444
+ code: InventoryWarningCode | (string & {});
445
+ articleId: string | null;
446
+ locationId: string | null;
447
+ /** Fuer Menschen, deutsch; nie darauf verzweigen. */
448
+ message: string;
449
+ }
450
+ /**
451
+ * Antwort jeder Buchung (`receiveGoods`, `transferStock`, `recordStockLoss`,
452
+ * `changeStockCondition`, `reverseStockMovement`). Werte traegt sie nie. Eine
453
+ * Wiederholung mit demselben `idempotencyKey` liefert genau diese Antwort
454
+ * noch einmal (ohne Kennzeichen, die beiden sind gleich).
455
+ */
456
+ export interface StockOperation {
457
+ /** Kennung des Vorgangs; `reverseStockMovement` nimmt ihn zurueck. */
458
+ operationId: string;
459
+ movementIds: string[];
460
+ lotIds: string[];
461
+ warnings: InventoryWarning[];
462
+ }
463
+ /** Eine Position eines Wareneingangs. */
464
+ export interface GoodsReceiptItem {
465
+ articleId: string;
466
+ /** Tausendstel, groesser als 0. */
467
+ quantity: number;
468
+ /** Gesamtpreis der Position in Cent. Entweder dieser oder `unitPriceMicros`; ohne beide der Einkaufspreis des Artikels. */
469
+ totalCents?: number;
470
+ /** Einzelpreis je Basiseinheit in Mikro-Euro. */
471
+ unitPriceMicros?: number;
472
+ /** Nebenkosten dieser Position in Cent; gilt nur bei `allocation: 'manual'`. */
473
+ landedCostCents?: number;
474
+ /** Ablaufdatum `YYYY-MM-DD`. */
475
+ expiresOn?: string;
476
+ /** Charge, 1–64 Zeichen. */
477
+ batch?: string;
478
+ /** Seriennummern (Einzelstuecke), hoechstens 80, je 1–128 Zeichen. */
479
+ serialNumbers?: string[];
480
+ }
481
+ export interface LandedCost {
482
+ type: LandedCostType;
483
+ /** Betrag in Cent; `discount` und `cash_discount` mindern den Wert. */
484
+ amountCents: number;
485
+ }
486
+ /**
487
+ * Wareneingang. Preise und Nebenkosten darf jeder Schreibende senden (so
488
+ * bekommt der Bestand seinen Wert); zurueck kommen Werte nur mit dem Recht
489
+ * `costs` und nur in der Vorschau ([previewGoodsReceipt]).
490
+ */
491
+ export interface ReceiveGoodsRequest {
492
+ idempotencyKey: string;
493
+ /** Hoechstens 80 Positionen (`too_many_positions`). */
494
+ items: GoodsReceiptItem[];
495
+ /** Ohne Angabe der Standard-Standort des Kontos. */
496
+ locationId?: string;
497
+ /** Hoechstens 20. */
498
+ landedCosts?: LandedCost[];
499
+ allocation?: LandedCostAllocation;
500
+ supplier?: {
501
+ name: string;
502
+ address?: string;
503
+ };
504
+ /** Lieferschein o. Ae., 1–80 Zeichen. */
505
+ reference?: string;
506
+ /** 1–500 Zeichen. */
507
+ note?: string;
508
+ }
509
+ /**
510
+ * Vorschau eines Wareneingangs (`dryRun: true`): schreibt nichts, der
511
+ * Schluessel ist freigestellt (wenn da, wird nur seine Form geprueft), das
512
+ * Schreibrecht braucht sie trotzdem. Den Standort prueft erst die Buchung.
513
+ */
514
+ export type GoodsReceiptPreviewRequest = Omit<ReceiveGoodsRequest, 'idempotencyKey'> & {
515
+ idempotencyKey?: string;
516
+ };
517
+ /**
518
+ * Eine Zeile der Vorschau. Die vier Werte (`baseCents`, `landedCostCents`,
519
+ * `valueCents`, `unitCostMicros`) kommen nur mit dem Recht `costs` und fehlen
520
+ * sonst ganz.
521
+ */
522
+ export interface GoodsReceiptPreviewLine {
523
+ articleId: string;
524
+ quantity: number;
525
+ expiresOn: string | null;
526
+ batch: string | null;
527
+ serialNumbers: string[];
528
+ /** `true`: der Preis kam aus dem Artikel, nicht aus der Anfrage. */
529
+ priceFromArticle: boolean;
530
+ baseCents?: number | null;
531
+ landedCostCents?: number | null;
532
+ valueCents?: number | null;
533
+ unitCostMicros?: number | null;
534
+ }
535
+ export interface GoodsReceiptPreview {
536
+ preview: GoodsReceiptPreviewLine[];
537
+ }
538
+ /** Eine Position von Umbuchung, Abgang oder Zustandswechsel. */
539
+ export interface StockItem {
540
+ articleId: string;
541
+ /** Tausendstel, groesser als 0. */
542
+ quantity: number;
543
+ /** Bei Einzelstuecken das Stueck. */
544
+ serialNumber?: string;
545
+ }
546
+ /** Umbuchung zwischen zwei Standorten. Ueberzieht nie (`exceeds_stock`). */
547
+ export interface TransferStockRequest {
548
+ idempotencyKey: string;
549
+ fromLocationId: string;
550
+ toLocationId: string;
551
+ items: StockItem[];
552
+ note?: string;
553
+ }
554
+ /**
555
+ * Abgang (Bruch, Schwund, Entnahme …). Ueberzieht nie (`exceeds_stock`).
556
+ * `reason: 'other'` braucht `note` (`note_required`), `reason: 'withdrawal'`
557
+ * braucht `withdrawalType` (`withdrawal_type_required`).
558
+ */
559
+ export interface RecordStockLossRequest {
560
+ idempotencyKey: string;
561
+ reason: StockLossReason;
562
+ withdrawalType?: WithdrawalType;
563
+ /** Aus welchem Zustand; Vorgabe `sellable`. */
564
+ condition?: StockCondition;
565
+ locationId?: string;
566
+ items: StockItem[];
567
+ note?: string;
568
+ }
569
+ /** Ware zwischen verkaufbar und defekt umbuchen. Ueberzieht nie (`exceeds_stock`). */
570
+ export interface ChangeStockConditionRequest {
571
+ idempotencyKey: string;
572
+ from: StockCondition;
573
+ to: StockCondition;
574
+ locationId?: string;
575
+ items: StockItem[];
576
+ note?: string;
577
+ }
578
+ /**
579
+ * Gegenbuchung: nimmt einen ganzen Vorgang zurueck. Verkaeufe und
580
+ * Reservierungen gehen so nicht (`reversal_not_supported`), ein zweites Mal
581
+ * auch nicht (`already_reversed`).
582
+ */
583
+ export interface ReverseStockMovementRequest {
584
+ idempotencyKey: string;
585
+ operationId: string;
586
+ /** Pflicht, bis 500 Zeichen; leer = `reason_required`. */
587
+ reason: string;
588
+ }
589
+ /**
590
+ * Eine Position einer Reservierung, Mengen in Tausendstel. Offen ist
591
+ * `quantity − redeemed − released`.
592
+ */
593
+ export interface ReservationItem {
594
+ articleId: string;
595
+ locationId: string;
596
+ quantity: number;
597
+ redeemed: number;
598
+ released: number;
599
+ }
600
+ /**
601
+ * Eine Reservierung, wie `getReservation`, jede schreibende Reservierungs-
602
+ * Antwort und die Ereignisse `reservation.*` sie senden.
603
+ */
604
+ export interface Reservation {
605
+ id: string;
606
+ /** `null`: ein Stand, den diese Paketversion nicht kennt, oder keiner. */
607
+ status: ReservationStatus | (string & {}) | null;
608
+ /** Eigene Referenz (Bestellnummer), `null` = keine. */
609
+ reference: string | null;
610
+ items: ReservationItem[];
611
+ /** Ablauf, ISO 8601 UTC. */
612
+ expiresAt: string | null;
613
+ createdAt: string | null;
614
+ }
615
+ export interface ReservationItemInput {
616
+ articleId: string;
617
+ /** Tausendstel, groesser als 0. */
618
+ quantity: number;
619
+ /** Ohne Angabe der Standard-Standort des Kontos. */
620
+ locationId?: string;
621
+ }
622
+ /**
623
+ * Reservieren (Checkout): ganz oder gar nicht. Fehlt verfuegbarer Bestand an
624
+ * einer Position, entsteht nichts und der Fehler `insufficient_available`
625
+ * nennt die fehlenden Positionen ([inventoryShortfalls]). Nur
626
+ * bestandsgefuehrte Artikel. Gleiche Artikel am gleichen Standort werden
627
+ * zusammengezaehlt.
628
+ */
629
+ export interface CreateReservationRequest {
630
+ idempotencyKey: string;
631
+ /** 1–50 Positionen. */
632
+ items: ReservationItemInput[];
633
+ /** 1–128 Zeichen; `listReservations({ reference })` findet sie damit. */
634
+ reference?: string | null;
635
+ /** 5 … 43 200 Minuten; ohne Angabe die Vorgabe des Kontos (7 Tage). */
636
+ expiresInMinutes?: number | null;
637
+ }
638
+ /** Verlaengern: neuer Ablauf = jetzt + Minuten. Nur eine aktive, noch nicht faellige Reservierung (`reservation_not_active`). */
639
+ export interface ExtendReservationRequest {
640
+ idempotencyKey: string;
641
+ reservationId: string;
642
+ /** 5 … 43 200 Minuten. */
643
+ expiresInMinutes: number;
644
+ }
645
+ export interface ReleaseReservationItem {
646
+ articleId: string;
647
+ locationId?: string;
648
+ /** Ohne Angabe der ganze offene Rest der Position. */
649
+ quantity?: number;
650
+ }
651
+ /** Freigeben: ohne `items` alles, sonst je Position (ganz oder teilweise). */
652
+ export interface ReleaseReservationRequest {
653
+ idempotencyKey: string;
654
+ reservationId: string;
655
+ /** Nicht leer; ganz weglassen, um alles freizugeben. */
656
+ items?: ReleaseReservationItem[];
657
+ }
658
+ export interface ReservationListQuery {
659
+ status?: ReservationStatus;
660
+ /** Genau diese Referenz. */
661
+ reference?: string;
662
+ /** 1–200, Vorgabe des Servers 50. */
663
+ limit?: number;
664
+ cursor?: string;
665
+ }
666
+ /** Neueste zuerst (`createdAt` absteigend). */
667
+ export interface ReservationPage {
668
+ reservations: Reservation[];
669
+ nextCursor: string | null;
670
+ }
671
+ /** Eine Position, fuer die beim Reservieren der verfuegbare Bestand nicht reicht (`insufficient_available`). */
672
+ export interface InventoryShortfall {
673
+ articleId: string;
674
+ locationId: string;
675
+ /** Angefragt, Tausendstel. */
676
+ requested: number;
677
+ /** Verfuegbar (`onHand − reserved`), Tausendstel; darf negativ sein. */
678
+ available: number;
679
+ }
@@ -1,15 +1,18 @@
1
1
  /**
2
- * Der Vertrag der Lager-API (Backend Stufe 5a) als Daten: Endpunkte,
3
- * Wertkataloge, Ereignisse und Fehlercodes, englisch wie am Draht `/v3`.
2
+ * Der Vertrag der Lager-API (Backend Stufe 5a lesen, 5b schreiben und
3
+ * reservieren) als Daten: Endpunkte, Wertkataloge, Ereignisse, Fehler- und
4
+ * Hinweiscodes, englisch wie am Draht `/v3`.
4
5
  *
5
6
  * Quelle ist der Vertrags-Export des Backends (`fixtures/v3/v3-vokabular.json`):
6
7
  * `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.
8
+ * `BEWEGUNG_QUELLE`, `LAGER_ZUSTAND`, `LAGER_URSACHE`, `ZUSTELLUNG`,
9
+ * `LAGER_ABGANG_GRUND`, `LAGER_ENTNAHME_ART`, `LAGER_NEBENKOSTEN_ART`,
10
+ * `LAGER_VERTEILUNG`, `RESERVIERUNG_STATUS`, dazu `events`, `errorCodes.inventory`
11
+ * und `warningCodes.inventory`. `test/inventory.test.ts` haelt jede Liste
12
+ * deckungsgleich mit dieser Datei; nichts hier wird geraten.
10
13
  */
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"];
14
+ /** Die 27 Endpunkte (14 aus 5a, 13 aus 5b), in der Reihenfolge von `endpoints.public`. */
15
+ export declare const INVENTORY_ENDPOINTS: readonly ["getArticle", "listArticles", "lookupArticleByCode", "listLocations", "getStock", "listStock", "listStockMovements", "createWebhook", "updateWebhook", "deleteWebhook", "listWebhooks", "sendWebhookTest", "rotateWebhookSecret", "listWebhookDeliveries", "createArticle", "updateArticle", "deactivateArticle", "receiveGoods", "transferStock", "recordStockLoss", "changeStockCondition", "reverseStockMovement", "createReservation", "extendReservation", "releaseReservation", "getReservation", "listReservations"];
13
16
  export type InventoryEndpoint = (typeof INVENTORY_ENDPOINTS)[number];
14
17
  /** Art eines Standorts (Katalog `STANDORT_TYP`). */
15
18
  export declare const LOCATION_TYPES: readonly ["warehouse", "store", "vehicle", "other"];
@@ -18,8 +21,10 @@ export type LocationType = (typeof LOCATION_TYPES)[number];
18
21
  * Art einer Lagerbewegung (Katalog `BEWEGUNG_ART`); zugleich der Filter `type`.
19
22
  * `goods_receipt` ist der Wareneingang, `takeover` der uebernommene Anfangsbestand
20
23
  * (auch per Import). `receipt` gibt es hier nicht: das ist der Kassenbeleg (Quelle).
24
+ * `reservation` (seit 1.5.0) aendert nur `reserved`: `quantityDelta` ist 0, die
25
+ * Menge steht in `reservedDelta`.
21
26
  */
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"];
27
+ 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", "reservation"];
23
28
  export type StockMovementType = (typeof STOCK_MOVEMENT_TYPES)[number];
24
29
  /**
25
30
  * Woher eine Bewegung kommt (Katalog `BEWEGUNG_QUELLE`); zugleich der Filter
@@ -42,10 +47,13 @@ export type StockChangeCause = (typeof STOCK_CHANGE_CAUSES)[number];
42
47
  export declare const WEBHOOK_DELIVERY_STATUSES: readonly ["delivered", "pending", "failed", "dropped"];
43
48
  export type WebhookDeliveryStatus = (typeof WEBHOOK_DELIVERY_STATUSES)[number];
44
49
  /**
45
- * Die Ereignisse, die ein Konto-Webhook abonnieren kann (Stufe 5a). Spaetere
46
- * Stufen ergaenzen `reservation.*` und `variant_group.*`.
50
+ * Die Ereignisse, die ein Konto-Webhook abonnieren kann, in der Reihenfolge von
51
+ * `listWebhooks().events`. `reservation.*` (seit 1.5.0) tragen die Reservierung
52
+ * wie `getReservation`, mit dem Status danach: `reservation.released` und
53
+ * `reservation.redeemed` kommen bei jeder wirksamen Freigabe bzw. Einloesung,
54
+ * auch einer teilweisen (dann bleibt der Status `active`).
47
55
  */
48
- export declare const INVENTORY_WEBHOOK_EVENTS: readonly ["stock.changed", "stock.below_minimum", "article.created", "article.updated", "article.deactivated"];
56
+ export declare const INVENTORY_WEBHOOK_EVENTS: readonly ["stock.changed", "stock.below_minimum", "article.created", "article.updated", "article.deactivated", "reservation.expired", "reservation.released", "reservation.redeemed"];
49
57
  export type InventoryWebhookEventType = (typeof INVENTORY_WEBHOOK_EVENTS)[number];
50
58
  /**
51
59
  * Die Felder der Huelle jeder Zustellung, in der Reihenfolge am Draht. Statt
@@ -58,12 +66,23 @@ export declare const INVENTORY_WEBHOOK_LIMIT = 5;
58
66
  /** Groesstes `limit` einer Liste; ohne Angabe liefert der Server 50. */
59
67
  export declare const INVENTORY_LIST_LIMIT_MAX = 200;
60
68
  /**
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).
69
+ * Die Codes, die die Lager-Endpunkte selbst senden (`errorCodes.inventory`;
70
+ * `register_user_not_allowed` steht bei [INVENTORY_REQUEST_ERROR_CODES]).
71
+ * `validation` traegt `errors: [{ field, message }]`, `rate_limited` traegt
72
+ * `retryAfterSec` (dazu die Kopfzeile `Retry-After`) – auch bei
73
+ * `sendWebhookTest` nach 20 Probesendungen je Wiener Kalendertag (dann bis
74
+ * Mitternacht in Wien).
75
+ *
76
+ * Seit 1.5.0 hinten angehaengt, in der Reihenfolge des Vertrags: die Codes
77
+ * der schreibenden Endpunkte. `idempotency_key_required` (Schluessel fehlt),
78
+ * `idempotency_conflict` (derselbe Schluessel mit anderem Inhalt),
79
+ * `exceeds_stock` (Abgang, Umbuchung und Zustandswechsel ueberziehen nie),
80
+ * `insufficient_available` (Reservierung; `data.details[]`, siehe
81
+ * [inventoryShortfalls]), `code_taken` und `external_id_taken` (mit `field` und
82
+ * `articleId` des Artikels, dem der Code gehoert), `stock_kind_locked`,
83
+ * `reservation_not_found`, `reservation_not_active` …
65
84
  */
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"];
85
+ 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", "idempotency_key_required", "idempotency_conflict", "location_not_found", "location_inactive", "invalid_location", "invalid_locations", "invalid_transfer", "operation_not_found", "already_reversed", "reversal_not_possible", "reversal_not_supported", "exceeds_stock", "no_positions", "too_many_positions", "invalid_step", "invalid_quantity", "invalid_amount", "invalid_price", "negative_value", "invalid_reason", "note_required", "withdrawal_type_required", "invalid_method", "invalid_stock_kind", "invalid_minimum", "invalid_dimensions", "weight_missing", "invalid_landed_cost", "invalid_distribution", "landed_costs_mismatch", "return_totals_mismatch", "lot_not_found", "invalid_serial", "serial_required", "serial_not_allowed", "serial_already_exists", "serial_not_in_stock", "code_taken", "external_id_taken", "group_not_found", "revenue_group_not_found", "stock_kind_locked", "article_inactive", "invalid_position", "invalid_condition", "reason_required", "insufficient_available", "reservation_not_found", "reservation_not_active"];
67
86
  export type InventoryErrorCode = (typeof INVENTORY_ERROR_CODES)[number];
68
87
  /**
69
88
  * Codes, die Anmeldung und Rand auf jedem Lager-Aufruf erzeugen koennen,
@@ -74,3 +93,44 @@ export type InventoryErrorCode = (typeof INVENTORY_ERROR_CODES)[number];
74
93
  */
75
94
  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
95
  export type InventoryRequestErrorCode = (typeof INVENTORY_REQUEST_ERROR_CODES)[number];
96
+ /**
97
+ * Hinweise einer Buchung (`warnings[].code`, `warningCodes.inventory`). Sie sind
98
+ * keine Fehler: die Buchung hat gewirkt. `insufficient_stock` gibt es nur beim
99
+ * Verkauf (Abgang, Umbuchung und Zustandswechsel weisen mit `exceeds_stock` ab),
100
+ * `below_minimum` misst am verfuegbaren Bestand (`onHand − reserved`) gegen den
101
+ * Mindestbestand des Standorts, `reservation_exceeded` meldet eine Rechnung, die
102
+ * mehr verkauft als reserviert war.
103
+ */
104
+ export declare const INVENTORY_WARNING_CODES: readonly ["insufficient_stock", "below_minimum", "return_exceeds_sale", "reservation_exceeded"];
105
+ export type InventoryWarningCode = (typeof INVENTORY_WARNING_CODES)[number];
106
+ /**
107
+ * Bestandsart eines Artikels (`stockKind`): `quantity` = Menge, `serial` =
108
+ * Einzelstueck mit Seriennummer. Kein Katalog des Vokabulars, der Server
109
+ * uebersetzt das Feld selbst; nach der ersten Bewegung fest (`stock_kind_locked`).
110
+ */
111
+ export declare const STOCK_KINDS: readonly ["quantity", "serial"];
112
+ export type StockKind = (typeof STOCK_KINDS)[number];
113
+ /** Grund eines Abgangs (`recordStockLoss.reason`, Katalog `LAGER_ABGANG_GRUND`). `other` braucht `note`. */
114
+ export declare const STOCK_LOSS_REASONS: readonly ["breakage", "shrinkage", "theft", "expired", "withdrawal", "disposal", "other"];
115
+ export type StockLossReason = (typeof STOCK_LOSS_REASONS)[number];
116
+ /** Art einer Entnahme (`withdrawalType`, Katalog `LAGER_ENTNAHME_ART`); Pflicht bei `reason: 'withdrawal'`, sonst nicht erlaubt. */
117
+ export declare const WITHDRAWAL_TYPES: readonly ["private", "staff", "gift", "sample"];
118
+ export type WithdrawalType = (typeof WITHDRAWAL_TYPES)[number];
119
+ /** Art von Nebenkosten eines Wareneingangs (`landedCosts[].type`, Katalog `LAGER_NEBENKOSTEN_ART`). */
120
+ export declare const LANDED_COST_TYPES: readonly ["freight", "customs", "insurance", "other", "discount", "cash_discount"];
121
+ export type LandedCostType = (typeof LANDED_COST_TYPES)[number];
122
+ /** Verteilung der Nebenkosten (`allocation`, Katalog `LAGER_VERTEILUNG`); Vorgabe des Servers `value`. */
123
+ export declare const LANDED_COST_ALLOCATIONS: readonly ["value", "quantity", "weight", "manual"];
124
+ export type LandedCostAllocation = (typeof LANDED_COST_ALLOCATIONS)[number];
125
+ /**
126
+ * Stand einer Reservierung (Katalog `RESERVIERUNG_STATUS`). Nur `active` haelt
127
+ * Ware zurueck; die drei anderen sind endgueltig: `redeemed` (ueber eine
128
+ * Rechnung eingeloest), `released` (freigegeben), `expired` (abgelaufen).
129
+ */
130
+ export declare const RESERVATION_STATUSES: readonly ["active", "redeemed", "released", "expired"];
131
+ export type ReservationStatus = (typeof RESERVATION_STATUSES)[number];
132
+ /** Laengster `idempotencyKey` (Zeichen); laenger weist der Server ab, er schneidet nie ab. */
133
+ export declare const INVENTORY_IDEMPOTENCY_KEY_MAX = 120;
134
+ /** Kuerzeste und laengste Haltedauer einer Reservierung in Minuten (`expiresInMinutes`, 30 Tage). */
135
+ export declare const RESERVATION_MINUTES_MIN = 5;
136
+ export declare const RESERVATION_MINUTES_MAX = 43200;