@kreiseck/kasseneck-api 1.5.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/README.md +119 -3
  3. package/dist/cjs/client/aufrufe.d.ts +3 -3
  4. package/dist/cjs/client/aufrufe.js +17 -0
  5. package/dist/cjs/inventory/api.d.ts +10 -2
  6. package/dist/cjs/inventory/api.js +8 -1
  7. package/dist/cjs/inventory/endpunkte.d.ts +2 -1
  8. package/dist/cjs/inventory/endpunkte.js +2 -1
  9. package/dist/cjs/inventory/index.d.ts +5 -3
  10. package/dist/cjs/inventory/index.js +15 -3
  11. package/dist/cjs/inventory/lesen.d.ts +7 -1
  12. package/dist/cjs/inventory/lesen.js +75 -0
  13. package/dist/cjs/inventory/schreiben.d.ts +23 -1
  14. package/dist/cjs/inventory/schreiben.js +18 -9
  15. package/dist/cjs/inventory/typen.d.ts +156 -2
  16. package/dist/cjs/inventory/varianten.d.ts +67 -0
  17. package/dist/cjs/inventory/varianten.js +150 -0
  18. package/dist/cjs/inventory/vertrag.d.ts +40 -5
  19. package/dist/cjs/inventory/vertrag.js +51 -3
  20. package/dist/cjs/inventory/webhook.d.ts +5 -2
  21. package/dist/cjs/inventory/webhook.js +8 -2
  22. package/dist/cjs/stored/vokabular.d.ts +1 -1
  23. package/dist/cjs/stored/vokabular.js +1 -1
  24. package/dist/cjs/version.d.ts +1 -1
  25. package/dist/cjs/version.js +1 -1
  26. package/dist/esm/client/aufrufe.d.ts +3 -3
  27. package/dist/esm/client/aufrufe.js +17 -0
  28. package/dist/esm/inventory/api.d.ts +10 -2
  29. package/dist/esm/inventory/api.js +8 -1
  30. package/dist/esm/inventory/endpunkte.d.ts +2 -1
  31. package/dist/esm/inventory/endpunkte.js +2 -1
  32. package/dist/esm/inventory/index.d.ts +5 -3
  33. package/dist/esm/inventory/index.js +4 -2
  34. package/dist/esm/inventory/lesen.d.ts +7 -1
  35. package/dist/esm/inventory/lesen.js +74 -0
  36. package/dist/esm/inventory/schreiben.d.ts +23 -1
  37. package/dist/esm/inventory/schreiben.js +13 -10
  38. package/dist/esm/inventory/typen.d.ts +156 -2
  39. package/dist/esm/inventory/varianten.d.ts +67 -0
  40. package/dist/esm/inventory/varianten.js +142 -0
  41. package/dist/esm/inventory/vertrag.d.ts +40 -5
  42. package/dist/esm/inventory/vertrag.js +50 -2
  43. package/dist/esm/inventory/webhook.d.ts +5 -2
  44. package/dist/esm/inventory/webhook.js +9 -3
  45. package/dist/esm/stored/vokabular.d.ts +1 -1
  46. package/dist/esm/stored/vokabular.js +1 -1
  47. package/dist/esm/version.d.ts +1 -1
  48. package/dist/esm/version.js +1 -1
  49. package/fixtures/hobex-hps-codes.json +1 -1
  50. package/fixtures/invoice-api.schema.json +1 -1
  51. package/fixtures/invoice-texts.json +1 -1
  52. package/fixtures/pos-texts.json +1 -1
  53. package/fixtures/surface.json +31 -6
  54. package/fixtures/v3/antworten/belege.json +1 -1
  55. package/fixtures/v3/antworten/belegmail.json +1 -1
  56. package/fixtures/v3/antworten/kasse-belege.json +1 -1
  57. package/fixtures/v3/antworten/kasse.json +2 -2
  58. package/fixtures/v3/antworten/lager.json +2396 -4
  59. package/fixtures/v3/antworten/rechnungen.json +1 -1
  60. package/fixtures/v3/antworten/storno.json +1 -1
  61. package/fixtures/v3/stored/belege.json +1 -1
  62. package/fixtures/v3/stored/kasse.json +2 -2
  63. package/fixtures/v3/stored/rechnungen.json +1 -1
  64. package/fixtures/v3/v3-vokabular.json +151 -6
  65. package/fixtures/v3/zahlbetrag-faelle.json +1 -1
  66. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,72 @@ Was vor 0.7.0 geschah, steht in der Commit-Historie (`git log`); ab hier wird
4
4
  es hier geführt. Ein Eintrag nennt die Änderung **und ihren Grund** —
5
5
  nur der Grund überlebt den nächsten Umbau.
6
6
 
7
+ ## 1.6.0
8
+
9
+ Inventory API, variants: `./inventory` gains the five endpoints of backend
10
+ stage 5c. Reason: a shop sells the same apron in three sizes and two colours.
11
+ Until now it had to create six unrelated articles and keep their names, prices
12
+ and codes in step by hand; nothing told the shop or the register that they
13
+ belong together, and nothing stopped a second "M red". A variant group holds
14
+ what they share and guarantees that each combination exists once.
15
+
16
+ Additive at runtime; existing calls send the same bytes as in 1.5.1. Two
17
+ things change for code that relies on the old shape: the unions
18
+ `InventoryWebhookEvent`/`InventoryWebhookEventType`, `InventoryErrorCode`,
19
+ `InventoryEndpoint` and `ApiCall` gain members, so an exhaustive `switch` with a
20
+ `never` check (or a `Record<…>` over them) needs the new cases; and
21
+ `parseInventoryWebhookEvent` now returns an event for `variant_group.*` where
22
+ 1.5.x returned `null`.
23
+
24
+ - **Variant groups**: `createVariantGroup` (with `createMatrix: true` every
25
+ combination of the values, at most 100, or the listed `variants[]`, at most
26
+ 100; never both), `updateVariantGroup` (name, defaults as a partial update,
27
+ `addAttributeValues`, or `active: false` to deactivate the group and all its
28
+ variants for good), `getVariantGroup`, `listVariantGroups` and
29
+ `iterateVariantGroups` (sorted by `updatedAt` ascending, filters `active`
30
+ and `updatedSince`). `VariantGroup` carries `attributes` (1 to 3, each with
31
+ `key`, `label` and 1 to 30 `values`, in group order), `defaults`
32
+ (`unitPriceCents`, `vatRate`, `unit`, `groupId`, `stockTracked`), `active`,
33
+ `variants[]` (`articleId` and `variantAttributes` of every active variant)
34
+ and the times. The group answers carry no articles: read them with
35
+ `listArticles({ variantGroupId })`.
36
+ - **Variants are articles**: `addVariant` creates one more variant and answers
37
+ with the article as `createArticle` does. Each variant takes the article
38
+ fields of `createArticle`; fields it does not name are filled from the group
39
+ defaults at creation, the name defaults to "<group> <value1> <value2>" in
40
+ attribute order. `Article.variantGroupId` and `Article.variantAttributes`
41
+ are set only on variants; the keys of `variantAttributes` come sorted by code
42
+ point, the attribute order is in `VariantGroup.attributes`.
43
+ - **Idempotency**: the three writes take `idempotencyKey` (required in the
44
+ type and refused before sending without a valid one) and are in
45
+ `UNKNOWN_OUTCOME_CALLS`: after `outcome: 'unknown'` resend with the same key.
46
+ `getVariantGroup` and `listVariantGroups` are reads.
47
+ - **Checked before sending**, nothing else: the key, `variantGroupId`,
48
+ `createMatrix: true` together with `variants`, `variants` that is no list or
49
+ holds an entry without a `variantAttributes` object, integer prices,
50
+ quantities and purchase prices (also in `defaults` and in every variant), an
51
+ update without a change, `active` other than `false` or not alone,
52
+ `addAttributeValues` that is no object. The limits (3 attributes, 30 values,
53
+ matrix 100, 250 active variants per group) are left to the server, so it can
54
+ raise them; they are exported as `VARIANT_ATTRIBUTES_MAX`,
55
+ `VARIANT_VALUES_MAX`, `VARIANT_MATRIX_MAX`, `VARIANT_GROUP_ACTIVE_MAX`.
56
+ - **Events**: `variant_group.created` and `variant_group.updated` in
57
+ `INVENTORY_WEBHOOK_EVENTS` and `parseInventoryWebhookEvent`, carrying the
58
+ group as `getVariantGroup` returns it. `updated` fires only on a visible
59
+ change (new value, new or deactivated variant, name, defaults, deactivating
60
+ the group). Two deliveries may overtake each other: keep the one with the
61
+ later `updatedAt`.
62
+ - **Errors**: `INVENTORY_ERROR_CODES` appends `variant_group_not_found`,
63
+ `variant_already_exists` (with `field`, and `articleId` of the existing
64
+ variant), `invalid_variant_attributes` (with `field` and `errors[]`),
65
+ `variant_group_inactive` and `variant_limit`. `too_many_positions` now also
66
+ answers a variant request that would need more writes than fit into one
67
+ operation, with `field` (`variants`, `createMatrix`, or `externalIds` for
68
+ `addVariant`); nothing is written then.
69
+ - **Contract**: `fixtures/v3/` pulled from the backend (stage 5c); the
70
+ vocabulary of `./stored` regenerated from it (fingerprint only, no schema
71
+ change for stored documents).
72
+
7
73
  ## 1.5.1
