@kreiseck/kasseneck-api 1.7.1 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +106 -0
- package/README.md +170 -1
- package/dist/cjs/client/aufrufe.d.ts +9 -7
- package/dist/cjs/client/aufrufe.js +57 -2
- package/dist/cjs/client/errors.js +2 -0
- package/dist/cjs/client/index.d.ts +1 -1
- package/dist/cjs/client/index.js +2 -1
- package/dist/cjs/client/transport.d.ts +27 -3
- package/dist/cjs/client/transport.js +29 -3
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js +3 -2
- package/dist/cjs/inventory/api.d.ts +21 -2
- package/dist/cjs/inventory/api.js +22 -3
- package/dist/cjs/inventory/fehler.d.ts +6 -0
- package/dist/cjs/inventory/fehler.js +12 -0
- package/dist/cjs/inventory/index.d.ts +6 -4
- package/dist/cjs/inventory/index.js +33 -3
- package/dist/cjs/inventory/inventur.d.ts +104 -0
- package/dist/cjs/inventory/inventur.js +245 -0
- package/dist/cjs/inventory/lesen.d.ts +20 -1
- package/dist/cjs/inventory/lesen.js +307 -0
- package/dist/cjs/inventory/typen.d.ts +410 -1
- package/dist/cjs/inventory/vertrag.d.ts +94 -8
- package/dist/cjs/inventory/vertrag.js +117 -5
- package/dist/cjs/invoice/vertrag.d.ts +1 -1
- package/dist/cjs/invoice/vertrag.js +2 -0
- package/dist/cjs/models/cancellation.d.ts +1 -1
- package/dist/cjs/models/cancellation.js +2 -0
- package/dist/cjs/models/payment-errors.d.ts +1 -1
- package/dist/cjs/models/payment-errors.js +2 -0
- package/dist/cjs/models/receipt-email.d.ts +1 -1
- package/dist/cjs/models/receipt-email.js +2 -0
- package/dist/cjs/models/receipt-errors.d.ts +1 -1
- package/dist/cjs/models/receipt-errors.js +2 -0
- package/dist/cjs/pos/errors.d.ts +4 -3
- package/dist/cjs/pos/errors.js +23 -2
- package/dist/cjs/pos/index.d.ts +4 -1
- package/dist/cjs/pos/index.js +9 -2
- package/dist/cjs/pos/inventur.d.ts +104 -0
- package/dist/cjs/pos/inventur.js +117 -0
- package/dist/cjs/pos/texte.d.ts +82 -0
- package/dist/cjs/pos/texte.js +35 -0
- package/dist/cjs/register/errors.d.ts +1 -1
- package/dist/cjs/register/errors.js +2 -0
- package/dist/cjs/stored/vokabular.d.ts +1 -1
- package/dist/cjs/stored/vokabular.js +1 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/client/aufrufe.d.ts +9 -7
- package/dist/esm/client/aufrufe.js +57 -2
- package/dist/esm/client/errors.js +2 -0
- package/dist/esm/client/index.d.ts +1 -1
- package/dist/esm/client/index.js +1 -1
- package/dist/esm/client/transport.d.ts +27 -3
- package/dist/esm/client/transport.js +28 -3
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/inventory/api.d.ts +21 -2
- package/dist/esm/inventory/api.js +23 -4
- package/dist/esm/inventory/fehler.d.ts +6 -0
- package/dist/esm/inventory/fehler.js +11 -0
- package/dist/esm/inventory/index.d.ts +6 -4
- package/dist/esm/inventory/index.js +5 -3
- package/dist/esm/inventory/inventur.d.ts +104 -0
- package/dist/esm/inventory/inventur.js +226 -0
- package/dist/esm/inventory/lesen.d.ts +20 -1
- package/dist/esm/inventory/lesen.js +301 -0
- package/dist/esm/inventory/typen.d.ts +410 -1
- package/dist/esm/inventory/vertrag.d.ts +94 -8
- package/dist/esm/inventory/vertrag.js +116 -4
- package/dist/esm/invoice/vertrag.d.ts +1 -1
- package/dist/esm/invoice/vertrag.js +2 -0
- package/dist/esm/models/cancellation.d.ts +1 -1
- package/dist/esm/models/cancellation.js +2 -0
- package/dist/esm/models/payment-errors.d.ts +1 -1
- package/dist/esm/models/payment-errors.js +2 -0
- package/dist/esm/models/receipt-email.d.ts +1 -1
- package/dist/esm/models/receipt-email.js +2 -0
- package/dist/esm/models/receipt-errors.d.ts +1 -1
- package/dist/esm/models/receipt-errors.js +2 -0
- package/dist/esm/pos/errors.d.ts +4 -3
- package/dist/esm/pos/errors.js +23 -2
- package/dist/esm/pos/index.d.ts +4 -1
- package/dist/esm/pos/index.js +2 -1
- package/dist/esm/pos/inventur.d.ts +104 -0
- package/dist/esm/pos/inventur.js +109 -0
- package/dist/esm/pos/texte.d.ts +82 -0
- package/dist/esm/pos/texte.js +35 -0
- package/dist/esm/register/errors.d.ts +1 -1
- package/dist/esm/register/errors.js +2 -0
- package/dist/esm/stored/vokabular.d.ts +1 -1
- package/dist/esm/stored/vokabular.js +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/fixtures/hobex-hps-codes.json +1 -1
- package/fixtures/invoice-api.schema.json +1 -1
- package/fixtures/invoice-texts.json +1 -1
- package/fixtures/pos-texts.json +94 -1
- package/fixtures/stocktake-quantity-cases.json +55 -0
- package/fixtures/surface.json +151 -8
- package/fixtures/v3/antworten/belege.json +1 -1
- package/fixtures/v3/antworten/belegmail.json +1 -1
- package/fixtures/v3/antworten/kasse-belege.json +1 -1
- package/fixtures/v3/antworten/kasse.json +2958 -3
- package/fixtures/v3/antworten/lager.json +1727 -3
- package/fixtures/v3/antworten/rechnungen.json +1 -1
- package/fixtures/v3/antworten/storno.json +1 -1
- package/fixtures/v3/stored/belege.json +1 -1
- package/fixtures/v3/stored/kasse.json +414 -3
- package/fixtures/v3/stored/rechnungen.json +1 -1
- package/fixtures/v3/v3-vokabular.json +475 -8
- package/fixtures/v3/zahlbetrag-faelle.json +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,112 @@ 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.8.0
|
|
8
|
+
|
|
9
|
+
Stocktake (Lager-Kern stage 3): `./inventory` gains the twelve stocktake
|
|
10
|
+
endpoints of the inventory API, `./pos` the five calls for counting at the
|
|
11
|
+
register. Reason: a business that counts its stock had only the old
|
|
12
|
+
"set the stock to this number" adjustment, which knows no expected quantity
|
|
13
|
+
at the time of the count, no several counts per article, no blind count and
|
|
14
|
+
no record. The backend now runs a stocktake as its own process (count, review,
|
|
15
|
+
recount, close in parts, PDF record with the state of the ledger seal), and
|
|
16
|
+
shops, the web register and the app need it through the package.
|
|
17
|
+
|
|
18
|
+
Additive at runtime; existing calls send the same bytes as in 1.7.1. As in
|
|
19
|
+
1.6.0, the unions `InventoryEndpoint`, `InventoryErrorCode`,
|
|
20
|
+
`InventoryWarningCode`, `PosErrorCode`, `ApiCall`, `PublicCall`, `PosCall`,
|
|
21
|
+
`MessageKey`, `LabelKey` and the error code unions derived from the
|
|
22
|
+
authentication codes (see Contract below) gain members, so an exhaustive `switch` with a
|
|
23
|
+
`never` check needs the new cases.
|
|
24
|
+
|
|
25
|
+
- **Inventory API**: `createStocktake`, `listStocktakes`/`iterateStocktakes`
|
|
26
|
+
(without `updatedSince` the most recently changed first; with `updatedSince`
|
|
27
|
+
sorted by `updatedAt` ascending and inclusive, like `listArticles`),
|
|
28
|
+
`getStocktake` (with `progress.counted`), `listStocktakeItems`/
|
|
29
|
+
`iterateStocktakeItems` (`openOnly`), `recordStocktakeCount`,
|
|
30
|
+
`voidStocktakeCount`, `listStocktakeCounts`/`iterateStocktakeCounts`,
|
|
31
|
+
`reviewStocktake`, `recountStocktake`, `closeStocktake` (answers
|
|
32
|
+
`{ stocktake, warnings }`), `cancelStocktake` and `getStocktakePdf`. Models
|
|
33
|
+
`Stocktake`, `StocktakeItem`, `StocktakeCount` and their parts; the result
|
|
34
|
+
fields of a closed stocktake (`totals`, `warnings`, `seal`, `checksum`,
|
|
35
|
+
`inventoryAsOf`, `pdf`) and the expected quantity of an item
|
|
36
|
+
(`expectedQuantity`, `differenceQuantity`, `needsCheck` …) are present only
|
|
37
|
+
when the server sends them: never before `review` (blind), values only with
|
|
38
|
+
`costs`. A missing count, quantity, round or list of counters, and an actor
|
|
39
|
+
that is not an object, are response errors, never `0` or "nobody".
|
|
40
|
+
`StocktakeItem.serialNumbers` is present only when the server sends it (the
|
|
41
|
+
answer of counting and voiding omits it), never invented as `[]`.
|
|
42
|
+
- **The record**: `getStocktakePdf` returns `{ kind: 'pdf', pdf }` (the bytes,
|
|
43
|
+
up to 9 MiB) or `{ kind: 'download', download: { url, expiresAt, sizeBytes,
|
|
44
|
+
sha256, fileName, contentType } }` (a signed link for 15 minutes above
|
|
45
|
+
that). It reads the answer as bytes like the report downloads and accepts
|
|
46
|
+
either a PDF or a success envelope. The transport for it is public:
|
|
47
|
+
`createPdfOrDataTransport(options)` at the package root (types
|
|
48
|
+
`KasseneckPdfOrDataTransport`, `PdfOrData`), so the free function
|
|
49
|
+
`getStocktakePdf(transport, stocktakeId)` works outside the client too, as
|
|
50
|
+
`getInvoicePdf` does with `createBinaryTransport`.
|
|
51
|
+
- **Counting at the register** (`./pos`, register path only):
|
|
52
|
+
`listMyStocktakes`, `listMyStocktakeItems`, `listMyStocktakeCounts`,
|
|
53
|
+
`recordMyStocktakeCount`, `voidMyStocktakeCount`, with the same models.
|
|
54
|
+
`parseQuantityMilli(text, unit, rule?)` turns the typed quantity into
|
|
55
|
+
thousandths without floating point (comma or point, at most three decimals;
|
|
56
|
+
a point with exactly three digits after a non-zero whole part, `'1.000'`,
|
|
57
|
+
is ambiguous and `null` for every unit; pieces, by the stored `rule` of the
|
|
58
|
+
article or else by the unit, whole numbers without separator only); its
|
|
59
|
+
cases are shared with the Dart twin in the new
|
|
60
|
+
`fixtures/stocktake-quantity-cases.json`.
|
|
61
|
+
Messages and labels `stocktake.*` for the counting screen in the catalogue
|
|
62
|
+
(`fixtures/pos-texts.json`).
|
|
63
|
+
- **Idempotency and outcome**: every write takes `idempotencyKey` (refused
|
|
64
|
+
before sending without a valid one). `createStocktake`, `recordStocktakeCount`,
|
|
65
|
+
`voidStocktakeCount`, `reviewStocktake`, `recountStocktake`, `closeStocktake`,
|
|
66
|
+
`cancelStocktake`, `recordMyStocktakeCount` and `voidMyStocktakeCount` are in
|
|
67
|
+
`UNKNOWN_OUTCOME_CALLS`: after `outcome: 'unknown'` resend with the **same**
|
|
68
|
+
key, a count is then counted once. The eight reads are in the list without
|
|
69
|
+
effect.
|
|
70
|
+
- **Checked before sending**, nothing else: the key, `stocktakeId`,
|
|
71
|
+
`articleId`, `countId`, `locationId`, `scope` as an object, an integer
|
|
72
|
+
`quantity`, a non-empty `reason`, a non-empty `items` list with `articleId`
|
|
73
|
+
for a recount, `serialNumbers` as a list, `uncountedAsZero` as a boolean.
|
|
74
|
+
The limits (5000 items, 200 per recount, 200 counts per item and round) are
|
|
75
|
+
left to the server and exported as `STOCKTAKE_ITEMS_MAX`,
|
|
76
|
+
`STOCKTAKE_RECOUNT_ITEMS_MAX`, `STOCKTAKE_COUNTS_PER_ITEM_MAX`.
|
|
77
|
+
- **Catalogues**: `STOCKTAKE_STATUSES`, `STOCKTAKE_TYPES`,
|
|
78
|
+
`STOCKTAKE_SCOPE_TYPES`, `STOCKTAKE_CHECK_REASONS`,
|
|
79
|
+
`STOCKTAKE_NOT_BOOKED_REASONS`, `STOCKTAKE_SOURCES`, `STOCKTAKE_ACTOR_TYPES`,
|
|
80
|
+
`STOCKTAKE_INVENTORY_AS_OF`, each the contract catalogue in its order.
|
|
81
|
+
- **Errors**: `INVENTORY_ERROR_CODES` appends `stocktake_not_found`,
|
|
82
|
+
`stocktake_not_open`, `stocktake_closed`, `stocktake_not_in_review`,
|
|
83
|
+
`stocktake_closing`, `stocktake_location_busy` (with `data.stocktakeId`, read
|
|
84
|
+
by the new `inventoryBusyStocktakeId(error)`), `stocktake_review_running`,
|
|
85
|
+
`stocktake_recount_open`, `article_not_in_scope`, `article_not_tracked`,
|
|
86
|
+
`count_not_found`, `count_already_voided`, `serial_already_counted`,
|
|
87
|
+
`too_many_counts` and `stocktake_not_closed`; `INVENTORY_WARNING_CODES`
|
|
88
|
+
appends `defect_capped`, `uncounted_items`, `not_booked` and
|
|
89
|
+
`recount_uncounted`. `POS_ERROR_CODES` gains the codes of the five register
|
|
90
|
+
calls.
|
|
91
|
+
- **Contract**: `fixtures/v3/` pulled from the backend at the state of the
|
|
92
|
+
stocktake (keck #633, #634); the vocabulary of `./stored` regenerated
|
|
93
|
+
(fingerprint only). The contract also lists `app_check_missing` and
|
|
94
|
+
`app_check_invalid` among the authentication codes (App Check of the admin
|
|
95
|
+
app, refused before any handler); every list derived from them gains both:
|
|
96
|
+
`RECEIPT_ERROR_CODES`, `CANCELLATION_ERROR_CODES`,
|
|
97
|
+
`RECEIPT_EMAIL_ERROR_CODES`, `PAYMENT_ERROR_CODES`, `REGISTER_ERROR_CODES`,
|
|
98
|
+
`POS_ERROR_CODES`, `INVOICE_REQUEST_ERROR_CODES`,
|
|
99
|
+
`INVENTORY_REQUEST_ERROR_CODES` (and their unions) and
|
|
100
|
+
`PAYMENT_CALL_REJECTED_CODES`, so they stay `rejected` on the money calls
|
|
101
|
+
(the Dart twin's `paymentCallRejectedCodes` follows). No call of this
|
|
102
|
+
package can receive them: the backend sends them only on three endpoints
|
|
103
|
+
of the admin app (App Check), none of which is public `/v3`, on the register
|
|
104
|
+
path or wrapped here; the lists follow the contract so that their guards
|
|
105
|
+
stay derived from it.
|
|
106
|
+
- **Counts**: `PUBLIC_CALLS` 92 → 104, `POS_CALLS` 28 → 33 (27 register-only
|
|
107
|
+
names).
|
|
108
|
+
- **Twin check**: the source fingerprint of `functions-kasse/kasse-settings-core.js`
|
|
109
|
+
in `test/fixtures/stored-zwillinge.json` follows the backend, which only added
|
|
110
|
+
functions after `mische` (card provider and auto-logout per device); the
|
|
111
|
+
behaviour comparison of `./stored` against the backend is unchanged and green.
|
|
112
|
+
|
|
7
113
|
## 1.7.1
|
|
8
114
|
|
|
9
115
|
`ReceiptSheetLines` pins `letter-spacing` and `word-spacing` to 0. Reason:
|
package/README.md
CHANGED
|
@@ -893,6 +893,48 @@ errors such as `location_not_found` and `location_inactive` are in
|
|
|
893
893
|
`RETURN_DISPOSITION_LABELS` gives the label of each return choice
|
|
894
894
|
(`labelText(RETURN_DISPOSITION_LABELS.restock)` is "Zurück ins Lager").
|
|
895
895
|
|
|
896
|
+
**Counting a stocktake at the register.** Five calls on the register path,
|
|
897
|
+
permissions `stocktakeCount` (count, void own counts) and `stocktakeClose`
|
|
898
|
+
(also void other people's counts; the expected quantity from `review` on).
|
|
899
|
+
Creating, reviewing and closing happen in the panel or through the inventory
|
|
900
|
+
API, not at the register.
|
|
901
|
+
|
|
902
|
+
```ts
|
|
903
|
+
import { listMyStocktakes, listMyStocktakeItems, recordMyStocktakeCount, voidMyStocktakeCount, parseQuantityMilli, messageText, labelText } from '@kreiseck/kasseneck-api/pos';
|
|
904
|
+
|
|
905
|
+
const [open] = await listMyStocktakes(transport, { locationId: 'haupt' });
|
|
906
|
+
if (!open) showHint(messageText('stocktake.none_open'));
|
|
907
|
+
const { items } = await listMyStocktakeItems(transport, { stocktakeId: open!.id, openOnly: true });
|
|
908
|
+
const quantity = parseQuantityMilli('0,25', 'kg', article.quantityRule); // 250; null for invalid input
|
|
909
|
+
if (quantity === null) showHint(messageText('stocktake.quantity_invalid'));
|
|
910
|
+
const key = crypto.randomUUID(); // keep it for "Erneut senden"
|
|
911
|
+
const { count, item } = await recordMyStocktakeCount(transport, {
|
|
912
|
+
idempotencyKey: key, stocktakeId: open!.id, articleId: items[0]!.articleId, quantity: quantity!,
|
|
913
|
+
});
|
|
914
|
+
await voidMyStocktakeCount(transport, { idempotencyKey: `${key}-void`, stocktakeId: open!.id, countId: count.id, reason: 'Doppelt gezählt' });
|
|
915
|
+
```
|
|
916
|
+
|
|
917
|
+
`parseQuantityMilli(text, unit, rule?)` turns the typed text into thousandths
|
|
918
|
+
without floating point: comma or point as decimal separator, at most three
|
|
919
|
+
decimals (trailing zeros do not count). A point followed by exactly three
|
|
920
|
+
digits after a non-zero whole part (`'1.000'`, `'12.500'`) is `null` for every
|
|
921
|
+
unit: in Austrian notation it is a thousands separator, on a keypad a decimal
|
|
922
|
+
point, and a factor of 1000 would be booked as a difference; with a comma it
|
|
923
|
+
is unambiguous (`'1,000'` is 1000, i.e. one unit). Pieces take whole numbers
|
|
924
|
+
without any separator only. Whether an article is counted in pieces comes
|
|
925
|
+
from `rule`, the stored quantity rule of the article (`PosArticle.quantityRule`,
|
|
926
|
+
`'piece'` or `'decimal'`), without it from the default of the unit
|
|
927
|
+
(`quantityRuleForUnit`: `Stk`, `g`, `ml` …, also when the unit is missing);
|
|
928
|
+
pass `'piece'` for a serial-number article. Anything else is `null`. Its cases are shared with the Dart twin in
|
|
929
|
+
`fixtures/stocktake-quantity-cases.json`. Counting works online only; after
|
|
930
|
+
`outcome: 'unknown'` resend the **same** count with the **same** key
|
|
931
|
+
(`labelText('stocktake.resend')`), it is counted exactly once. The texts of the
|
|
932
|
+
counting screen are in the catalogue as `stocktake.*`
|
|
933
|
+
(`messageText('stocktake.counted', { name, quantity })`,
|
|
934
|
+
`labelText('stocktake.progress', { counted, total })`); the error codes
|
|
935
|
+
(`stocktake_not_open`, `article_not_in_scope`, `count_already_voided` …) are in
|
|
936
|
+
`POS_ERROR_CODES`.
|
|
937
|
+
|
|
896
938
|
`stockViewOf(perms)` (also exported from the package root) tells whether a
|
|
897
939
|
register user may see locations and quantities: a missing `stockView` counts
|
|
898
940
|
as granted, only an explicit `false` blocks it, and the other stock
|
|
@@ -1483,7 +1525,8 @@ ones made at the register in the shop. Since 1.5.0 also the write side:
|
|
|
1483
1525
|
create and update articles, book goods receipts, transfers, losses and
|
|
1484
1526
|
condition changes, and reserve stock at checkout (see
|
|
1485
1527
|
[Shop: reserve and invoice](#shop-reserve-and-invoice)); since 1.6.0 variant
|
|
1486
|
-
groups (sizes, colours, see [Variants](#variants))
|
|
1528
|
+
groups (sizes, colours, see [Variants](#variants)); since 1.8.0 stocktakes
|
|
1529
|
+
(see [Stocktake](#stocktake)). Uses the `api_key` of
|
|
1487
1530
|
the account and belongs on a **server**. Reading needs the module `lager`,
|
|
1488
1531
|
writing additionally the account switch *Lager-API schreiben*, which Kasseneck
|
|
1489
1532
|
turns on (always on in the test environment, `kr_test_…`; otherwise
|
|
@@ -1863,6 +1906,131 @@ function onDelivery(rawBody: Buffer) {
|
|
|
1863
1906
|
`listArticles({ variantGroupId, updatedSince })` are sorted by `updatedAt`
|
|
1864
1907
|
ascending and include the boundary.
|
|
1865
1908
|
|
|
1909
|
+
### Stocktake
|
|
1910
|
+
|
|
1911
|
+
A stocktake counts the stock of one location: create it (scope, key date or
|
|
1912
|
+
perpetual, blind by default), count (several counts of the same article are
|
|
1913
|
+
added up, a wrong one is voided with a reason), review (only now the expected
|
|
1914
|
+
quantity and the difference appear), recount single items, close (books one
|
|
1915
|
+
movement `stocktake` per item and stores the stocktake record as PDF) or
|
|
1916
|
+
cancel. The same flow runs in the panel and, for counting, at the register
|
|
1917
|
+
(`./pos`, below). All writes, counting included, take an `idempotencyKey`
|
|
1918
|
+
and the account switch *Lager-API schreiben*; values (`…Cents`, `…Micros`)
|
|
1919
|
+
and the PDF with values need `costs`.
|
|
1920
|
+
|
|
1921
|
+
Example: Bäckerei Kornblum has 40 Kornspitz at the location `haupt`. At
|
|
1922
|
+
10:00:00 the register sells 3, the stock movement is booked a few seconds
|
|
1923
|
+
late at 10:00:03. At 10:00:02 Livia Lindmayr counts 37 on the shelf.
|
|
1924
|
+
|
|
1925
|
+
```ts
|
|
1926
|
+
import { createInventoryClient, inventoryBusyStocktakeId, isInventoryError } from '@kreiseck/kasseneck-api/inventory';
|
|
1927
|
+
import { parseQuantityMilli } from '@kreiseck/kasseneck-api/pos';
|
|
1928
|
+
|
|
1929
|
+
const inventory = createInventoryClient({ apiKey: process.env.KASSENECK_API_KEY! });
|
|
1930
|
+
|
|
1931
|
+
// 1. One open stocktake per location; reuse it if there is one.
|
|
1932
|
+
let stocktakeId: string;
|
|
1933
|
+
try {
|
|
1934
|
+
const created = await inventory.createStocktake({
|
|
1935
|
+
idempotencyKey: 'shop-stocktake-haupt-2026-12',
|
|
1936
|
+
locationId: 'haupt',
|
|
1937
|
+
scope: { type: 'groups', groupIds: ['gebaeck'] },
|
|
1938
|
+
type: 'key_date',
|
|
1939
|
+
keyDate: '2026-12-31', // blind: true is the default
|
|
1940
|
+
});
|
|
1941
|
+
stocktakeId = created.id; // status: 'counting'
|
|
1942
|
+
} catch (error) {
|
|
1943
|
+
const busy = inventoryBusyStocktakeId(error);
|
|
1944
|
+
if (!busy) throw error;
|
|
1945
|
+
stocktakeId = busy;
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
// 2. Count. Quantities in thousandths: "37" pieces -> 37000, "0,25" kg -> 250.
|
|
1949
|
+
const kornspitz = await inventory.lookupArticleByCode('9001234567896');
|
|
1950
|
+
const { item } = await inventory.recordStocktakeCount({
|
|
1951
|
+
idempotencyKey: 'shelf-a-kornspitz-1', // after outcome 'unknown': resend with the SAME key
|
|
1952
|
+
stocktakeId,
|
|
1953
|
+
articleId: kornspitz.id,
|
|
1954
|
+
quantity: parseQuantityMilli('37', kornspitz.unit)!,
|
|
1955
|
+
});
|
|
1956
|
+
// item.quantity: 37000 (sum of the round), no expectedQuantity while counting
|
|
1957
|
+
|
|
1958
|
+
// 3. Review: computed in the background, poll until complete.
|
|
1959
|
+
await inventory.reviewStocktake({ idempotencyKey: 'review-1', stocktakeId });
|
|
1960
|
+
let stocktake = await inventory.getStocktake(stocktakeId);
|
|
1961
|
+
while (!stocktake.review?.complete) {
|
|
1962
|
+
await new Promise((r) => setTimeout(r, 2000));
|
|
1963
|
+
stocktake = await inventory.getStocktake(stocktakeId);
|
|
1964
|
+
}
|
|
1965
|
+
for await (const it of inventory.iterateStocktakeItems({ stocktakeId })) {
|
|
1966
|
+
// Kornspitz: expectedQuantity 37000, differenceQuantity 0 (the sale at
|
|
1967
|
+
// 10:00:00 was booked after the count, but it happened before it)
|
|
1968
|
+
if (it.needsCheck) console.log(it.articleId, it.checkReasons);
|
|
1969
|
+
}
|
|
1970
|
+
|
|
1971
|
+
// 4. Close (books in parts in the background), then fetch the record.
|
|
1972
|
+
const { warnings } = await inventory.closeStocktake({ idempotencyKey: 'close-1', stocktakeId });
|
|
1973
|
+
// … poll getStocktake until status === 'closed' …
|
|
1974
|
+
const pdf = await inventory.getStocktakePdf(stocktakeId);
|
|
1975
|
+
if (pdf.kind === 'pdf') await save('stocktake.pdf', pdf.pdf);
|
|
1976
|
+
else await download(pdf.download.url, pdf.download.sha256); // over 9 MiB: signed link, 15 minutes
|
|
1977
|
+
```
|
|
1978
|
+
|
|
1979
|
+
- **Reference time.** The expected quantity of an item is the stock at the
|
|
1980
|
+
time of its last count (server time; the device clock never counts), taken
|
|
1981
|
+
from the stock ledger, including sales that happened before the count but
|
|
1982
|
+
were booked after it (within 3 days). In the example the expected quantity
|
|
1983
|
+
is 37, the difference 0, and closing changes nothing. Had the 3 Kornspitz
|
|
1984
|
+
been sold at 10:00:05, after the count, the expected quantity would be 40
|
|
1985
|
+
and the difference −3: closing books −3 on today's stock (37 after the
|
|
1986
|
+
sale), which leaves 34. Each piece is deducted exactly once.
|
|
1987
|
+
- **Blind.** Before `review` no response carries an expected quantity, a
|
|
1988
|
+
difference or `needsCheck`; the fields are absent, not `null`. With
|
|
1989
|
+
`blind: false` the items carry `bookStockNow` while counting: today's book
|
|
1990
|
+
stock, never the expected quantity at the reference time.
|
|
1991
|
+
- **Counting.** `quantity` in thousandths, `0` means counted empty. Pieces
|
|
1992
|
+
and serial-number articles take whole pieces only, serial-number articles
|
|
1993
|
+
exactly one serial number per piece (`serial_required`,
|
|
1994
|
+
`serial_already_counted`). Scope `all` adds a tracked article that was not
|
|
1995
|
+
listed (`addedLater`); scopes `groups` and `articles` answer
|
|
1996
|
+
`article_not_in_scope`. While counting or recounting, `voidStocktakeCount`
|
|
1997
|
+
with a reason takes a count back; the item is summed up again.
|
|
1998
|
+
- **Recount.** In `review`, `recountStocktake({ items, reason })` starts a new
|
|
1999
|
+
round for the named items (old counts stay, but no longer count); count
|
|
2000
|
+
them, then call `reviewStocktake` again. `closeStocktake` refuses with
|
|
2001
|
+
`stocktake_recount_open` while recounts are open.
|
|
2002
|
+
- **Closing.** Only from `review` (`stocktake_not_in_review`) and only once the
|
|
2003
|
+
review has finished computing: while `review.complete` is `false`,
|
|
2004
|
+
`closeStocktake` and `recountStocktake` answer `stocktake_review_running`
|
|
2005
|
+
(poll `getStocktake` and try again). Uncounted items
|
|
2006
|
+
are not booked and appear as "not counted" in the record; with
|
|
2007
|
+
`uncountedAsZero: true` they are booked as 0. The answer usually has
|
|
2008
|
+
`status: 'closing'` with `closing.parts` and `closing.bookedParts`; calling
|
|
2009
|
+
`closeStocktake` again while it is closing resumes it. After `closed`, the
|
|
2010
|
+
head carries `totals`, `warnings` (`uncounted_items`, `not_booked`,
|
|
2011
|
+
`defect_capped`), `seal` (the state of the stock ledger seal), `checksum`
|
|
2012
|
+
and `pdf`; `closeStocktake` itself may warn `recount_uncounted`. Each
|
|
2013
|
+
booking reaches webhooks as `stock.changed` with `cause: 'stocktake'`;
|
|
2014
|
+
there is no `stocktake.*` event.
|
|
2015
|
+
- **Lists.** `listStocktakes()` without `updatedSince` returns the most
|
|
2016
|
+
recently changed first (an open stocktake is not necessarily on top; filter
|
|
2017
|
+
with `status`). With `updatedSince` it is sorted by `updatedAt` ascending
|
|
2018
|
+
and includes the boundary, like `listArticles`: remember the largest
|
|
2019
|
+
`updatedAt` and ask again. `listStocktakeItems({ stocktakeId, openOnly })`
|
|
2020
|
+
and `listStocktakeCounts({ stocktakeId, articleId })` page with `cursor`;
|
|
2021
|
+
the `iterate…` variants follow `nextCursor` in the same order.
|
|
2022
|
+
- **The record.** `getStocktakePdf` exists only after closing
|
|
2023
|
+
(`stocktake_not_closed`, also for a cancelled stocktake). With `costs` it is
|
|
2024
|
+
the version with values, otherwise the one with quantities only. Up to
|
|
2025
|
+
9 MiB the file comes in the answer (`kind: 'pdf'`), above that as a signed
|
|
2026
|
+
link for 15 minutes (`kind: 'download'`, with `sizeBytes` and `sha256`; check
|
|
2027
|
+
the downloaded file against `sha256`).
|
|
2028
|
+
- **Limits.** At most `STOCKTAKE_ITEMS_MAX` (5000) items per stocktake
|
|
2029
|
+
(`too_many_positions`; count larger stocks in several stocktakes one after
|
|
2030
|
+
another), `STOCKTAKE_RECOUNT_ITEMS_MAX` (200) items per recount and
|
|
2031
|
+
`STOCKTAKE_COUNTS_PER_ITEM_MAX` (200) counts per item and round
|
|
2032
|
+
(`too_many_counts`). The server checks them, not the client.
|
|
2033
|
+
|
|
1866
2034
|
## Migrating from 0.x
|
|
1867
2035
|
|
|
1868
2036
|
1.0 is one breaking step: the wire, the exported names and the contract files
|
|
@@ -1946,6 +2114,7 @@ in machine form what both sides agreed on, among them:
|
|
|
1946
2114
|
| `pos-message-cases.json` | error cases and the message each one must show in both registers | by hand |
|
|
1947
2115
|
| `receipt-due-generated.json` | 1206 amounts due computed by the backend's own code, the reference for `receiptDueCents` | `node scripts/v3-zahlbetrag-generieren.mjs` |
|
|
1948
2116
|
| `receipt-due-errors.json` | input the amount due cannot be computed from, with the `reason` of the `ReceiptDueError` each one throws | by hand |
|
|
2117
|
+
| `stocktake-quantity-cases.json` | typed quantities and the thousandths `parseQuantityMilli` makes of them (or `null`), per unit | by hand |
|
|
1949
2118
|
| `v3/` | the backend's `/v3` contract (vocabulary, response cases, stored cases, amounts due), copied byte for byte | `node scripts/v3-vertrag-holen.mjs` |
|
|
1950
2119
|
| `renames-1.0.json` | everything in these files that changed from 0.x to 1.0: paths (`files`), text catalogue keys (`texts`), placeholders, structural keys (`structure`), machine values (`values`), shape changes (`shapes`); rendered texts are unchanged | `npm run fixtures:umbenennung` |
|
|
1951
2120
|
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
* weiterhin jeden `string`: wer einen Aufruf braucht, den dieses Paket nicht
|
|
13
13
|
* umhuellt, muss ihn weiterhin absetzen koennen.
|
|
14
14
|
*/
|
|
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", "createVariantGroup", "updateVariantGroup", "getVariantGroup", "listVariantGroups", "addVariant"];
|
|
15
|
+
import type { PdfOrData, 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", "createVariantGroup", "updateVariantGroup", "getVariantGroup", "listVariantGroups", "addVariant", "createStocktake", "listStocktakes", "getStocktake", "listStocktakeItems", "recordStocktakeCount", "voidStocktakeCount", "listStocktakeCounts", "reviewStocktake", "recountStocktake", "closeStocktake", "cancelStocktake", "getStocktakePdf", "listMyStocktakes", "listMyStocktakeItems", "listMyStocktakeCounts", "recordMyStocktakeCount", "voidMyStocktakeCount"];
|
|
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,14 +21,14 @@ 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", "createVariantGroup", "updateVariantGroup", "getVariantGroup", "listVariantGroups", "addVariant"];
|
|
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", "createStocktake", "listStocktakes", "getStocktake", "listStocktakeItems", "recordStocktakeCount", "voidStocktakeCount", "listStocktakeCounts", "reviewStocktake", "recountStocktake", "closeStocktake", "cancelStocktake", "getStocktakePdf"];
|
|
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
|
|
28
28
|
* `endpoints.register`. Sechs davon sind zugleich oeffentlich; die Kasse ruft
|
|
29
29
|
* sie trotzdem ueber diesen Weg (ein Dialekt je Client, Nachtrag §5.2).
|
|
30
30
|
*/
|
|
31
|
-
export declare const POS_CALLS: readonly ["pairRegisterDevice", "listRegisterUsersForDevice", "listRegisterSessionsForDevice", "registerUserLogin", "registerPinLogin", "renewRegisterSession", "endRegisterSession", "unpairRegisterDevice", "listMyCashregisters", "listMyReceipts", "getReceipt", "createReceipt", "generateFullReceiptId", "cancelReceipt", "sendReceiptEmail", "listMyArticleGroups", "listMyArticles", "getKasseSettings", "setMyKasseSettings", "setMyKasseLogo", "setMyRegisterDeviceSettings", "listMyPrinters", "createPrintJob", "getPrintJob", "listMyTipRecipients", "listMyStockLocations", "listMyStock", "setMyCashregisterStockLocation"];
|
|
31
|
+
export declare const POS_CALLS: readonly ["pairRegisterDevice", "listRegisterUsersForDevice", "listRegisterSessionsForDevice", "registerUserLogin", "registerPinLogin", "renewRegisterSession", "endRegisterSession", "unpairRegisterDevice", "listMyCashregisters", "listMyReceipts", "getReceipt", "createReceipt", "generateFullReceiptId", "cancelReceipt", "sendReceiptEmail", "listMyArticleGroups", "listMyArticles", "getKasseSettings", "setMyKasseSettings", "setMyKasseLogo", "setMyRegisterDeviceSettings", "listMyPrinters", "createPrintJob", "getPrintJob", "listMyTipRecipients", "listMyStockLocations", "listMyStock", "setMyCashregisterStockLocation", "listMyStocktakes", "listMyStocktakeItems", "listMyStocktakeCounts", "recordMyStocktakeCount", "voidMyStocktakeCount"];
|
|
32
32
|
export type PublicCall = typeof PUBLIC_CALLS[number];
|
|
33
33
|
export type PosCall = typeof POS_CALLS[number];
|
|
34
34
|
/**
|
|
@@ -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", "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"];
|
|
52
|
+
export declare const UNKNOWN_OUTCOME_CALLS: readonly ["activateCashregister", "addVariant", "cancelInvoice", "cancelReceipt", "cancelStocktake", "changeStockCondition", "closeStocktake", "createArticle", "createCreditNote", "createCustomer", "createCustomerCashregister", "createInvoiceItem", "createPartnerCustomer", "createPartnerWebhook", "createPrintJob", "createReceipt", "createReservation", "createStocktake", "createVariantGroup", "createWebhook", "deactivateArticle", "deletePartnerWebhook", "deleteWebhook", "extendReservation", "financeWebService", "hobexPayApi", "hobexRefundApi", "issueInvoice", "pairRegisterDevice", "receiveGoods", "recordInvoicePayment", "recordMyStocktakeCount", "recordStockLoss", "recordStocktakeCount", "recountStocktake", "releaseReservation", "reportCustomerContract", "requestCustomerSignature", "reverseStockMovement", "reviewStocktake", "revokeCustomerMandate", "rotatePartnerWebhookSecret", "rotateWebhookSecret", "sendPartnerCustomerFonLink", "sendPartnerWebhookTest", "sendReceiptEmail", "sendWebhookTest", "setCustomerMandate", "setMyCashregisterStockLocation", "setMyKasseLogo", "setMyKasseSettings", "setMyRegisterDeviceSettings", "stripeCaptureIntent", "transferStock", "unpairRegisterDevice", "updateArticle", "updateCustomer", "updateInvoiceItem", "updatePartnerWebhook", "updateVariantGroup", "updateWebhook", "voidMyStocktakeCount", "voidStocktakeCount", "withdrawInvoiceItem"];
|
|
53
53
|
/** Warum ein Aufruf keine Wirkung hat, die ein Zeitlimit offen lassen koennte. */
|
|
54
54
|
export type CallWithoutEffectReason = 'read' | 'repeatable';
|
|
55
55
|
/**
|
|
@@ -85,10 +85,10 @@ export declare const CALLS_WITHOUT_EFFECT: Readonly<Record<string, CallWithoutEf
|
|
|
85
85
|
* absetzt, sagt es mit `hasEffect: true`.
|
|
86
86
|
*/
|
|
87
87
|
export declare function isUnknownOutcomeCall(name: string): boolean;
|
|
88
|
-
/** Einer der
|
|
88
|
+
/** Einer der 33 Aufrufe des Kassenwegs. */
|
|
89
89
|
export declare function isPosCall(name: string): boolean;
|
|
90
90
|
/**
|
|
91
|
-
* Nur ueber den Kassenweg erreichbar (
|
|
91
|
+
* Nur ueber den Kassenweg erreichbar (27 Namen): unter `api.kasseneck.at/v3`
|
|
92
92
|
* gibt es sie nicht. Der Transport schickt sie darum ohne eigene Basis an
|
|
93
93
|
* [POS_BASE_URL] statt an die oeffentliche Basis.
|
|
94
94
|
*/
|
|
@@ -97,3 +97,5 @@ export declare function isPosOnlyCall(name: string): boolean;
|
|
|
97
97
|
export type InternerTransport = <T = unknown>(functionName: ApiCall, params?: Record<string, unknown>, extraBodyFields?: TransportBodyFields, secretParams?: readonly string[], options?: TransportCallOptions) => Promise<T>;
|
|
98
98
|
/** Wie [KasseneckBinaryTransport], nur mit bekanntem Aufrufnamen. */
|
|
99
99
|
export type InternerBinaerTransport = (functionName: ApiCall, params?: Record<string, unknown>) => Promise<Uint8Array>;
|
|
100
|
+
/** Wie `createPdfOrDataTransport` (transport.ts), nur mit bekanntem Aufrufnamen. */
|
|
101
|
+
export type InternerPdfOderDatenTransport = (functionName: ApiCall, params?: Record<string, unknown>) => Promise<PdfOrData>;
|
|
@@ -111,6 +111,25 @@ exports.ALL_CALLS = [
|
|
|
111
111
|
'getVariantGroup',
|
|
112
112
|
'listVariantGroups',
|
|
113
113
|
'addVariant',
|
|
114
|
+
// Lager-API Inventur (Lager-Kern Stufe 3, ./inventory)
|
|
115
|
+
'createStocktake',
|
|
116
|
+
'listStocktakes',
|
|
117
|
+
'getStocktake',
|
|
118
|
+
'listStocktakeItems',
|
|
119
|
+
'recordStocktakeCount',
|
|
120
|
+
'voidStocktakeCount',
|
|
121
|
+
'listStocktakeCounts',
|
|
122
|
+
'reviewStocktake',
|
|
123
|
+
'recountStocktake',
|
|
124
|
+
'closeStocktake',
|
|
125
|
+
'cancelStocktake',
|
|
126
|
+
'getStocktakePdf',
|
|
127
|
+
// Inventur zaehlen an der Kasse (Lager-Kern Stufe 3, ./pos)
|
|
128
|
+
'listMyStocktakes',
|
|
129
|
+
'listMyStocktakeItems',
|
|
130
|
+
'listMyStocktakeCounts',
|
|
131
|
+
'recordMyStocktakeCount',
|
|
132
|
+
'voidMyStocktakeCount',
|
|
114
133
|
];
|
|
115
134
|
/**
|
|
116
135
|
* Die oeffentlichen Endpunkte unter `/v3` (`https://api.kasseneck.at/v3/<name>`),
|
|
@@ -217,6 +236,19 @@ exports.PUBLIC_CALLS = [
|
|
|
217
236
|
'getVariantGroup',
|
|
218
237
|
'listVariantGroups',
|
|
219
238
|
'addVariant',
|
|
239
|
+
// Lager-API Inventur (Lager-Kern Stufe 3), umhuellt in `./inventory`.
|
|
240
|
+
'createStocktake',
|
|
241
|
+
'listStocktakes',
|
|
242
|
+
'getStocktake',
|
|
243
|
+
'listStocktakeItems',
|
|
244
|
+
'recordStocktakeCount',
|
|
245
|
+
'voidStocktakeCount',
|
|
246
|
+
'listStocktakeCounts',
|
|
247
|
+
'reviewStocktake',
|
|
248
|
+
'recountStocktake',
|
|
249
|
+
'closeStocktake',
|
|
250
|
+
'cancelStocktake',
|
|
251
|
+
'getStocktakePdf',
|
|
220
252
|
];
|
|
221
253
|
/**
|
|
222
254
|
* Die Endpunkte des Kassenwegs (`https://kasse.kasseneck.at/api/v3/<name>`,
|
|
@@ -254,6 +286,12 @@ exports.POS_CALLS = [
|
|
|
254
286
|
'listMyStockLocations',
|
|
255
287
|
'listMyStock',
|
|
256
288
|
'setMyCashregisterStockLocation',
|
|
289
|
+
// Inventur zaehlen (Lager-Kern Stufe 3): nur ueber den Kassenweg.
|
|
290
|
+
'listMyStocktakes',
|
|
291
|
+
'listMyStocktakeItems',
|
|
292
|
+
'listMyStocktakeCounts',
|
|
293
|
+
'recordMyStocktakeCount',
|
|
294
|
+
'voidMyStocktakeCount',
|
|
257
295
|
];
|
|
258
296
|
/**
|
|
259
297
|
* Die Aufrufe **mit Wirkung**, alphabetisch: sie legen etwas an, aendern oder
|
|
@@ -278,7 +316,9 @@ exports.UNKNOWN_OUTCOME_CALLS = [
|
|
|
278
316
|
'addVariant',
|
|
279
317
|
'cancelInvoice',
|
|
280
318
|
'cancelReceipt',
|
|
319
|
+
'cancelStocktake',
|
|
281
320
|
'changeStockCondition',
|
|
321
|
+
'closeStocktake',
|
|
282
322
|
'createArticle',
|
|
283
323
|
'createCreditNote',
|
|
284
324
|
'createCustomer',
|
|
@@ -289,6 +329,7 @@ exports.UNKNOWN_OUTCOME_CALLS = [
|
|
|
289
329
|
'createPrintJob',
|
|
290
330
|
'createReceipt',
|
|
291
331
|
'createReservation',
|
|
332
|
+
'createStocktake',
|
|
292
333
|
'createVariantGroup',
|
|
293
334
|
'createWebhook',
|
|
294
335
|
'deactivateArticle',
|
|
@@ -302,11 +343,15 @@ exports.UNKNOWN_OUTCOME_CALLS = [
|
|
|
302
343
|
'pairRegisterDevice',
|
|
303
344
|
'receiveGoods',
|
|
304
345
|
'recordInvoicePayment',
|
|
346
|
+
'recordMyStocktakeCount',
|
|
305
347
|
'recordStockLoss',
|
|
348
|
+
'recordStocktakeCount',
|
|
349
|
+
'recountStocktake',
|
|
306
350
|
'releaseReservation',
|
|
307
351
|
'reportCustomerContract',
|
|
308
352
|
'requestCustomerSignature',
|
|
309
353
|
'reverseStockMovement',
|
|
354
|
+
'reviewStocktake',
|
|
310
355
|
'revokeCustomerMandate',
|
|
311
356
|
'rotatePartnerWebhookSecret',
|
|
312
357
|
'rotateWebhookSecret',
|
|
@@ -328,6 +373,8 @@ exports.UNKNOWN_OUTCOME_CALLS = [
|
|
|
328
373
|
'updatePartnerWebhook',
|
|
329
374
|
'updateVariantGroup',
|
|
330
375
|
'updateWebhook',
|
|
376
|
+
'voidMyStocktakeCount',
|
|
377
|
+
'voidStocktakeCount',
|
|
331
378
|
'withdrawInvoiceItem',
|
|
332
379
|
];
|
|
333
380
|
/**
|
|
@@ -382,6 +429,8 @@ exports.CALLS_WITHOUT_EFFECT = Object.freeze({
|
|
|
382
429
|
getReportV2: 'read',
|
|
383
430
|
getReservation: 'read',
|
|
384
431
|
getStock: 'read',
|
|
432
|
+
getStocktake: 'read',
|
|
433
|
+
getStocktakePdf: 'read',
|
|
385
434
|
getVariantGroup: 'read',
|
|
386
435
|
hobexGetStatus: 'read',
|
|
387
436
|
listArticles: 'read',
|
|
@@ -397,6 +446,9 @@ exports.CALLS_WITHOUT_EFFECT = Object.freeze({
|
|
|
397
446
|
listMyReceipts: 'read',
|
|
398
447
|
listMyStock: 'read',
|
|
399
448
|
listMyStockLocations: 'read',
|
|
449
|
+
listMyStocktakeCounts: 'read',
|
|
450
|
+
listMyStocktakeItems: 'read',
|
|
451
|
+
listMyStocktakes: 'read',
|
|
400
452
|
listMyTipRecipients: 'read',
|
|
401
453
|
listPartnerCustomers: 'read',
|
|
402
454
|
listPartnerWebhookDeliveries: 'read',
|
|
@@ -406,6 +458,9 @@ exports.CALLS_WITHOUT_EFFECT = Object.freeze({
|
|
|
406
458
|
listReservations: 'read',
|
|
407
459
|
listStock: 'read',
|
|
408
460
|
listStockMovements: 'read',
|
|
461
|
+
listStocktakeCounts: 'read',
|
|
462
|
+
listStocktakeItems: 'read',
|
|
463
|
+
listStocktakes: 'read',
|
|
409
464
|
listVariantGroups: 'read',
|
|
410
465
|
listWebhookDeliveries: 'read',
|
|
411
466
|
listWebhooks: 'read',
|
|
@@ -429,12 +484,12 @@ function isUnknownOutcomeCall(name) {
|
|
|
429
484
|
const OEFFENTLICH = new Set(exports.PUBLIC_CALLS);
|
|
430
485
|
const KASSENWEG = new Set(exports.POS_CALLS);
|
|
431
486
|
const NUR_KASSE = new Set(exports.POS_CALLS.filter((name) => !OEFFENTLICH.has(name)));
|
|
432
|
-
/** Einer der
|
|
487
|
+
/** Einer der 33 Aufrufe des Kassenwegs. */
|
|
433
488
|
function isPosCall(name) {
|
|
434
489
|
return KASSENWEG.has(name);
|
|
435
490
|
}
|
|
436
491
|
/**
|
|
437
|
-
* Nur ueber den Kassenweg erreichbar (
|
|
492
|
+
* Nur ueber den Kassenweg erreichbar (27 Namen): unter `api.kasseneck.at/v3`
|
|
438
493
|
* gibt es sie nicht. Der Transport schickt sie darum ohne eigene Basis an
|
|
439
494
|
* [POS_BASE_URL] statt an die oeffentliche Basis.
|
|
440
495
|
*/
|
|
@@ -280,6 +280,8 @@ exports.PAYMENT_CALL_REJECTED_CODES = Object.freeze([
|
|
|
280
280
|
'account_not_found',
|
|
281
281
|
'live_not_enabled',
|
|
282
282
|
'api_not_approved', // Live-API ohne Freigabe (Entwicklerbereich): vor dem Handler abgewiesen
|
|
283
|
+
'app_check_missing', // Admin-App ohne bzw. mit ungueltigem App Check: vor dem Handler abgewiesen
|
|
284
|
+
'app_check_invalid',
|
|
283
285
|
'unauthorized',
|
|
284
286
|
'mfa_required',
|
|
285
287
|
'user_verification_failed',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { type AuthCredentials, type KasseneckAuth, type ApiKeyAuthOptions, type RegisterUserAuthOptions, apiKeyAuth, registerUserAuth, } from './auth.js';
|
|
2
|
-
export { DEFAULT_BASE_URL, POS_BASE_URL, DEFAULT_TIMEOUT_MS, type HttpResponseLike, type HttpRequestInit, type FetchLike, type TransportOptions, type TransportBodyFields, type TransportCallOptions, type KasseneckTransport, type KasseneckBinaryTransport, createTransport, createBinaryTransport, } from './transport.js';
|
|
2
|
+
export { DEFAULT_BASE_URL, POS_BASE_URL, DEFAULT_TIMEOUT_MS, type HttpResponseLike, type HttpRequestInit, type FetchLike, type TransportOptions, type TransportBodyFields, type TransportCallOptions, type KasseneckTransport, type KasseneckBinaryTransport, type KasseneckPdfOrDataTransport, type PdfOrData, createTransport, createBinaryTransport, createPdfOrDataTransport, } from './transport.js';
|
|
3
3
|
export { ALL_CALLS, type ApiCall, PUBLIC_CALLS, POS_CALLS, UNKNOWN_OUTCOME_CALLS, type PublicCall, type PosCall, } from './aufrufe.js';
|
|
4
4
|
export { KasseneckApiError, KasseneckAuthError, KasseneckHttpError, KasseneckNetworkError, KasseneckValidationError, type ValidationScope, type KasseneckError, type HttpFailureReason, type CauseDigest, type ErrorOutcome, CLIENT_ERROR_CODES, type ClientErrorCode, isKasseneckApiError, isKasseneckAuthError, isKasseneckHttpError, isKasseneckNetworkError, isKasseneckValidationError, isOutcomeUnknown, } from './errors.js';
|
|
5
5
|
export { type ReceiptCommonOptions, type SellReceiptOptions, type TipOptions, type TipRecipientShare, type CancelReceiptOptions, type ReceiptWithCompany, sellReceipt, sellReceiptWithCompany, paymentsExpectedCents, cardRefundReference, receiptLayoutFromResult, cancelReceipt, type CancelReceiptResult, zeroReceipt, getReceipt, getReceiptWithCompany, generateFullReceiptId, getFirstReceiptDate, listMyReceipts, type ListMyReceiptsOptions, type ReceiptList, type ReceiptListStats, checkVoucherCombinationError, type SendReceiptEmailOptions, type SendReceiptEmailResult, sendReceiptEmail, } from './receipts.js';
|
package/dist/cjs/client/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createKasseneckApi = exports.getSignatureStatus = exports.getCashboxStatus = exports.getReportV2 = exports.downloadMonthlyReport = exports.downloadDailyReport = exports.listMyCashregisters = exports.sendReceiptEmail = exports.checkVoucherCombinationError = exports.listMyReceipts = exports.getFirstReceiptDate = exports.generateFullReceiptId = exports.getReceiptWithCompany = exports.getReceipt = exports.zeroReceipt = exports.cancelReceipt = exports.receiptLayoutFromResult = exports.cardRefundReference = exports.paymentsExpectedCents = exports.sellReceiptWithCompany = exports.sellReceipt = exports.isOutcomeUnknown = exports.isKasseneckValidationError = exports.isKasseneckNetworkError = exports.isKasseneckHttpError = exports.isKasseneckAuthError = exports.isKasseneckApiError = exports.CLIENT_ERROR_CODES = exports.KasseneckValidationError = exports.KasseneckNetworkError = exports.KasseneckHttpError = exports.KasseneckAuthError = exports.KasseneckApiError = exports.UNKNOWN_OUTCOME_CALLS = exports.POS_CALLS = exports.PUBLIC_CALLS = exports.ALL_CALLS = exports.createBinaryTransport = exports.createTransport = exports.DEFAULT_TIMEOUT_MS = exports.POS_BASE_URL = exports.DEFAULT_BASE_URL = exports.registerUserAuth = exports.apiKeyAuth = void 0;
|
|
3
|
+
exports.createKasseneckApi = exports.getSignatureStatus = exports.getCashboxStatus = exports.getReportV2 = exports.downloadMonthlyReport = exports.downloadDailyReport = exports.listMyCashregisters = exports.sendReceiptEmail = exports.checkVoucherCombinationError = exports.listMyReceipts = exports.getFirstReceiptDate = exports.generateFullReceiptId = exports.getReceiptWithCompany = exports.getReceipt = exports.zeroReceipt = exports.cancelReceipt = exports.receiptLayoutFromResult = exports.cardRefundReference = exports.paymentsExpectedCents = exports.sellReceiptWithCompany = exports.sellReceipt = exports.isOutcomeUnknown = exports.isKasseneckValidationError = exports.isKasseneckNetworkError = exports.isKasseneckHttpError = exports.isKasseneckAuthError = exports.isKasseneckApiError = exports.CLIENT_ERROR_CODES = exports.KasseneckValidationError = exports.KasseneckNetworkError = exports.KasseneckHttpError = exports.KasseneckAuthError = exports.KasseneckApiError = exports.UNKNOWN_OUTCOME_CALLS = exports.POS_CALLS = exports.PUBLIC_CALLS = exports.ALL_CALLS = exports.createPdfOrDataTransport = exports.createBinaryTransport = exports.createTransport = exports.DEFAULT_TIMEOUT_MS = exports.POS_BASE_URL = exports.DEFAULT_BASE_URL = exports.registerUserAuth = exports.apiKeyAuth = void 0;
|
|
4
4
|
var auth_js_1 = require("./auth.js");
|
|
5
5
|
Object.defineProperty(exports, "apiKeyAuth", { enumerable: true, get: function () { return auth_js_1.apiKeyAuth; } });
|
|
6
6
|
Object.defineProperty(exports, "registerUserAuth", { enumerable: true, get: function () { return auth_js_1.registerUserAuth; } });
|
|
@@ -10,6 +10,7 @@ Object.defineProperty(exports, "POS_BASE_URL", { enumerable: true, get: function
|
|
|
10
10
|
Object.defineProperty(exports, "DEFAULT_TIMEOUT_MS", { enumerable: true, get: function () { return transport_js_1.DEFAULT_TIMEOUT_MS; } });
|
|
11
11
|
Object.defineProperty(exports, "createTransport", { enumerable: true, get: function () { return transport_js_1.createTransport; } });
|
|
12
12
|
Object.defineProperty(exports, "createBinaryTransport", { enumerable: true, get: function () { return transport_js_1.createBinaryTransport; } });
|
|
13
|
+
Object.defineProperty(exports, "createPdfOrDataTransport", { enumerable: true, get: function () { return transport_js_1.createPdfOrDataTransport; } });
|
|
13
14
|
var aufrufe_js_1 = require("./aufrufe.js");
|
|
14
15
|
Object.defineProperty(exports, "ALL_CALLS", { enumerable: true, get: function () { return aufrufe_js_1.ALL_CALLS; } });
|
|
15
16
|
Object.defineProperty(exports, "PUBLIC_CALLS", { enumerable: true, get: function () { return aufrufe_js_1.PUBLIC_CALLS; } });
|
|
@@ -91,16 +91,16 @@ export interface TransportOptions {
|
|
|
91
91
|
auth: KasseneckAuth;
|
|
92
92
|
/**
|
|
93
93
|
* Abweichende Basis der **oeffentlichen** Aufrufe (Vorgabe
|
|
94
|
-
* [DEFAULT_BASE_URL]): alles ausser den
|
|
94
|
+
* [DEFAULT_BASE_URL]): alles ausser den 33 Aufrufen des Kassenwegs, und die
|
|
95
95
|
* sechs oeffentlichen davon nur, wenn nicht mit `registerUserAuth`
|
|
96
96
|
* angemeldet. Muss auf `/v3` enden (eigene Proxys erlaubt), sonst wirft das
|
|
97
97
|
* Anlegen; `/v1` oder `/api` gibt es in der 1.x-Linie nicht.
|
|
98
98
|
*/
|
|
99
99
|
baseUrl?: string;
|
|
100
100
|
/**
|
|
101
|
-
* Abweichende Basis des **Kassenwegs** (Vorgabe [POS_BASE_URL]): die
|
|
101
|
+
* Abweichende Basis des **Kassenwegs** (Vorgabe [POS_BASE_URL]): die 27
|
|
102
102
|
* reinen Kassenaufrufe (Kopplung, Anmeldung, Einstellungen, Artikel,
|
|
103
|
-
* Drucker, ...) und mit `registerUserAuth` alle
|
|
103
|
+
* Drucker, ...) und mit `registerUserAuth` alle 33 Aufrufe des Kassenwegs.
|
|
104
104
|
* Die Web-Kasse gibt `'/api/v3'` (gleicher Ursprung). Muss auf `/v3` enden
|
|
105
105
|
* (in der Regel `/api/v3`), sonst wirft das Anlegen.
|
|
106
106
|
*/
|
|
@@ -193,3 +193,27 @@ export declare function createTransport(options: TransportOptions): KasseneckTra
|
|
|
193
193
|
* reports.ts.)
|
|
194
194
|
*/
|
|
195
195
|
export declare function createBinaryTransport(options: TransportOptions): KasseneckBinaryTransport;
|
|
196
|
+
/**
|
|
197
|
+
* Ergebnis eines Aufrufs, der eine Datei **oder** eine Nutzlast liefert: das
|
|
198
|
+
* PDF als Bytes oder die `data` einer Erfolgshuelle (etwa ein Lese-Link, wenn
|
|
199
|
+
* die Datei zu gross fuer die Antwort ist).
|
|
200
|
+
*/
|
|
201
|
+
export type PdfOrData = {
|
|
202
|
+
pdf: Uint8Array;
|
|
203
|
+
} | {
|
|
204
|
+
data: unknown;
|
|
205
|
+
};
|
|
206
|
+
/**
|
|
207
|
+
* Ruft eine Backend-Funktion auf, die ein PDF **oder** eine JSON-Nutzlast
|
|
208
|
+
* liefert (Inventurprotokoll: die Datei bis 9 MiB, darueber ein Lese-Link).
|
|
209
|
+
*/
|
|
210
|
+
export type KasseneckPdfOrDataTransport = (functionName: string, params?: Record<string, unknown>) => Promise<PdfOrData>;
|
|
211
|
+
/**
|
|
212
|
+
* Dritter Einstiegspunkt, fuer Aufrufe, die eine Datei oder eine Nutzlast
|
|
213
|
+
* liefern (`getStocktakePdf` aus `./inventory`). Wie [createBinaryTransport]
|
|
214
|
+
* wird die Antwort nur als Bytes gelesen; die ersten Bytes entscheiden: `%PDF`
|
|
215
|
+
* ergibt `{ pdf }`, eine Erfolgshuelle `{ data }`, eine Fehlerhuelle denselben
|
|
216
|
+
* fachlichen Fehler wie auf dem JSON-Weg. Leer, kein JSON oder ohne Statusfeld
|
|
217
|
+
* ist unlesbar mit denselben Gruenden wie dort.
|
|
218
|
+
*/
|
|
219
|
+
export declare function createPdfOrDataTransport(options: TransportOptions): KasseneckPdfOrDataTransport;
|