8
74
 
9
75
  Every call with an effect reports `outcome: 'unknown'` when it fails after
package/README.md CHANGED
@@ -1482,7 +1482,8 @@ ledger, and get every stock change pushed by webhook within seconds, also the
1482
1482
  ones made at the register in the shop. Since 1.5.0 also the write side:
1483
1483
  create and update articles, book goods receipts, transfers, losses and
1484
1484
  condition changes, and reserve stock at checkout (see
1485
- [Shop: reserve and invoice](#shop-reserve-and-invoice)). Uses the `api_key` of
1485
+ [Shop: reserve and invoice](#shop-reserve-and-invoice)); since 1.6.0 variant
1486
+ groups (sizes, colours, see [Variants](#variants)). Uses the `api_key` of
1486
1487
  the account and belongs on a **server**. Reading needs the module `lager`,
1487
1488
  writing additionally the account switch *Lager-API schreiben*, which Kasseneck
1488
1489
  turns on (always on in the test environment, `kr_test_…`; otherwise
@@ -1603,8 +1604,13 @@ answer of the first call, the same key with different content gives
1603
1604
  **same** key, never with a new one. Since 1.5.1 every write, reservation and
1604
1605
  webhook call reports `outcome: 'unknown'` in that case (also after HTTP 5xx or
1605
1606
  an unreadable answer; before: `'rejected'`), so `isOutcomeUnknown(error)` is
1606
- the signal to resend with the same key; `previewGoodsReceipt` and the reading
1607
- calls stay `'rejected'`. The client refuses to send a write without
1607
+ the signal to resend writes and reservations with the same key;
1608
+ `previewGoodsReceipt` and the reading calls stay `'rejected'`. The webhook
1609
+ calls (`createWebhook`, `updateWebhook`, `deleteWebhook`,
1610
+ `rotateWebhookSecret`, `sendWebhookTest`) have no key: after `'unknown'` look
1611
+ the state up first (`listWebhooks`, `listWebhookDeliveries`) instead of
1612
+ resending, or you get a second webhook, a second new secret or a used-up test
1613
+ delivery. The client refuses to send a write without
1608
1614
  a valid key, and checks before sending only what is certainly wrong without the
1609
1615
  network (required ids, integer quantities, amounts and prices, the range of
1610
1616
  `expiresInMinutes`); everything else the server decides and reports with its
@@ -1747,6 +1753,116 @@ function onDelivery(rawBody: Buffer) {
1747
1753
  net without webhooks; the stock ledger shows reservations as movements of
1748
1754
  type `reservation` with `quantityDelta: 0` and the change in `reservedDelta`.
1749
1755
 
1756
+ ### Variants
1757
+
1758
+ A variant is an ordinary article with `variantGroupId` and
1759
+ `variantAttributes`: its own id, code, stock and tile at the register; it is
1760
+ read, booked, reserved and invoiced like any other article. The variant group
1761
+ holds what the variants share (name, attributes with their values, defaults
1762
+ for new variants) and guarantees that each combination exists only once. The
1763
+ writes take an `idempotencyKey` and the account switch *Lager-API schreiben*,
1764
+ like every other write.
1765
+
1766
+ ```ts
1767
+ import { createInventoryClient, isInventoryError, parseInventoryWebhookEvent } from '@kreiseck/kasseneck-api/inventory';
1768
+
1769
+ const inventory = createInventoryClient({ apiKey: process.env.KASSENECK_API_KEY! });
1770
+
1771
+ // 1. Create the group with every combination (3 sizes × 2 colours = 6 variants).
1772
+ const apron = await inventory.createVariantGroup({
1773
+ idempotencyKey: 'shop-group-3001',
1774
+ name: 'Schürze',
1775
+ attributes: [
1776
+ { key: 'size', label: 'Größe', values: ['S', 'M', 'L'] },
1777
+ { key: 'colour', label: 'Farbe', values: ['rot', 'blau'] },
1778
+ ],
1779
+ defaults: { unitPriceCents: 2490, vatRate: 20, stockTracked: true },
1780
+ createMatrix: true,
1781
+ });
1782
+ // apron.variants: [{ articleId, variantAttributes: { colour: 'rot', size: 'S' } }, …]
1783
+
1784
+ // 2. The answer carries ids only. Read the articles of the group (names
1785
+ // "Schürze S rot" …, own codes) and map them to the shop's products.
1786
+ for await (const article of inventory.iterateArticles({ variantGroupId: apron.id })) {
1787
+ await shop.linkVariant(article.variantAttributes!, article.id, article.internalCode);
1788
+ }
1789
+
1790
+ // 3. A new size later: add the value, then the variants you want.
1791
+ await inventory.updateVariantGroup({
1792
+ idempotencyKey: 'shop-group-3001-xl',
1793
+ variantGroupId: apron.id,
1794
+ addAttributeValues: { size: ['S', 'M', 'L', 'XL'] }, // known values are skipped
1795
+ });
1796
+ try {
1797
+ await inventory.addVariant({
1798
+ idempotencyKey: 'shop-variant-3001-xl-rot',
1799
+ variantGroupId: apron.id,
1800
+ variantAttributes: { size: 'XL', colour: 'rot' },
1801
+ ean: '9001234567834', // optional: a foreign article with this code
1802
+ });
1803
+ } catch (error) {
1804
+ if (!isInventoryError(error, 'variant_already_exists')) throw error;
1805
+ // Exists already (error.details.articleId): link that one instead.
1806
+ }
1807
+
1808
+ // 4. Webhooks: keep the group state with the latest updatedAt.
1809
+ function onDelivery(rawBody: Buffer) {
1810
+ const event = parseInventoryWebhookEvent(rawBody);
1811
+ if (event && !event.test && (event.type === 'variant_group.created' || event.type === 'variant_group.updated')) {
1812
+ return shop.saveGroupIfNewer(event.data.id, event.data, event.data.updatedAt);
1813
+ }
1814
+ }
1815
+ ```
1816
+
1817
+ - **Limits.** At most 3 attributes per group (keys `^[a-z0-9_]{1,32}$`,
1818
+ `__…__` is reserved), at most 30 values per attribute (1 to 30 characters,
1819
+ unique ignoring case), at most 100 combinations with `createMatrix` and at
1820
+ most 100 entries in `variants[]` per request, at most 250 active variants
1821
+ per group (`variant_limit`). The client does not check these before sending
1822
+ (the server may raise them); they are exported as
1823
+ `VARIANT_ATTRIBUTES_MAX`, `VARIANT_VALUES_MAX`, `VARIANT_MATRIX_MAX` and
1824
+ `VARIANT_GROUP_ACTIVE_MAX`. A request that would need more writes than fit
1825
+ into one operation (about 187 external ids with 100 variants) is refused as
1826
+ a whole with `too_many_positions` and `field` (`variants`, `createMatrix`,
1827
+ or `externalIds` for `addVariant`); nothing is written. Send fewer variants
1828
+ and add the rest with `addVariant`.
1829
+ - **Order.** `attributes` keeps the order of the group: it decides the default
1830
+ name "<group> <value1> <value2>" and the matrix (the first attribute runs
1831
+ outermost). `variantAttributes` on articles, in `variants[]` and in webhooks
1832
+ comes with its keys **sorted by code point**, not in attribute order; compare
1833
+ by key, never by position. Values are stored trimmed and in Unicode NFC; a
1834
+ variant's value must match a listed value exactly (case and spaces are not
1835
+ adjusted), otherwise `invalid_variant_attributes` names the `field`.
1836
+ - **Variants are articles.** `addVariant` answers with the article as
1837
+ `createArticle` does. Each variant takes the fields of `createArticle`;
1838
+ fields it does not name are filled from the group defaults **at creation
1839
+ only**: changing the group name or defaults later changes no existing
1840
+ variant (use `updateArticle`). `createArticle` and `updateArticle` refuse
1841
+ `variantGroupId` and `variantAttributes`; a variant is never moved to another
1842
+ group, and an existing article never becomes a variant.
1843
+ - **Deactivating.** `deactivateArticle` on one variant of an active group
1844
+ takes it out of the group's `variants[]` and frees its combination for a new
1845
+ variant.
1846
+ `updateVariantGroup({ active: false })` deactivates the group and every
1847
+ variant (codes and external ids become free), stands alone and is final; a
1848
+ deactivated group answers every other change and `addVariant` with
1849
+ `variant_group_inactive`. The answer comes when all variants are
1850
+ deactivated; after `outcome: 'unknown'` simply repeat it, also with a new
1851
+ key, it completes an interrupted run.
1852
+ - **After `unknown`.** As with every write: resend with the **same**
1853
+ `idempotencyKey`. A new key would create the group a second time (the
1854
+ combination check is per group). `variant_already_exists` on `addVariant`
1855
+ carries `articleId` of the existing variant.
1856
+ - **Events.** `variant_group.created` and `variant_group.updated` carry the
1857
+ group as `getVariantGroup` returns it (with `variants[]`, without articles).
1858
+ `updated` fires only on a visible change; creating a variant also sends
1859
+ `article.created`, deactivating the group one `variant_group.updated` and
1860
+ one `article.deactivated` per variant. Deliveries can overtake each other:
1861
+ keep a group state only if its `updatedAt` is later than the stored one.
1862
+ Without webhooks, `listVariantGroups({ updatedSince })` and
1863
+ `listArticles({ variantGroupId, updatedSince })` are sorted by `updatedAt`
1864
+ ascending and include the boundary.
1865
+
1750
1866
  ## Migrating from 0.x
1751
1867
 
1752
1868
  1.0 is one breaking step: the wire, the exported names and the contract files
@@ -13,7 +13,7 @@
13
13
  * umhuellt, muss ihn weiterhin absetzen koennen.
14
14
  */
15
15
  import type { TransportBodyFields, TransportCallOptions } 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", "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"];
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", "createArticle", "updateArticle", "deactivateArticle", "receiveGoods", "transferStock", "recordStockLoss", "changeStockCondition", "reverseStockMovement", "createReservation", "extendReservation", "releaseReservation", "getReservation", "listReservations", "createVariantGroup", "updateVariantGroup", "getVariantGroup", "listVariantGroups", "addVariant"];
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", "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"];
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", "createArticle", "updateArticle", "deactivateArticle", "receiveGoods", "transferStock", "recordStockLoss", "changeStockCondition", "reverseStockMovement", "createReservation", "extendReservation", "releaseReservation", "getReservation", "listReservations", "createVariantGroup", "updateVariantGroup", "getVariantGroup", "listVariantGroups", "addVariant"];
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
@@ -49,7 +49,7 @@ export type PosCall = typeof POS_CALLS[number];
49
49
  * [ALL_CALLS], [PUBLIC_CALLS] und [POS_CALLS] steht entweder hier oder in
50
50
  * [CALLS_WITHOUT_EFFECT] (Waechter `test/ausgang-einordnung.test.ts`).
51
51
  */
52
- export declare const UNKNOWN_OUTCOME_CALLS: readonly ["activateCashregister", "cancelInvoice", "cancelReceipt", "changeStockCondition", "createArticle", "createCreditNote", "createCustomer", "createCustomerCashregister", "createInvoiceItem", "createPartnerCustomer", "createPartnerWebhook", "createPrintJob", "createReceipt", "createReservation", "createWebhook", "deactivateArticle", "deletePartnerWebhook", "deleteWebhook", "extendReservation", "financeWebService", "hobexPayApi", "hobexRefundApi", "issueInvoice", "pairRegisterDevice", "receiveGoods", "recordInvoicePayment", "recordStockLoss", "releaseReservation", "reportCustomerContract", "requestCustomerSignature", "reverseStockMovement", "revokeCustomerMandate", "rotatePartnerWebhookSecret", "rotateWebhookSecret", "sendPartnerCustomerFonLink", "sendPartnerWebhookTest", "sendReceiptEmail", "sendWebhookTest", "setCustomerMandate", "setMyCashregisterStockLocation", "setMyKasseLogo", "setMyKasseSettings", "setMyRegisterDeviceSettings", "stripeCaptureIntent", "transferStock", "unpairRegisterDevice", "updateArticle", "updateCustomer", "updateInvoiceItem", "updatePartnerWebhook", "updateWebhook", "withdrawInvoiceItem"];
52
+ export declare const UNKNOWN_OUTCOME_CALLS: readonly ["activateCashregister", "addVariant", "cancelInvoice", "cancelReceipt", "changeStockCondition", "createArticle", "createCreditNote", "createCustomer", "createCustomerCashregister", "createInvoiceItem", "createPartnerCustomer", "createPartnerWebhook", "createPrintJob", "createReceipt", "createReservation", "createVariantGroup", "createWebhook", "deactivateArticle", "deletePartnerWebhook", "deleteWebhook", "extendReservation", "financeWebService", "hobexPayApi", "hobexRefundApi", "issueInvoice", "pairRegisterDevice", "receiveGoods", "recordInvoicePayment", "recordStockLoss", "releaseReservation", "reportCustomerContract", "requestCustomerSignature", "reverseStockMovement", "revokeCustomerMandate", "rotatePartnerWebhookSecret", "rotateWebhookSecret", "sendPartnerCustomerFonLink", "sendPartnerWebhookTest", "sendReceiptEmail", "sendWebhookTest", "setCustomerMandate", "setMyCashregisterStockLocation", "setMyKasseLogo", "setMyKasseSettings", "setMyRegisterDeviceSettings", "stripeCaptureIntent", "transferStock", "unpairRegisterDevice", "updateArticle", "updateCustomer", "updateInvoiceItem", "updatePartnerWebhook", "updateVariantGroup", "updateWebhook", "withdrawInvoiceItem"];
53
53
  /** Warum ein Aufruf keine Wirkung hat, die ein Zeitlimit offen lassen koennte. */
54
54
  export type CallWithoutEffectReason = 'read' | 'repeatable';
55
55
  /**
@@ -105,6 +105,12 @@ exports.ALL_CALLS = [
105
105
  'releaseReservation',
106
106
  'getReservation',
107
107
  'listReservations',
108
+ // Lager-API Varianten (Stufe 5c, ./inventory)
109
+ 'createVariantGroup',
110
+ 'updateVariantGroup',
111
+ 'getVariantGroup',
112
+ 'listVariantGroups',
113
+ 'addVariant',
108
114
  ];
109
115
  /**
110
116
  * Die oeffentlichen Endpunkte unter `/v3` (`https://api.kasseneck.at/v3/<name>`),
@@ -205,6 +211,12 @@ exports.PUBLIC_CALLS = [
205
211
  'releaseReservation',
206
212
  'getReservation',
207
213
  'listReservations',
214
+ // Lager-API Varianten (Backend Stufe 5c), umhuellt in `./inventory`.
215
+ 'createVariantGroup',
216
+ 'updateVariantGroup',
217
+ 'getVariantGroup',
218
+ 'listVariantGroups',
219
+ 'addVariant',
208
220
  ];
209
221
  /**
210
222
  * Die Endpunkte des Kassenwegs (`https://kasse.kasseneck.at/api/v3/<name>`,
@@ -263,6 +275,7 @@ exports.POS_CALLS = [
263
275
  */
264
276
  exports.UNKNOWN_OUTCOME_CALLS = [
265
277
  'activateCashregister',
278
+ 'addVariant',
266
279
  'cancelInvoice',
267
280
  'cancelReceipt',
268
281
  'changeStockCondition',
@@ -276,6 +289,7 @@ exports.UNKNOWN_OUTCOME_CALLS = [
276
289
  'createPrintJob',
277
290
  'createReceipt',
278
291
  'createReservation',
292
+ 'createVariantGroup',
279
293
  'createWebhook',
280
294
  'deactivateArticle',
281
295
  'deletePartnerWebhook',
@@ -312,6 +326,7 @@ exports.UNKNOWN_OUTCOME_CALLS = [
312
326
  'updateCustomer',
313
327
  'updateInvoiceItem',
314
328
  'updatePartnerWebhook',
329
+ 'updateVariantGroup',
315
330
  'updateWebhook',
316
331
  'withdrawInvoiceItem',
317
332
  ];
@@ -367,6 +382,7 @@ exports.CALLS_WITHOUT_EFFECT = Object.freeze({
367
382
  getReportV2: 'read',
368
383
  getReservation: 'read',
369
384
  getStock: 'read',
385
+ getVariantGroup: 'read',
370
386
  hobexGetStatus: 'read',
371
387
  listArticles: 'read',
372
388
  listBrands: 'read',
@@ -390,6 +406,7 @@ exports.CALLS_WITHOUT_EFFECT = Object.freeze({
390
406
  listReservations: 'read',
391
407
  listStock: 'read',
392
408
  listStockMovements: 'read',
409
+ listVariantGroups: 'read',
393
410
  listWebhookDeliveries: 'read',
394
411
  listWebhooks: 'read',
395
412
  lookupArticleByCode: 'read',
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * Fassade ueber den Aufrufen der Lager-API (lesen, Webhooks, schreiben,
3
- * reservieren): Schluessel einmal binden, dann rufen. Wie [createInvoiceApi] bewusst keine Klasse; die Aufrufe sind freie
3
+ * reservieren, Varianten): Schluessel einmal binden, dann rufen. Wie [createInvoiceApi] bewusst keine Klasse; die Aufrufe sind freie
4
4
  * Funktionen (endpunkte.ts) und bleiben einzeln importierbar.
5
5
  */
6
6
  import { type FetchLike } from '../client/transport.js';
7
- import type { Article, ChangeStockConditionRequest, CreateArticleRequest, CreateReservationRequest, DeactivateArticleRequest, ExtendReservationRequest, GoodsReceiptPreview, GoodsReceiptPreviewRequest, ReceiveGoodsRequest, RecordStockLossRequest, ReleaseReservationRequest, Reservation, ReservationListQuery, ReservationPage, ReverseStockMovementRequest, StockOperation, TransferStockRequest, UpdateArticleRequest, ArticleListQuery, ArticleLookup, ArticlePage, CreateInventoryWebhookOptions, InventoryWebhook, InventoryWebhookDelivery, InventoryWebhookList, InventoryWebhookPatch, InventoryWebhookTestResult, InventoryWebhookWithSecret, Location, StockLevel, StockListQuery, StockMovement, StockMovementPage, StockMovementQuery, StockPage, StockResult } from './typen.js';
7
+ import type { AddVariantRequest, CreateVariantGroupRequest, UpdateVariantGroupRequest, VariantGroup, VariantGroupListQuery, VariantGroupPage, Article, ChangeStockConditionRequest, CreateArticleRequest, CreateReservationRequest, DeactivateArticleRequest, ExtendReservationRequest, GoodsReceiptPreview, GoodsReceiptPreviewRequest, ReceiveGoodsRequest, RecordStockLossRequest, ReleaseReservationRequest, Reservation, ReservationListQuery, ReservationPage, ReverseStockMovementRequest, StockOperation, TransferStockRequest, UpdateArticleRequest, ArticleListQuery, ArticleLookup, ArticlePage, CreateInventoryWebhookOptions, InventoryWebhook, InventoryWebhookDelivery, InventoryWebhookList, InventoryWebhookPatch, InventoryWebhookTestResult, InventoryWebhookWithSecret, Location, StockLevel, StockListQuery, StockMovement, StockMovementPage, StockMovementQuery, StockPage, StockResult } from './typen.js';
8
8
  import type { InventoryWebhookEventType } from './vertrag.js';
9
9
  export interface InventoryClientOptions {
10
10
  /** `api_key` des Kontos (`kr_live_…` / `kr_test_…`). Gehoert auf einen Server. */
@@ -57,5 +57,13 @@ export interface InventoryClient {
57
57
  getReservation(reservationId: string): Promise<Reservation>;
58
58
  listReservations(query?: ReservationListQuery): Promise<ReservationPage>;
59
59
  iterateReservations(query?: ReservationListQuery): AsyncGenerator<Reservation, void, undefined>;
60
+ createVariantGroup(request: CreateVariantGroupRequest): Promise<VariantGroup>;
61
+ /** Name, Vorgaben, neue Werte; oder `active: false` (Gruppe und alle Varianten stilllegen, endgueltig). */
62
+ updateVariantGroup(request: UpdateVariantGroupRequest): Promise<VariantGroup>;
63
+ /** Eine Variante mehr; Antwort: der Artikel wie `createArticle`. */
64
+ addVariant(request: AddVariantRequest): Promise<Article>;
65
+ getVariantGroup(variantGroupId: string): Promise<VariantGroup>;
66
+ listVariantGroups(query?: VariantGroupListQuery): Promise<VariantGroupPage>;
67
+ iterateVariantGroups(query?: VariantGroupListQuery): AsyncGenerator<VariantGroup, void, undefined>;
60
68
  }
61
69
  export declare function createInventoryClient(options: InventoryClientOptions): InventoryClient;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  /**
3
3
  * Fassade ueber den Aufrufen der Lager-API (lesen, Webhooks, schreiben,
4
- * reservieren): Schluessel einmal binden, dann rufen. Wie [createInvoiceApi] bewusst keine Klasse; die Aufrufe sind freie
4
+ * reservieren, Varianten): Schluessel einmal binden, dann rufen. Wie [createInvoiceApi] bewusst keine Klasse; die Aufrufe sind freie
5
5
  * Funktionen (endpunkte.ts) und bleiben einzeln importierbar.
6
6
  */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -10,6 +10,7 @@ const transport_js_1 = require("../client/transport.js");
10
10
  const auth_js_1 = require("./auth.js");
11
11
  const endpunkte_js_1 = require("./endpunkte.js");
12
12
  const schreiben_js_1 = require("./schreiben.js");
13
+ const varianten_js_1 = require("./varianten.js");
13
14
  function createInventoryClient(options) {
14
15
  const rufen = (0, transport_js_1.createTransport)({
15
16
  auth: (0, auth_js_1.inventoryKeyAuth)({ apiKey: options.apiKey }),
@@ -50,5 +51,11 @@ function createInventoryClient(options) {
50
51
  getReservation: (id) => (0, schreiben_js_1.getReservation)(rufen, id),
51
52
  listReservations: (q) => (0, schreiben_js_1.listReservations)(rufen, q),
52
53
  iterateReservations: (q) => (0, schreiben_js_1.iterateReservations)(rufen, q),
54
+ createVariantGroup: (r) => (0, varianten_js_1.createVariantGroup)(rufen, r),
55
+ updateVariantGroup: (r) => (0, varianten_js_1.updateVariantGroup)(rufen, r),
56
+ addVariant: (r) => (0, varianten_js_1.addVariant)(rufen, r),
57
+ getVariantGroup: (id) => (0, varianten_js_1.getVariantGroup)(rufen, id),
58
+ listVariantGroups: (q) => (0, varianten_js_1.listVariantGroups)(rufen, q),
59
+ iterateVariantGroups: (q) => (0, varianten_js_1.iterateVariantGroups)(rufen, q),
53
60
  };
54
61
  }
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * Die Aufrufe der Lager-API: Artikel, Standorte, Bestand und Bewegungen
3
3
  * lesen, Konto-Webhooks verwalten (Backend Stufe 5a). Die schreibenden
4
- * Aufrufe (Stufe 5b) stehen in `schreiben.ts` und teilen die Helfer hier.
4
+ * Aufrufe (Stufe 5b) stehen in `schreiben.ts`, die Variantengruppen (Stufe 5c)
5
+ * in `varianten.ts`; beide teilen die Helfer hier.
5
6
  *
6
7
  * Jede Funktion nimmt den Transport als ersten Parameter und ist einzeln
7
8
  * importierbar; die Fassade [createInventoryClient] bindet ihn nur einmal.
@@ -2,7 +2,8 @@
2
2
  /**
3
3
  * Die Aufrufe der Lager-API: Artikel, Standorte, Bestand und Bewegungen
4
4
  * lesen, Konto-Webhooks verwalten (Backend Stufe 5a). Die schreibenden
5
- * Aufrufe (Stufe 5b) stehen in `schreiben.ts` und teilen die Helfer hier.
5
+ * Aufrufe (Stufe 5b) stehen in `schreiben.ts`, die Variantengruppen (Stufe 5c)
6
+ * in `varianten.ts`; beide teilen die Helfer hier.
6
7
  *
7
8
  * Jede Funktion nimmt den Transport als ersten Parameter und ist einzeln
8
9
  * importierbar; die Fassade [createInventoryClient] bindet ihn nur einmal.
@@ -2,7 +2,8 @@
2
2
  * `@kreiseck/kasseneck-api/inventory` – die Lager-API: Artikel, Standorte,
3
3
  * Bestand und Lagerprotokoll lesen, Konto-Webhooks verwalten und eingehende
4
4
  * Zustellungen pruefen (Backend Stufe 5a); Artikel anlegen und aendern,
5
- * Bestand buchen und Ware reservieren (Stufe 5b, seit 1.5.0).
5
+ * Bestand buchen und Ware reservieren (Stufe 5b, seit 1.5.0);
6
+ * Variantengruppen (Stufe 5c, seit 1.6.0).
6
7
  *
7
8
  * Ein eigener Unterpfad wie `invoice`: der `api_key` eines Kontos gehoert auf
8
9
  * einen **Server** (etwa das Backend eines Online-Shops) und soll nicht
@@ -16,6 +17,7 @@ export { inventoryKeyAuth, type InventoryKeyAuthOptions } from './auth.js';
16
17
  export { isInventoryError, isInventoryErrorCode, inventoryErrorCode, inventoryFieldErrors, inventoryRetryAfterSec, inventoryShortfalls, isInventoryWarningCode, type InventoryApiErrorCode, type InventoryFieldError, } from './fehler.js';
17
18
  export { createWebhook, deleteWebhook, getArticle, getStock, iterateArticles, iterateStock, iterateStockMovements, listArticles, listLocations, listStock, listStockMovements, listWebhookDeliveries, listWebhooks, lookupArticleByCode, rotateWebhookSecret, sendWebhookTest, updateWebhook, } from './endpunkte.js';
18
19
  export { changeStockCondition, createArticle, createReservation, deactivateArticle, extendReservation, getReservation, iterateReservations, listReservations, previewGoodsReceipt, receiveGoods, recordStockLoss, releaseReservation, reverseStockMovement, transferStock, updateArticle, } from './schreiben.js';
20
+ export { addVariant, createVariantGroup, getVariantGroup, iterateVariantGroups, listVariantGroups, updateVariantGroup, } from './varianten.js';
19
21
  export { verifyInventoryWebhookSignature, parseInventoryWebhookEvent, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_EVENT_HEADER, WEBHOOK_DELIVERY_HEADER, WEBHOOK_TOLERANCE_SEC, type VerifyInventoryWebhookOptions, } from './webhook.js';
20
- export type { Article, ArticleInput, ArticleListQuery, ArticleLookup, ArticlePage, ChangeStockConditionRequest, CreateArticleRequest, CreateInventoryWebhookOptions, CreateReservationRequest, DeactivateArticleRequest, ExtendReservationRequest, GoodsReceiptItem, GoodsReceiptPreview, GoodsReceiptPreviewLine, GoodsReceiptPreviewRequest, InventoryShortfall, InventoryWarning, InventoryWebhook, InventoryWebhookDelivery, InventoryWebhookEnvelope, InventoryWebhookEvent, InventoryWebhookList, InventoryWebhookPatch, InventoryWebhookTestDelivery, InventoryWebhookTestResult, InventoryWebhookWithSecret, LandedCost, Location, LocationAddress, ReceiveGoodsRequest, RecordStockLossRequest, ReleaseReservationItem, ReleaseReservationRequest, Reservation, ReservationItem, ReservationItemInput, ReservationListQuery, ReservationPage, ReverseStockMovementRequest, StockBelowMinimumEventData, StockChangedEventData, StockItem, StockLevel, StockListQuery, StockMovement, StockMovementLot, StockMovementPage, StockMovementQuery, StockMovementSourceRef, StockOperation, StockPage, StockResult, StockValue, TransferStockRequest, UpdateArticleRequest, } from './typen.js';
21
- export { INVENTORY_ENDPOINTS, INVENTORY_ERROR_CODES, INVENTORY_REQUEST_ERROR_CODES, INVENTORY_WEBHOOK_EVENTS, INVENTORY_WEBHOOK_ENVELOPE_FIELDS, INVENTORY_WEBHOOK_LIMIT, INVENTORY_LIST_LIMIT_MAX, LOCATION_TYPES, STOCK_MOVEMENT_TYPES, STOCK_MOVEMENT_SOURCES, STOCK_CONDITIONS, STOCK_CHANGE_CAUSES, WEBHOOK_DELIVERY_STATUSES, INVENTORY_WARNING_CODES, STOCK_KINDS, STOCK_LOSS_REASONS, WITHDRAWAL_TYPES, LANDED_COST_TYPES, LANDED_COST_ALLOCATIONS, RESERVATION_STATUSES, INVENTORY_IDEMPOTENCY_KEY_MAX, RESERVATION_MINUTES_MIN, RESERVATION_MINUTES_MAX, type InventoryEndpoint, type InventoryErrorCode, type InventoryRequestErrorCode, type InventoryWebhookEventType, type LocationType, type StockMovementType, type StockMovementSource, type StockCondition, type StockChangeCause, type WebhookDeliveryStatus, type InventoryWarningCode, type StockKind, type StockLossReason, type WithdrawalType, type LandedCostType, type LandedCostAllocation, type ReservationStatus, } from './vertrag.js';
22
+ export type { AddVariantRequest, Article, ArticleInput, ArticleListQuery, ArticleLookup, ArticlePage, ChangeStockConditionRequest, CreateArticleRequest, CreateInventoryWebhookOptions, CreateReservationRequest, CreateVariantGroupRequest, DeactivateArticleRequest, ExtendReservationRequest, GoodsReceiptItem, GoodsReceiptPreview, GoodsReceiptPreviewLine, GoodsReceiptPreviewRequest, InventoryShortfall, InventoryWarning, InventoryWebhook, InventoryWebhookDelivery, InventoryWebhookEnvelope, InventoryWebhookEvent, InventoryWebhookList, InventoryWebhookPatch, InventoryWebhookTestDelivery, InventoryWebhookTestResult, InventoryWebhookWithSecret, LandedCost, Location, LocationAddress, ReceiveGoodsRequest, RecordStockLossRequest, ReleaseReservationItem, ReleaseReservationRequest, Reservation, ReservationItem, ReservationItemInput, ReservationListQuery, ReservationPage, ReverseStockMovementRequest, StockBelowMinimumEventData, StockChangedEventData, StockItem, StockLevel, StockListQuery, StockMovement, StockMovementLot, StockMovementPage, StockMovementQuery, StockMovementSourceRef, StockOperation, StockPage, StockResult, StockValue, TransferStockRequest, UpdateArticleRequest, UpdateVariantGroupRequest, VariantAttribute, VariantGroup, VariantGroupDefaults, VariantGroupDefaultsInput, VariantGroupListQuery, VariantGroupMember, VariantGroupPage, VariantInput, } from './typen.js';
23
+ export { INVENTORY_ENDPOINTS, INVENTORY_ERROR_CODES, INVENTORY_REQUEST_ERROR_CODES, INVENTORY_WEBHOOK_EVENTS, INVENTORY_WEBHOOK_ENVELOPE_FIELDS, INVENTORY_WEBHOOK_LIMIT, INVENTORY_LIST_LIMIT_MAX, LOCATION_TYPES, STOCK_MOVEMENT_TYPES, STOCK_MOVEMENT_SOURCES, STOCK_CONDITIONS, STOCK_CHANGE_CAUSES, WEBHOOK_DELIVERY_STATUSES, INVENTORY_WARNING_CODES, STOCK_KINDS, STOCK_LOSS_REASONS, WITHDRAWAL_TYPES, LANDED_COST_TYPES, LANDED_COST_ALLOCATIONS, RESERVATION_STATUSES, INVENTORY_IDEMPOTENCY_KEY_MAX, RESERVATION_MINUTES_MIN, RESERVATION_MINUTES_MAX, VARIANT_ATTRIBUTES_MAX, VARIANT_VALUES_MAX, VARIANT_MATRIX_MAX, VARIANT_GROUP_ACTIVE_MAX, type InventoryEndpoint, type InventoryErrorCode, type InventoryRequestErrorCode, type InventoryWebhookEventType, type LocationType, type StockMovementType, type StockMovementSource, type StockCondition, type StockChangeCause, type WebhookDeliveryStatus, type InventoryWarningCode, type StockKind, type StockLossReason, type WithdrawalType, type LandedCostType, type LandedCostAllocation, type ReservationStatus, } from './vertrag.js';
@@ -3,7 +3,8 @@
3
3
  * `@kreiseck/kasseneck-api/inventory` – die Lager-API: Artikel, Standorte,
4
4
  * Bestand und Lagerprotokoll lesen, Konto-Webhooks verwalten und eingehende
5
5
  * Zustellungen pruefen (Backend Stufe 5a); Artikel anlegen und aendern,
6
- * Bestand buchen und Ware reservieren (Stufe 5b, seit 1.5.0).
6
+ * Bestand buchen und Ware reservieren (Stufe 5b, seit 1.5.0);
7
+ * Variantengruppen (Stufe 5c, seit 1.6.0).
7
8
  *
8
9
  * Ein eigener Unterpfad wie `invoice`: der `api_key` eines Kontos gehoert auf
9
10
  * einen **Server** (etwa das Backend eines Online-Shops) und soll nicht
@@ -13,8 +14,8 @@
13
14
  * Mikro-Euro; alles Ganzzahlen.
14
15
  */
15
16
  Object.defineProperty(exports, "__esModule", { value: true });
16
- exports.INVENTORY_REQUEST_ERROR_CODES = exports.INVENTORY_ERROR_CODES = exports.INVENTORY_ENDPOINTS = exports.WEBHOOK_TOLERANCE_SEC = exports.WEBHOOK_DELIVERY_HEADER = exports.WEBHOOK_EVENT_HEADER = exports.WEBHOOK_SIGNATURE_HEADER = exports.parseInventoryWebhookEvent = exports.verifyInventoryWebhookSignature = exports.updateArticle = exports.transferStock = exports.reverseStockMovement = exports.releaseReservation = exports.recordStockLoss = exports.receiveGoods = exports.previewGoodsReceipt = exports.listReservations = exports.iterateReservations = exports.getReservation = exports.extendReservation = exports.deactivateArticle = exports.createReservation = exports.createArticle = exports.changeStockCondition = exports.updateWebhook = exports.sendWebhookTest = exports.rotateWebhookSecret = exports.lookupArticleByCode = exports.listWebhooks = exports.listWebhookDeliveries = exports.listStockMovements = exports.listStock = exports.listLocations = exports.listArticles = exports.iterateStockMovements = exports.iterateStock = exports.iterateArticles = exports.getStock = exports.getArticle = exports.deleteWebhook = exports.createWebhook = exports.isInventoryWarningCode = exports.inventoryShortfalls = exports.inventoryRetryAfterSec = exports.inventoryFieldErrors = exports.inventoryErrorCode = exports.isInventoryErrorCode = exports.isInventoryError = exports.inventoryKeyAuth = exports.createInventoryClient = void 0;
17
- exports.RESERVATION_MINUTES_MAX = exports.RESERVATION_MINUTES_MIN = exports.INVENTORY_IDEMPOTENCY_KEY_MAX = exports.RESERVATION_STATUSES = exports.LANDED_COST_ALLOCATIONS = exports.LANDED_COST_TYPES = exports.WITHDRAWAL_TYPES = exports.STOCK_LOSS_REASONS = exports.STOCK_KINDS = exports.INVENTORY_WARNING_CODES = exports.WEBHOOK_DELIVERY_STATUSES = exports.STOCK_CHANGE_CAUSES = exports.STOCK_CONDITIONS = exports.STOCK_MOVEMENT_SOURCES = exports.STOCK_MOVEMENT_TYPES = exports.LOCATION_TYPES = exports.INVENTORY_LIST_LIMIT_MAX = exports.INVENTORY_WEBHOOK_LIMIT = exports.INVENTORY_WEBHOOK_ENVELOPE_FIELDS = exports.INVENTORY_WEBHOOK_EVENTS = void 0;
17
+ exports.WEBHOOK_SIGNATURE_HEADER = exports.parseInventoryWebhookEvent = exports.verifyInventoryWebhookSignature = exports.updateVariantGroup = exports.listVariantGroups = exports.iterateVariantGroups = exports.getVariantGroup = exports.createVariantGroup = exports.addVariant = exports.updateArticle = exports.transferStock = exports.reverseStockMovement = exports.releaseReservation = exports.recordStockLoss = exports.receiveGoods = exports.previewGoodsReceipt = exports.listReservations = exports.iterateReservations = exports.getReservation = exports.extendReservation = exports.deactivateArticle = exports.createReservation = exports.createArticle = exports.changeStockCondition = exports.updateWebhook = exports.sendWebhookTest = exports.rotateWebhookSecret = exports.lookupArticleByCode = exports.listWebhooks = exports.listWebhookDeliveries = exports.listStockMovements = exports.listStock = exports.listLocations = exports.listArticles = exports.iterateStockMovements = exports.iterateStock = exports.iterateArticles = exports.getStock = exports.getArticle = exports.deleteWebhook = exports.createWebhook = exports.isInventoryWarningCode = exports.inventoryShortfalls = exports.inventoryRetryAfterSec = exports.inventoryFieldErrors = exports.inventoryErrorCode = exports.isInventoryErrorCode = exports.isInventoryError = exports.inventoryKeyAuth = exports.createInventoryClient = void 0;
18
+ exports.VARIANT_GROUP_ACTIVE_MAX = exports.VARIANT_MATRIX_MAX = exports.VARIANT_VALUES_MAX = exports.VARIANT_ATTRIBUTES_MAX = exports.RESERVATION_MINUTES_MAX = exports.RESERVATION_MINUTES_MIN = exports.INVENTORY_IDEMPOTENCY_KEY_MAX = exports.RESERVATION_STATUSES = exports.LANDED_COST_ALLOCATIONS = exports.LANDED_COST_TYPES = exports.WITHDRAWAL_TYPES = exports.STOCK_LOSS_REASONS = exports.STOCK_KINDS = exports.INVENTORY_WARNING_CODES = exports.WEBHOOK_DELIVERY_STATUSES = exports.STOCK_CHANGE_CAUSES = exports.STOCK_CONDITIONS = exports.STOCK_MOVEMENT_SOURCES = exports.STOCK_MOVEMENT_TYPES = exports.LOCATION_TYPES = exports.INVENTORY_LIST_LIMIT_MAX = exports.INVENTORY_WEBHOOK_LIMIT = exports.INVENTORY_WEBHOOK_ENVELOPE_FIELDS = exports.INVENTORY_WEBHOOK_EVENTS = exports.INVENTORY_REQUEST_ERROR_CODES = exports.INVENTORY_ERROR_CODES = exports.INVENTORY_ENDPOINTS = exports.WEBHOOK_TOLERANCE_SEC = exports.WEBHOOK_DELIVERY_HEADER = exports.WEBHOOK_EVENT_HEADER = void 0;
18
19
  var api_js_1 = require("./api.js");
19
20
  Object.defineProperty(exports, "createInventoryClient", { enumerable: true, get: function () { return api_js_1.createInventoryClient; } });
20
21
  var auth_js_1 = require("./auth.js");
@@ -61,6 +62,13 @@ Object.defineProperty(exports, "releaseReservation", { enumerable: true, get: fu
61
62
  Object.defineProperty(exports, "reverseStockMovement", { enumerable: true, get: function () { return schreiben_js_1.reverseStockMovement; } });
62
63
  Object.defineProperty(exports, "transferStock", { enumerable: true, get: function () { return schreiben_js_1.transferStock; } });
63
64
  Object.defineProperty(exports, "updateArticle", { enumerable: true, get: function () { return schreiben_js_1.updateArticle; } });
65
+ var varianten_js_1 = require("./varianten.js");
66
+ Object.defineProperty(exports, "addVariant", { enumerable: true, get: function () { return varianten_js_1.addVariant; } });
67
+ Object.defineProperty(exports, "createVariantGroup", { enumerable: true, get: function () { return varianten_js_1.createVariantGroup; } });
68
+ Object.defineProperty(exports, "getVariantGroup", { enumerable: true, get: function () { return varianten_js_1.getVariantGroup; } });
69
+ Object.defineProperty(exports, "iterateVariantGroups", { enumerable: true, get: function () { return varianten_js_1.iterateVariantGroups; } });
70
+ Object.defineProperty(exports, "listVariantGroups", { enumerable: true, get: function () { return varianten_js_1.listVariantGroups; } });
71
+ Object.defineProperty(exports, "updateVariantGroup", { enumerable: true, get: function () { return varianten_js_1.updateVariantGroup; } });
64
72
  var webhook_js_1 = require("./webhook.js");
65
73
  Object.defineProperty(exports, "verifyInventoryWebhookSignature", { enumerable: true, get: function () { return webhook_js_1.verifyInventoryWebhookSignature; } });
66
74
  Object.defineProperty(exports, "parseInventoryWebhookEvent", { enumerable: true, get: function () { return webhook_js_1.parseInventoryWebhookEvent; } });
@@ -92,3 +100,7 @@ Object.defineProperty(exports, "RESERVATION_STATUSES", { enumerable: true, get:
92
100
  Object.defineProperty(exports, "INVENTORY_IDEMPOTENCY_KEY_MAX", { enumerable: true, get: function () { return vertrag_js_1.INVENTORY_IDEMPOTENCY_KEY_MAX; } });
93
101
  Object.defineProperty(exports, "RESERVATION_MINUTES_MIN", { enumerable: true, get: function () { return vertrag_js_1.RESERVATION_MINUTES_MIN; } });
94
102
  Object.defineProperty(exports, "RESERVATION_MINUTES_MAX", { enumerable: true, get: function () { return vertrag_js_1.RESERVATION_MINUTES_MAX; } });
103
+ Object.defineProperty(exports, "VARIANT_ATTRIBUTES_MAX", { enumerable: true, get: function () { return vertrag_js_1.VARIANT_ATTRIBUTES_MAX; } });
104
+ Object.defineProperty(exports, "VARIANT_VALUES_MAX", { enumerable: true, get: function () { return vertrag_js_1.VARIANT_VALUES_MAX; } });
105
+ Object.defineProperty(exports, "VARIANT_MATRIX_MAX", { enumerable: true, get: function () { return vertrag_js_1.VARIANT_MATRIX_MAX; } });
106
+ Object.defineProperty(exports, "VARIANT_GROUP_ACTIVE_MAX", { enumerable: true, get: function () { return vertrag_js_1.VARIANT_GROUP_ACTIVE_MAX; } });
@@ -12,7 +12,7 @@
12
12
  * wenn der Server sie sendet: „fehlt“ heisst dort „kein Recht“, nicht „leer“.
13
13
  */
14
14
  import { KasseneckValidationError } from '../client/errors.js';
15
- import type { Article, GoodsReceiptPreviewLine, InventoryShortfall, InventoryWebhook, InventoryWebhookDelivery, InventoryWebhookTestDelivery, Location, Reservation, StockBelowMinimumEventData, StockChangedEventData, StockLevel, StockMovement, StockOperation, StockValue } from './typen.js';
15
+ import type { Article, GoodsReceiptPreviewLine, InventoryShortfall, InventoryWebhook, InventoryWebhookDelivery, InventoryWebhookTestDelivery, Location, Reservation, StockBelowMinimumEventData, StockChangedEventData, StockLevel, StockMovement, StockOperation, StockValue, VariantGroup } from './typen.js';
16
16
  type Roh = Record<string, unknown>;
17
17
  /** Ein Leser bekommt den Vorgang (fuer die Meldung) und den Pfad im Rumpf. */
18
18
  export interface Ort {
@@ -38,6 +38,12 @@ export declare function vorschauZeile(ort: Ort, w: unknown): GoodsReceiptPreview
38
38
  export declare function reservierung(ort: Ort, w: unknown): Reservation;
39
39
  /** Die fehlenden Positionen aus `insufficient_available` (`data.details[]`); ein kaputter Eintrag faellt weg. */
40
40
  export declare function fehlmengen(roh: unknown): InventoryShortfall[];
41
+ /**
42
+ * Eine Variantengruppe. `attributes` und `variants` sind zugesagte Listen:
43
+ * fehlen sie, ist die Antwort kaputt (eine leere Liste hiesse „keine Merkmale“
44
+ * bzw. „keine Varianten“).
45
+ */
46
+ export declare function variantengruppe(ort: Ort, w: unknown): VariantGroup;
41
47
  /** Eine zugesagte Liste `data.<feld>`, Eintrag fuer Eintrag gelesen. */
42
48
  export declare function liste<T>(name: string, daten: unknown, feld: string, lesen: (ort: Ort, e: unknown) => T): T[];
43
49
  /** Der Cursor der naechsten Seite; `null` am Ende. Etwas anderes als Text oder `null` ist kaputt. */
@@ -29,6 +29,7 @@ exports.vorgang = vorgang;
29
29
  exports.vorschauZeile = vorschauZeile;
30
30
  exports.reservierung = reservierung;
31
31
  exports.fehlmengen = fehlmengen;
32
+ exports.variantengruppe = variantengruppe;
32
33
  exports.liste = liste;
33
34
  exports.naechsterCursor = naechsterCursor;
34
35
  const errors_js_1 = require("../client/errors.js");
@@ -401,6 +402,80 @@ function fehlmengen(roh) {
401
402
  }
402
403
  return raus;
403
404
  }
405
+ // ---- Varianten (Stufe 5c) ------------------------------------------------------------
406
+ /** Eine Liste von Texten (Werte eines Merkmals); etwas anderes ist kaputt. */
407
+ function textliste(ort, feld, w) {
408
+ if (!Array.isArray(w) || !w.every((x) => typeof x === 'string')) {
409
+ throw antwortfehler(ort.name, `Antwort ist unbrauchbar (data.${ort.pfad}.${feld} ist keine Liste von Texten)`);
410
+ }
411
+ return [...w];
412
+ }
413
+ function merkmal(ort, w) {
414
+ const m = eintrag(ort, w);
415
+ return { key: kennung(ort, 'key', m.key), label: typeof m.label === 'string' ? m.label : '', values: textliste(ort, 'values', m.values) };
416
+ }
417
+ /**
418
+ * Vorgaben einer Gruppe: nur die Felder, die der Server sendet. Ein Preis als
419
+ * Bruchzahl ist kaputt (er fuellte sonst jede neue Variante falsch), ein Feld
420
+ * mit fremdem Typ ebenso.
421
+ */
422
+ function vorgaben(ort, w) {
423
+ if (w === undefined || w === null)
424
+ return {};
425
+ const v = objekt(w);
426
+ const vOrt = { name: ort.name, pfad: `${ort.pfad}.defaults` };
427
+ if (!v)
428
+ throw antwortfehler(ort.name, `Antwort ist unbrauchbar (data.${vOrt.pfad} ist kein Objekt)`);
429
+ const raus = {};
430
+ if (v.unitPriceCents !== undefined && v.unitPriceCents !== null)
431
+ raus.unitPriceCents = ganzzahl(vOrt, 'unitPriceCents', v.unitPriceCents);
432
+ if (v.vatRate !== undefined && v.vatRate !== null) {
433
+ if (typeof v.vatRate !== 'number' || !Number.isFinite(v.vatRate))
434
+ throw antwortfehler(ort.name, `Antwort enthaelt keinen USt-Satz (data.${vOrt.pfad}.vatRate)`);
435
+ raus.vatRate = v.vatRate;
436
+ }
437
+ for (const feld of ['unit', 'groupId']) {
438
+ const t = v[feld];
439
+ if (t === undefined || t === null)
440
+ continue;
441
+ if (typeof t !== 'string')
442
+ throw antwortfehler(ort.name, `Antwort ist unbrauchbar (data.${vOrt.pfad}.${feld} ist kein Text)`);
443
+ raus[feld] = t;
444
+ }
445
+ if (v.stockTracked !== undefined && v.stockTracked !== null) {
446
+ if (typeof v.stockTracked !== 'boolean')
447
+ throw antwortfehler(ort.name, `Antwort ist unbrauchbar (data.${vOrt.pfad}.stockTracked ist kein Wahrheitswert)`);
448
+ raus.stockTracked = v.stockTracked;
449
+ }
450
+ return raus;
451
+ }
452
+ function mitglied(ort, w) {
453
+ const x = eintrag(ort, w);
454
+ return { articleId: kennung(ort, 'articleId', x.articleId), variantAttributes: textAbbildung(x.variantAttributes) ?? {} };
455
+ }
456
+ /**
457
+ * Eine Variantengruppe. `attributes` und `variants` sind zugesagte Listen:
458
+ * fehlen sie, ist die Antwort kaputt (eine leere Liste hiesse „keine Merkmale“
459
+ * bzw. „keine Varianten“).
460
+ */
461
+ function variantengruppe(ort, w) {
462
+ const g = eintrag(ort, w);
463
+ for (const feld of ['attributes', 'variants']) {
464
+ if (!Array.isArray(g[feld]))
465
+ throw antwortfehler(ort.name, `Antwort ist unbrauchbar (data.${ort.pfad}.${feld} ist keine Liste)`);
466
+ }
467
+ const unter = (feld, i) => ({ name: ort.name, pfad: `${ort.pfad}.${feld}[${i}]` });
468
+ return {
469
+ id: kennung(ort, 'id', g.id),
470
+ name: text(g.name),
471
+ attributes: g.attributes.map((m, i) => merkmal(unter('attributes', i), m)),
472
+ defaults: vorgaben(ort, g.defaults),
473
+ active: g.active !== false,
474
+ variants: g.variants.map((x, i) => mitglied(unter('variants', i), x)),
475
+ createdAt: text(g.createdAt),
476
+ updatedAt: text(g.updatedAt),
477
+ };
478
+ }
404
479
  // ---- Listen ------------------------------------------------------------------
405
480
  /** Eine zugesagte Liste `data.<feld>`, Eintrag fuer Eintrag gelesen. */
406
481
  function liste(name, daten, feld, lesen) {