@kreiseck/kasseneck-api 1.16.0 → 1.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/dist/cjs/client/receipts.js +8 -0
- package/dist/cjs/client/reports.d.ts +10 -9
- package/dist/cjs/client/reports.js +10 -9
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/models/voucher.d.ts +46 -4
- package/dist/cjs/models/voucher.js +58 -11
- package/dist/cjs/pos/artikel.d.ts +9 -0
- package/dist/cjs/pos/artikel.js +1 -0
- package/dist/cjs/pos/gutschein.d.ts +107 -2
- package/dist/cjs/pos/gutschein.js +124 -4
- package/dist/cjs/pos/index.d.ts +1 -1
- package/dist/cjs/pos/index.js +7 -3
- package/dist/cjs/pos/texte.d.ts +39 -0
- package/dist/cjs/pos/texte.js +22 -0
- package/dist/cjs/receipt/due.d.ts +20 -9
- package/dist/cjs/receipt/due.js +1 -0
- package/dist/cjs/receipt/gutschein-plan.d.ts +23 -7
- package/dist/cjs/receipt/gutschein-plan.js +67 -2
- package/dist/cjs/receipt/index.d.ts +1 -1
- package/dist/cjs/stored/draht.js +10 -2
- package/dist/cjs/stored/vokabular.d.ts +1 -1
- package/dist/cjs/stored/vokabular.js +84 -3
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/client/receipts.js +8 -0
- package/dist/esm/client/reports.d.ts +10 -9
- package/dist/esm/client/reports.js +10 -9
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/models/voucher.d.ts +46 -4
- package/dist/esm/models/voucher.js +56 -11
- package/dist/esm/pos/artikel.d.ts +9 -0
- package/dist/esm/pos/artikel.js +1 -0
- package/dist/esm/pos/gutschein.d.ts +107 -2
- package/dist/esm/pos/gutschein.js +123 -3
- package/dist/esm/pos/index.d.ts +1 -1
- package/dist/esm/pos/index.js +2 -2
- package/dist/esm/pos/texte.d.ts +39 -0
- package/dist/esm/pos/texte.js +22 -0
- package/dist/esm/receipt/due.d.ts +20 -9
- package/dist/esm/receipt/due.js +1 -0
- package/dist/esm/receipt/gutschein-plan.d.ts +23 -7
- package/dist/esm/receipt/gutschein-plan.js +68 -3
- package/dist/esm/receipt/index.d.ts +1 -1
- package/dist/esm/stored/draht.js +10 -2
- package/dist/esm/stored/vokabular.d.ts +1 -1
- package/dist/esm/stored/vokabular.js +84 -3
- 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 +43 -2
- package/fixtures/receipt-due-voucher-generated.json +485 -483
- package/fixtures/surface.json +17 -1
- package/fixtures/v3/README.md +8 -1
- package/fixtures/v3/antworten/belege.json +27 -12
- package/fixtures/v3/antworten/belegmail.json +4 -1
- package/fixtures/v3/antworten/berichte.json +151 -0
- package/fixtures/v3/antworten/kasse-belege.json +27 -12
- package/fixtures/v3/antworten/kasse.json +366 -9
- package/fixtures/v3/antworten/lager.json +1 -1
- package/fixtures/v3/antworten/rechnungen.json +4 -1
- package/fixtures/v3/antworten/storno.json +4 -1
- package/fixtures/v3/stored/belege.json +4 -1
- package/fixtures/v3/stored/kasse.json +2 -2
- package/fixtures/v3/stored/rechnungen.json +4 -1
- package/fixtures/v3/v3-vokabular.json +417 -10
- package/fixtures/v3/zahlbetrag-faelle.json +29 -10
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,27 @@ 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.17.1 - 2026-10-29
|
|
8
|
+
|
|
9
|
+
- **Contract `v3` gains `fixtures/v3/antworten/berichte.json`** (backend keck#798): `getCashregisterReport` as a binary path, generated from the real handler. A case with `file` is the PDF (HTTP 200, `Content-Type: application/pdf`, the bytes start with `file.startsWith`); every rejection also comes with HTTP 200, as an envelope with a code (`period_not_closed` for the current month and today, `period_in_future`, `invalid_period`). New test `test/v3-berichte-vertrag.test.ts` replays the file through `createBinaryTransport`: the PDF arrives byte for byte, each rejection is a `KasseneckApiError` with the code of the contract and outcome `rejected`. No behaviour change: the binary path always decided on the first bytes. Reason: the Dart twin returned such an envelope as PDF bytes up to 11.8.0 (fixed in 11.8.1); with the case in the contract both packages and the backend are pinned to the same answer, and the Dart twin replays this file too.
|
|
10
|
+
- The other contract files change only `_quelle` (new inputs on the backend side).
|
|
11
|
+
|
|
12
|
+
## 1.17.0 - 2026-10-29
|
|
13
|
+
|
|
14
|
+
Vouchers at the register, stage 4b: voucher types (Gutschein-Sorten). A business names any number of voucher types (multi- or single-purpose, free or fixed amount, validity, payout, label template); the register shows one tile per type in a tab "Gutscheine" and sells a value voucher only through a type. Additive for reading, with three behaviour changes for selling (see the items on `typeId` and the due amount).
|
|
15
|
+
|
|
16
|
+
- **Voucher types in the register settings: `PosVoucherSettings.typeSale`, `types`, `serviceArticles`, `labelDefault`.** `typeSale` shows the tab (server switch and at least one sellable type or service article), `types` are the sellable types in tile order (`PosVoucherType`: `id`, `name`, `kind`, `vatRateBp`, `amount` free or fixed, `validity` unlimited or years, `payout`, `label`, `order`, `active`, `soldCount`), `serviceArticles` adds the fixed tile "Leistungsgutschein", `labelDefault` is the business's standard label template. The four fields are optional in the type so existing literals still compile; `posVoucherSettingsFromWire` always sets them (an older server: off, empty, `null`). Fail-closed as before: a malformed `typeSale`, `serviceArticles` or `types` closes the whole block, a malformed type is dropped on its own (unknown kind, rate not matching the kind, fixed amount outside 1.00-10,000.00 €, years outside 1-30, payout `never` with a limited validity, inactive, reserved id), and `typeSale` is off when no type and no service article is left. An unusable label template becomes `null` and never closes anything (a sale never fails on the label). The old field `label` (registers before 1.17) is not read. Reason: from stage 4b the server sells value vouchers only through a voucher type and keeps `sale` always `false`, so registers before 1.17 never offer a sale it would reject.
|
|
17
|
+
- **New types and lists in `./pos`:** `PosVoucherType`, `VoucherLabelTemplate` (passed through as a copy; the package does not draw labels), `VoucherPayout`, `VoucherTypeKind`, `VOUCHER_TYPE_KINDS`, `VOUCHER_AMOUNT_MODES`, `VOUCHER_TYPE_VALIDITY_PATTERNS`, `VOUCHER_PAYOUTS` (equal to the `/v3` catalogues, also in `fixtures/surface.json`). Reason: web register and app read the same model.
|
|
18
|
+
- **A value voucher is sold only with `typeId`:** `Voucher.typeId` carries the voucher type, the wish is `{ action: 'sell', type: kind, typeId, amountCents }` (with a fixed amount exactly `amount.cents`). `type` may be left out on the wire (the kind then comes from the type); a wish read that way goes out without `type`. Behaviour change: `voucherIsValid` is `false` for a multi- or single-purpose sale without `typeId`, and `createReceipt` rejects it before sending (message starts with `voucher_type_required`); `typeId` on any other action or kind is rejected as `voucher_invalid`, and so are `typeName` and `payout` on a wish (server fields, `GUTSCHEIN_SERVERFELDER`). Reason: the server answers a value sale without type `voucher_type_required`; nothing is sent that it would refuse.
|
|
19
|
+
- **Due amount with voucher types: `ReceiptDueOptions.voucherTypes` (`VoucherDueType` = `id`, `kind`, `vatRateBp`, `amount` of a `PosVoucherType`).** A sale through a type takes kind and rate from the type (multi-purpose as value flow, from the zero-rate date in the 0 % bucket; single-purpose as an item at the rate of the type, 0 % for a small business). A type the register does not pass (or one the server would not sell) throws `voucher_type_not_found`, a different fixed amount `voucher_amount_mismatch`, and so does a `type` other than the kind of the type (the owner switched the kind after the register loaded its types; the register reloads them on this code), a reserved id `voucher_type_not_found`. Behaviour change: a value sale without `typeId` still computes with a `voucherSettings` that names a kind exactly as in 1.16 (for existing callers), but without `voucherSettings` or with one naming no kind (`valueVoucherType: null`, as every stage-4b server sends) it now throws `voucher_type_required` instead of `voucher_settings_missing`. Reason: the register computes the amount to charge before the card terminal, with the same rules and codes as the server's `gutschein-beleg.plane`.
|
|
20
|
+
- **Payout locked per voucher:** `VoucherCheck.payout` (`allowed`/`never`, frozen at sale) and `VoucherCheck.typeName` from `checkVoucher`; a payout of a `never` voucher throws `voucher_payout_not_allowed` in the due amount (also when expired). An unknown payout value reads as `never` without throwing, because redeeming must not fail on a new value. Reason: a business may exclude payouts for unlimited voucher types; the server refuses them.
|
|
21
|
+
- **Validity in years:** `VoucherValidity.redeemableYears` (1-30) from `checkVoucher`, also in `IssuedVoucher.validity`. The patterns stay `unlimited`, `1+3`, `custom`; the type's own pattern `years` never appears on a voucher. A voucher of a type with N years comes as `1+3` for every N, with the explicit dates (`redeemableUntil` = sale + N years, `refundableUntil` = sale + N + 3 years) and `redeemableYears` = N; read N from `redeemableYears`, never from the pattern. Reason: registers before 1.17 keep redeeming such vouchers and print "einlösbar bis <date>" from `redeemableUntil` on a reprint (with `custom` and no `validUntil` they printed no validity line at all).
|
|
22
|
+
- **Service vouchers only for approved articles: `PosArticle.serviceVoucher`** (only an explicit `true` counts; the reader always sets it, also `fromStoredArticle` from `gutscheinLeistung`), and `VoucherDueArticle.serviceVoucher`: `false` throws `voucher_service_not_allowed`, absent computes as before. Reason: the tile "Leistungsgutschein" offers only approved articles, the server sells no other.
|
|
23
|
+
- **Receipt entries of a sale through a type** read and write back `typeId`, `typeName` and `payout`; `IssuedVoucher` gains `typeId` and `typeName`; the `./stored` twin maps `sorteId`, `sorteName` and `auszahlung` (`erlaubt`/`nie`) like the server. Reason: the receipt and the label show the type name, and a cached receipt must write back unchanged.
|
|
24
|
+
- **5 labels and 5 sentences:** `voucher.tab` (Gutscheine), `voucher.enter_amount` (Betrag eingeben), `voucher.service_tile` (Leistungsgutschein), `voucher.kind_multi_short` (Mehrzweck), `voucher.kind_single_short` (Einzweck {rate} %); `VOUCHER_ERROR_MESSAGES` maps the new register codes to `voucher_error.type_required`, `type_not_found`, `amount_mismatch`, `service_not_allowed`, `payout_not_allowed` (also in `fixtures/pos-texts.json`). The codes of the customer area (`invalid_voucher_type`, `voucher_type_in_use`, `too_many_voucher_types`) are not register codes and get no sentence here. Reason: web register and app say the same words for the same tile and error.
|
|
25
|
+
- **One sentence of the register itself: `voucher.type_changed`** ("Diese Gutschein-Sorte hat sich geändert. Bitte die Zeile entfernen und die Kachel neu antippen.", also in `fixtures/pos-texts.json`). The register shows it on a voucher sale line in the cart that no longer matches the reloaded types (type changed, deactivated or deleted); the sentences after a server rejection stay `voucher_error.type_not_found` and `voucher_error.amount_mismatch`. Reason: those say "Die Kasse lädt die Sorten neu", which is over once the types are reloaded; the line blocks payment until it is removed and the tile tapped again, and the cashier must be told so.
|
|
26
|
+
- Contract re-fetched from the backend (stage 4b): the server names the position of a single-purpose sale with the type name, so the print digests of `sale_single_purpose_voucher` (both channels) are redrawn; the generated due cases (`fixtures/receipt-due-voucher-generated.json`, seed 20261027) now sell through types, with and without `type`, free and fixed, and cover the rejections above.
|
|
27
|
+
|
|
7
28
|
## 1.16.0 - 2026-10-28
|
|
8
29
|
|
|
9
30
|
Header data for the full view of `listReceipts`, and the new upper limit of `getReportV2`. Additive.
|
|
@@ -20,6 +20,7 @@ exports.belegAusHuelle = belegAusHuelle;
|
|
|
20
20
|
exports.belegMitFirmaAusHuelle = belegMitFirmaAusHuelle;
|
|
21
21
|
exports.paymentsExpectedCents = paymentsExpectedCents;
|
|
22
22
|
const index_js_1 = require("../enums/index.js");
|
|
23
|
+
const voucher_js_1 = require("../models/voucher.js");
|
|
23
24
|
const index_js_2 = require("../models/index.js");
|
|
24
25
|
const receipt_output_js_1 = require("../models/receipt-output.js");
|
|
25
26
|
const validator_1 = require("@kreiseck/validator");
|
|
@@ -143,6 +144,13 @@ function createReceiptParams(options) {
|
|
|
143
144
|
if (typ.value === index_js_1.ReceiptType.training.value && vouchers.some(index_js_2.isNewFormVoucher)) {
|
|
144
145
|
throw eingabefehler('Gutscheine der neuen Form gibt es nicht auf Schulungsbelegen (receiptType training).');
|
|
145
146
|
}
|
|
147
|
+
// Gutscheine Stufe 4b: ein Wertgutschein nur ueber eine Sorte, die Sorte nur an einem solchen Verkauf.
|
|
148
|
+
if (vouchers.some((voucher) => (0, voucher_js_1.istWertVerkauf)(voucher) && voucher.typeId == null)) {
|
|
149
|
+
throw eingabefehler('voucher_type_required: Ein Mehrzweck- oder Einzweckgutschein wird nur ueber eine Gutschein-Sorte verkauft (typeId aus getKasseSettings vouchers.types).');
|
|
150
|
+
}
|
|
151
|
+
if (vouchers.some((voucher) => voucher.typeId != null && !(0, voucher_js_1.istWertVerkauf)(voucher))) {
|
|
152
|
+
throw eingabefehler('voucher_invalid: typeId gehoert nur an den Verkauf eines Mehrzweck- oder Einzweckgutscheins.');
|
|
153
|
+
}
|
|
146
154
|
if (vouchers.some((voucher) => !(0, index_js_2.voucherIsValid)(voucher))) {
|
|
147
155
|
throw eingabefehler('Ungueltiger Gutschein uebergeben.');
|
|
148
156
|
}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { type Receipt, type ReceiptCompany, type ReportMonth } from '../models/index.js';
|
|
2
2
|
import type { InternerBinaerTransport, InternerTransport } from './aufrufe.js';
|
|
3
3
|
/**
|
|
4
|
-
* Bericht-Downloads — Zwilling von `
|
|
5
|
-
*
|
|
4
|
+
* Bericht-Downloads — Zwilling von `getCashregisterReport`,
|
|
5
|
+
* `downloadDailyReport` und `downloadMonthlyReport` in
|
|
6
|
+
* kasseneck_api/lib/kasseneck_api.dart.
|
|
6
7
|
*
|
|
7
|
-
* **
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
8
|
+
* **Alle drei liefern ein PDF, also Binaerdaten.** `response.text()` waere hier
|
|
9
|
+
* falsch: es deutet die Bytes als UTF-8 und ersetzt jedes Byte ueber 0x7F
|
|
10
|
+
* durch U+FFFD, ein so "heruntergeladener" Bericht liesse sich in keinem
|
|
11
|
+
* Betrachter oeffnen. Gelesen wird `arrayBuffer()`, geliefert `Uint8Array`;
|
|
12
|
+
* eine Ablehnung mit HTTP 200 und Huelle (`period_not_closed`) wird zum Fehler
|
|
13
|
+
* (siehe [createBinaryTransport] in transport.ts). Der Dart-Zwilling reichte
|
|
14
|
+
* sie bis 11.8.0 als PDF durch und prueft seit 11.8.1 ebenso die ersten Bytes.
|
|
14
15
|
*
|
|
15
16
|
* **Kassen-Benutzer-Weg (`registerUserAuth`, Browser-Kasse):** Keiner der
|
|
16
17
|
* beiden Download-Endpunkte setzt `allowRegisterUser`; sie funktionieren nur
|
|
@@ -8,16 +8,17 @@ const index_js_1 = require("../models/index.js");
|
|
|
8
8
|
const vienna_time_js_1 = require("../vienna-time.js");
|
|
9
9
|
const errors_js_1 = require("./errors.js");
|
|
10
10
|
/**
|
|
11
|
-
* Bericht-Downloads — Zwilling von `
|
|
12
|
-
*
|
|
11
|
+
* Bericht-Downloads — Zwilling von `getCashregisterReport`,
|
|
12
|
+
* `downloadDailyReport` und `downloadMonthlyReport` in
|
|
13
|
+
* kasseneck_api/lib/kasseneck_api.dart.
|
|
13
14
|
*
|
|
14
|
-
* **
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
15
|
+
* **Alle drei liefern ein PDF, also Binaerdaten.** `response.text()` waere hier
|
|
16
|
+
* falsch: es deutet die Bytes als UTF-8 und ersetzt jedes Byte ueber 0x7F
|
|
17
|
+
* durch U+FFFD, ein so "heruntergeladener" Bericht liesse sich in keinem
|
|
18
|
+
* Betrachter oeffnen. Gelesen wird `arrayBuffer()`, geliefert `Uint8Array`;
|
|
19
|
+
* eine Ablehnung mit HTTP 200 und Huelle (`period_not_closed`) wird zum Fehler
|
|
20
|
+
* (siehe [createBinaryTransport] in transport.ts). Der Dart-Zwilling reichte
|
|
21
|
+
* sie bis 11.8.0 als PDF durch und prueft seit 11.8.1 ebenso die ersten Bytes.
|
|
21
22
|
*
|
|
22
23
|
* **Kassen-Benutzer-Weg (`registerUserAuth`, Browser-Kasse):** Keiner der
|
|
23
24
|
* beiden Download-Endpunkte setzt `allowRegisterUser`; sie funktionieren nur
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { ReceiptType, type ReceiptTypeKey, VatRate, type VatRateKey, KeckPaymentMethod, type KeckPaymentMethodKey, CreditCardProvider, type CreditCardProviderKey, VoucherType, type VoucherTypeKey, VoucherAction, type VoucherActionKey, StripeLinkMode, type StripeLinkModeKey, } from './enums/index.js';
|
|
2
2
|
export { type ReceiptItem, type ReceiptItemPayload, type ReceiptItemPayloadRead, toReceiptItemPayload, fromReceiptItemPayload, receiptItemTotalCents, receiptItemIsValid, negateReceiptItem, type TipRecipient, isTipItem, isVoucherItem, isVoucherFloatItem, type Voucher, type VoucherArticle, type IssuedVoucher, type VoucherPayload, toVoucherPayload, fromVoucherPayload, voucherIsValid, type Receipt, type RegistrationInfo, type ReceiptPayload, type ReceiptPayloadRead, toReceiptPayload, fromReceiptPayload, receiptSubSumCents, receiptSumCents, receiptValueVoucherSign, type CancellationOf, type CancellationItem, type Cancellation, type CancellationReason, type CancellationErrorCode, type CancellationStatus, type ReturnDisposition, RETURN_DISPOSITIONS, CANCELLATION_REASONS, CANCELLATION_STATUSES, CANCELLATION_ERROR_CODES, CANCELLATION_RESERVATION_MS, isCancellationReason, isReturnDisposition, isCancellationErrorCode, cancellationErrorCode, isCancellationError, cancellationFieldErrors, type CancellationFieldError, type ReceiptPayment, type ReceiptPaymentPayload, type ReceiptPaymentInput, fromReceiptPaymentPayload, toReceiptPaymentPayload, type PaymentErrorCode, PAYMENT_ERROR_CODES, isPaymentErrorCode, paymentErrorCode, isPaymentError, paymentFieldErrors, type PaymentFieldError, type ReceiptEmailErrorCode, type ReceiptEmailVia, RECEIPT_EMAIL_ERROR_CODES, RECEIPT_EMAIL_SEND_ERROR_CODES, type ReceiptEmailSendErrorCode, RECEIPT_EMAIL_VIAS, isReceiptEmailErrorCode, receiptEmailErrorCode, isReceiptEmailError, receiptEmailFieldErrors, type ReceiptEmailFieldError, RECEIPT_OUTPUT_KINDS, type ReceiptOutputKind, RECEIPT_OUTPUT_LOG_KINDS, type ReceiptOutputLogKind, RECEIPT_OUTPUT_RESULTS, type ReceiptOutputResult, RECEIPT_OUTPUT_ENTRIES_MAX, type ReceiptOutput, type ReceiptOutputActor, RECEIPT_OUTPUT_ENTRY_ERROR_CODES, type ReceiptOutputEntryErrorCode, RECEIPT_OUTPUT_ERROR_CODES, type ReceiptOutputErrorCode, isReceiptOutputErrorCode, receiptOutputErrorCode, isReceiptOutputError, receiptOutputFieldErrors, type ReceiptOutputFieldError, type ReceiptErrorCode, type ReceiptFieldError, RECEIPT_ERROR_CODES, isReceiptErrorCode, receiptErrorCode, isReceiptError, receiptFieldErrors, remainingQuantities, TIP_REFUND_SOURCES, type TipRefundSource, isTipRefundSource, openStaffTipCents, cancellationItemsForTip, cancellationCashRefundCents, asksTipRefundSource, asksRefundTip, type ReceiptCompany, type ReceiptCompanyPayload, fromReceiptCompanyPayload, receiptCompanyTaxInfo, type Cashregister, type CashregisterOnboarding, type CashregisterPayload, type CashregisterOnboardingPayload, type CashregisterAutoLogout, type CashregisterAutoLogoutPayload, fromCashregisterPayload, type ReceiptSummary, type ReceiptSummaryPayload, fromReceiptSummaryPayload, type ZeroKind, ZERO_KINDS, isZeroKind, type ReportMonth, reportMonthFromDate, previousReportMonth, nextReportMonth, reportMonthKey, reportMonthReadable, type StripeUrlSession, type StripeUrlSessionPayload, toStripeUrlSessionPayload, fromStripeUrlSessionPayload, type HobexReceipt, type HobexReceiptPayload, toHobexReceiptPayload, fromHobexReceiptPayload, hobexReceiptToCardPaymentData, hobexReceiptNeedsSignature, } from './models/index.js';
|
|
3
3
|
export { type AuthCredentials, type KasseneckAuth, type ApiKeyAuthOptions, type RegisterUserAuthOptions, apiKeyAuth, registerUserAuth, 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, ALL_CALLS, type ApiCall, PUBLIC_CALLS, POS_CALLS, UNKNOWN_OUTCOME_CALLS, type PublicCall, type PosCall, createTransport, createBinaryTransport, createPdfOrDataTransport, 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, type ReceiptCommonOptions, type SellReceiptOptions, type TipOptions, type TipRecipientShare, type CancelReceiptOptions, type CancelReceiptResult, type ReceiptWithCompany, sellReceipt, sellReceiptWithCompany, paymentsExpectedCents, cardRefundReference, receiptLayoutFromResult, cancelReceipt, zeroReceipt, getReceipt, getReceiptWithCompany, generateFullReceiptId, getFirstReceiptDate, listMyReceipts, type ListMyReceiptsOptions, type ReceiptList, type ReceiptListStats, listMyCashregisters, checkVoucherCombinationError, type SendReceiptEmailOptions, type SendReceiptEmailResult, sendReceiptEmail, type ReceiptOutputEntry, type LogReceiptOutputsOptions, type LogReceiptOutputsResult, type RejectedReceiptOutput, logReceiptOutputs, downloadDailyReport, downloadMonthlyReport, getCashregisterReport, type CashregisterReportPeriod, getReportV2, type ReportV2, type ReportV2Metadata, type ReportV2Options, listReceipts, listAllReceipts, fromListReceiptsSummaryPayload, LIST_RECEIPTS_VIEWS, LIST_RECEIPTS_ORDERS, LIST_RECEIPTS_LIMIT_MAX, LIST_RECEIPTS_DAYS_MAX, LIST_ALL_RECEIPTS_MAX_PAGES, LIST_RECEIPTS_ERROR_CODES, type ListReceiptsErrorCode, type ListReceiptsView, type ListReceiptsOrder, type ListReceiptsOptions, type ListReceiptsWindow, type ListReceiptsGrossByRate, type ListReceiptsSummary, type ListReceiptsDaySummary, type ListReceiptsPage, type ListedReceipt, type CashboxStatus, type SignatureStatus, getCashboxStatus, getSignatureStatus, type KasseneckApi, createKasseneckApi, } from './client/index.js';
|
|
4
|
-
export { type ReceiptDueTip, type ReceiptDueTipRecipient, type ReceiptDueOptions, type ReceiptDueBuckets, type ReceiptDueBreakdown, type ReceiptDueErrorReason, receiptDueCents, receiptDueBreakdown, ReceiptDueError, RECEIPT_DUE_ERROR_REASONS, isReceiptDueError, type VoucherDueInfo, type VoucherDueArticle, type VoucherRedeemContext, voucherRedeemMaxCents, VOUCHER_ZERO_RATE_BUCKET_FROM, } from './receipt/due.js';
|
|
4
|
+
export { type ReceiptDueTip, type ReceiptDueTipRecipient, type ReceiptDueOptions, type ReceiptDueBuckets, type ReceiptDueBreakdown, type ReceiptDueErrorReason, receiptDueCents, receiptDueBreakdown, ReceiptDueError, RECEIPT_DUE_ERROR_REASONS, isReceiptDueError, type VoucherDueInfo, type VoucherDueArticle, type VoucherDueType, type VoucherRedeemContext, voucherRedeemMaxCents, VOUCHER_ZERO_RATE_BUCKET_FROM, } from './receipt/due.js';
|
|
5
5
|
export { parseServerTimeStamp, toViennaWallClock, type ViennaWallClock } from './vienna-time.js';
|
|
6
6
|
export { type PosBusinessSettings, type PosDeviceSettings, type PosSettings, type ArticleGroup, type PosArticle, POS_BUSINESS_DEFAULTS, POS_DEVICE_DEFAULTS, mergePosSettings, fromArticleGroupPayload, fromPosArticlePayload, listMyArticleGroups, listMyArticles, getPosSettings, setMyPosSettings, setMyRegisterDeviceSettings, distributeDiscount, cancelScopeOf, receiptsScopeOf, stockViewOf, voucherPermsOf, } from './pos/index.js';
|
|
@@ -14,6 +14,12 @@ export interface Voucher {
|
|
|
14
14
|
name?: string;
|
|
15
15
|
code?: string;
|
|
16
16
|
action: VoucherAction | string;
|
|
17
|
+
/**
|
|
18
|
+
* Art des Gutscheins. Beim Verkauf ueber eine Sorte die Art der Sorte
|
|
19
|
+
* (`PosVoucherType.kind`): der Server prueft sie gegen die Sorte und lehnt
|
|
20
|
+
* eine andere ab (`voucher_invalid`). Am Draht darf sie dort fehlen (die Art
|
|
21
|
+
* kommt dann aus der Sorte); ein so gelesener Wunsch geht ohne `type` hinaus.
|
|
22
|
+
*/
|
|
17
23
|
type: VoucherType | string;
|
|
18
24
|
valueCents?: number;
|
|
19
25
|
/** Neue Form: Betrag in Cent (Verkauf, Einloesung, Auszahlung). */
|
|
@@ -26,6 +32,18 @@ export interface Voucher {
|
|
|
26
32
|
positions?: number[];
|
|
27
33
|
/** Neue Form, Auszahlung: Grund, 1 bis 200 Zeichen. */
|
|
28
34
|
reason?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Neue Form, Wertgutschein verkaufen: die Gutschein-Sorte
|
|
37
|
+
* (`PosVoucherType.id` aus `getKasseSettings`). Pflicht fuer jeden Verkauf
|
|
38
|
+
* eines Mehrzweck- oder Einzweckgutscheins (Server: `voucher_type_required`),
|
|
39
|
+
* an jeder anderen Aktion oder Art verboten. Am gelesenen Eintrag die Sorte
|
|
40
|
+
* des Verkaufs (fehlt ohne Sorte).
|
|
41
|
+
*/
|
|
42
|
+
typeId?: string;
|
|
43
|
+
/** Name der Sorte beim Verkauf (eingefroren). */
|
|
44
|
+
typeName?: string;
|
|
45
|
+
/** Auszahlung des verkauften Gutscheins (`allowed`/`never`, eingefroren). */
|
|
46
|
+
payout?: string;
|
|
29
47
|
voucherType?: string;
|
|
30
48
|
voucherId?: string;
|
|
31
49
|
/** Letzte vier Zeichen des Codes; der Klartext steht nie am Beleg. */
|
|
@@ -53,8 +71,13 @@ export interface IssuedVoucher {
|
|
|
53
71
|
quantity?: number;
|
|
54
72
|
/** Nur bei Leistungsgutscheinen: Name des verkauften Artikels; sonst fehlt das Feld. */
|
|
55
73
|
articleName?: string;
|
|
74
|
+
/** Verkauf ueber eine Sorte: ihre Kennung und ihr Name; sonst fehlen die Felder. */
|
|
75
|
+
typeId?: string;
|
|
76
|
+
typeName?: string;
|
|
56
77
|
validity?: {
|
|
57
78
|
pattern: string;
|
|
79
|
+
/** Sorte „N Jahre“: die Zahl N (Muster `1+3` fuer jedes N, die Daten gelten); fehlt sonst. */
|
|
80
|
+
redeemableYears?: number;
|
|
58
81
|
redeemableUntil: string | null;
|
|
59
82
|
refundableUntil: string | null;
|
|
60
83
|
validUntil: string | null;
|
|
@@ -87,6 +110,9 @@ export interface VoucherPayload {
|
|
|
87
110
|
quantity?: number;
|
|
88
111
|
positions?: number[];
|
|
89
112
|
reason?: string;
|
|
113
|
+
typeId?: string;
|
|
114
|
+
typeName?: string;
|
|
115
|
+
payout?: string;
|
|
90
116
|
voucherType?: string;
|
|
91
117
|
voucherId?: string;
|
|
92
118
|
codeSuffix?: string;
|
|
@@ -100,10 +126,19 @@ export interface VoucherPayload {
|
|
|
100
126
|
}
|
|
101
127
|
/** Arten der neuen Gutscheinform (die Altwerte sind `value` und `promo`). */
|
|
102
128
|
export declare const NEUE_GUTSCHEINARTEN: readonly string[];
|
|
103
|
-
/** Gehoert der Gutschein zur neuen Form (Art
|
|
104
|
-
export declare function isNewFormVoucher(voucher: Pick<Voucher, 'type' | 'action'>): boolean;
|
|
105
|
-
/**
|
|
106
|
-
|
|
129
|
+
/** Gehoert der Gutschein zur neuen Form (Art, Aktion `payout` oder Verkauf ueber eine Sorte ohne Art)? */
|
|
130
|
+
export declare function isNewFormVoucher(voucher: Pick<Voucher, 'type' | 'action' | 'typeId'>): boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Wert-Verkauf: ein Mehrzweck- oder Einzweckgutschein wird verkauft (mit Art
|
|
133
|
+
* oder nur ueber die Sorte). Paketintern: Zahlbetrag und Pruefung vor dem
|
|
134
|
+
* Senden entscheiden daran, ob eine Sorte noetig ist.
|
|
135
|
+
*/
|
|
136
|
+
export declare function istWertVerkauf(voucher: Pick<Voucher, 'type' | 'action' | 'typeId'>): boolean;
|
|
137
|
+
/**
|
|
138
|
+
* Felder, die nur der Server setzt; an einem Wunsch sind sie `voucher_invalid`.
|
|
139
|
+
* Sortenname und Auszahlung friert der Server beim Verkauf ein (Stufe 4b).
|
|
140
|
+
*/
|
|
141
|
+
export declare const GUTSCHEIN_SERVERFELDER: readonly ["voucherId", "codeSuffix", "zeroRateBucket", "voucherType", "typeName", "payout"];
|
|
107
142
|
/** Welche Serverfelder tragt der Gutschein (leere Liste = keines)? */
|
|
108
143
|
export declare function voucherServerFields(voucher: Voucher): string[];
|
|
109
144
|
export declare function toVoucherPayload(voucher: Voucher): VoucherPayload;
|
|
@@ -115,3 +150,10 @@ export declare function toVoucherPayload(voucher: Voucher): VoucherPayload;
|
|
|
115
150
|
*/
|
|
116
151
|
export declare function voucherIsValid(voucher: Voucher): boolean;
|
|
117
152
|
export declare function fromVoucherPayload(payload: VoucherPayload): Voucher;
|
|
153
|
+
/**
|
|
154
|
+
* Die Form eines Wunschs der neuen Form. `sorteNoetig: false` laesst einen
|
|
155
|
+
* Wert-Verkauf ohne `typeId` zu: so rechnet der Zahlbetrag den Verkauf eines
|
|
156
|
+
* Aufrufers bis 1.16 mit der alten Gutschein-Einstellung weiter (der Server ab
|
|
157
|
+
* Stufe 4b antwortet darauf `voucher_type_required`). Paketintern.
|
|
158
|
+
*/
|
|
159
|
+
export declare function wunschFormGueltig(v: Voucher, sorteNoetig: boolean): boolean;
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.GUTSCHEIN_SERVERFELDER = exports.NEUE_GUTSCHEINARTEN = void 0;
|
|
4
4
|
exports.isNewFormVoucher = isNewFormVoucher;
|
|
5
|
+
exports.istWertVerkauf = istWertVerkauf;
|
|
5
6
|
exports.voucherServerFields = voucherServerFields;
|
|
6
7
|
exports.toVoucherPayload = toVoucherPayload;
|
|
7
8
|
exports.voucherIsValid = voucherIsValid;
|
|
8
9
|
exports.fromVoucherPayload = fromVoucherPayload;
|
|
10
|
+
exports.wunschFormGueltig = wunschFormGueltig;
|
|
9
11
|
const index_js_1 = require("../enums/index.js");
|
|
10
12
|
const money_js_1 = require("../money.js");
|
|
11
13
|
const enum_payload_js_1 = require("./enum-payload.js");
|
|
@@ -16,23 +18,44 @@ exports.NEUE_GUTSCHEINARTEN = [
|
|
|
16
18
|
index_js_1.VoucherType.service,
|
|
17
19
|
index_js_1.VoucherType.promotion,
|
|
18
20
|
];
|
|
19
|
-
/**
|
|
21
|
+
/**
|
|
22
|
+
* Verkauf ueber eine Sorte ohne Art (`typeId` ohne `type`): die Art kommt aus
|
|
23
|
+
* der Sorte. Zwilling von `gutschein-beleg.istSortenVerkauf`.
|
|
24
|
+
*/
|
|
25
|
+
function istSortenVerkaufOhneArt(voucher) {
|
|
26
|
+
return voucher.action === index_js_1.VoucherAction.sell && voucher.type == null && voucher.typeId != null;
|
|
27
|
+
}
|
|
28
|
+
/** Gehoert der Gutschein zur neuen Form (Art, Aktion `payout` oder Verkauf ueber eine Sorte ohne Art)? */
|
|
20
29
|
function isNewFormVoucher(voucher) {
|
|
21
|
-
return exports.NEUE_GUTSCHEINARTEN.includes(voucher.type) || voucher.action === index_js_1.VoucherAction.payout;
|
|
30
|
+
return exports.NEUE_GUTSCHEINARTEN.includes(voucher.type) || voucher.action === index_js_1.VoucherAction.payout || istSortenVerkaufOhneArt(voucher);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Wert-Verkauf: ein Mehrzweck- oder Einzweckgutschein wird verkauft (mit Art
|
|
34
|
+
* oder nur ueber die Sorte). Paketintern: Zahlbetrag und Pruefung vor dem
|
|
35
|
+
* Senden entscheiden daran, ob eine Sorte noetig ist.
|
|
36
|
+
*/
|
|
37
|
+
function istWertVerkauf(voucher) {
|
|
38
|
+
return voucher.action === index_js_1.VoucherAction.sell
|
|
39
|
+
&& (voucher.type === index_js_1.VoucherType.multi_purpose || voucher.type === index_js_1.VoucherType.single_purpose || istSortenVerkaufOhneArt(voucher));
|
|
22
40
|
}
|
|
23
|
-
/**
|
|
24
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Felder, die nur der Server setzt; an einem Wunsch sind sie `voucher_invalid`.
|
|
43
|
+
* Sortenname und Auszahlung friert der Server beim Verkauf ein (Stufe 4b).
|
|
44
|
+
*/
|
|
45
|
+
exports.GUTSCHEIN_SERVERFELDER = ['voucherId', 'codeSuffix', 'zeroRateBucket', 'voucherType', 'typeName', 'payout'];
|
|
25
46
|
/** Welche Serverfelder tragt der Gutschein (leere Liste = keines)? */
|
|
26
47
|
function voucherServerFields(voucher) {
|
|
27
48
|
return exports.GUTSCHEIN_SERVERFELDER.filter((feld) => voucher[feld] != null);
|
|
28
49
|
}
|
|
29
50
|
const NEUE_FELDER = [
|
|
30
|
-
'amountCents', 'articleId', 'quantity', 'positions', 'reason', 'voucherType', 'voucherId', 'codeSuffix',
|
|
51
|
+
'amountCents', 'articleId', 'quantity', 'positions', 'reason', 'typeId', 'typeName', 'payout', 'voucherType', 'voucherId', 'codeSuffix',
|
|
31
52
|
'vatRateBp', 'article', 'balanceAfterCents', 'remainingQuantityAfter', 'taxedWith', 'exempt', 'zeroRateBucket',
|
|
32
53
|
];
|
|
33
54
|
function toVoucherPayload(voucher) {
|
|
34
55
|
const action = (0, enum_payload_js_1.requireEnumKey)(index_js_1.VoucherAction, voucher.action, 'Gutschein-Aktion');
|
|
35
|
-
|
|
56
|
+
// Verkauf ueber eine Sorte ohne Art: `type` bleibt weg wie im Wunsch (die Art kommt aus der Sorte).
|
|
57
|
+
const ohneArt = istSortenVerkaufOhneArt(voucher);
|
|
58
|
+
const type = ohneArt ? undefined : (0, enum_payload_js_1.requireEnumKey)(index_js_1.VoucherType, voucher.type, 'Gutscheinart');
|
|
36
59
|
// Felder der neuen Form gehen roh hinaus, soweit gesetzt (auch an einem
|
|
37
60
|
// gelesenen Altbeleg: dort fehlen sie, die Nutzlast bleibt byte-gleich).
|
|
38
61
|
const roh = voucher;
|
|
@@ -42,7 +65,7 @@ function toVoucherPayload(voucher) {
|
|
|
42
65
|
neu[feld] = roh[feld];
|
|
43
66
|
return {
|
|
44
67
|
action,
|
|
45
|
-
type,
|
|
68
|
+
...(ohneArt ? {} : { type }),
|
|
46
69
|
// Die neue Form kennt kein `valueCents`; nur ein gelesener Eintrag (die
|
|
47
70
|
// Auszahlung steht beim Server als Wert mit Cent) traegt es weiter.
|
|
48
71
|
...(isNewFormVoucher(voucher) && voucher.valueCents == null ? {} : { valueCents: voucher.valueCents ?? null }),
|
|
@@ -95,11 +118,13 @@ function fromVoucherPayload(payload) {
|
|
|
95
118
|
: payload.value != null
|
|
96
119
|
? (0, money_js_1.euroToCents)(payload.value)
|
|
97
120
|
: undefined;
|
|
121
|
+
// Ein Verkaufswunsch ueber eine Sorte darf ohne Art sein: dann bleibt `type` weg (nicht `undefined`).
|
|
122
|
+
const ohneArt = payload.type == null && payload.action === index_js_1.VoucherAction.sell && payload.typeId != null;
|
|
98
123
|
return {
|
|
99
124
|
name: payload.name ?? undefined,
|
|
100
125
|
code: payload.code ?? undefined,
|
|
101
126
|
action: (0, enum_payload_js_1.readEnumKey)(index_js_1.VoucherAction, payload.action),
|
|
102
|
-
type: (0, enum_payload_js_1.readEnumKey)(index_js_1.VoucherType, payload.type),
|
|
127
|
+
...(ohneArt ? {} : { type: (0, enum_payload_js_1.readEnumKey)(index_js_1.VoucherType, payload.type) }),
|
|
103
128
|
valueCents,
|
|
104
129
|
...lesenNeu(payload),
|
|
105
130
|
};
|
|
@@ -120,15 +145,31 @@ const MAX_GRUND = 200;
|
|
|
120
145
|
const istCent = (n) => typeof n === 'number' && Number.isInteger(n) && n >= 1 && n <= MAX_BETRAG_CENTS;
|
|
121
146
|
const istMenge = (n) => typeof n === 'number' && Number.isInteger(n) && n >= 1 && n <= MAX_STUECK;
|
|
122
147
|
const hatText = (t) => typeof t === 'string' && t.trim().length > 0;
|
|
148
|
+
/**
|
|
149
|
+
* Form einer Sorten-Kennung am Wunsch (gutschein-core.ID_MUSTER ohne den
|
|
150
|
+
* Ausschluss): eine reservierte `__…__` ist der Form nach gueltig, der Server
|
|
151
|
+
* kennt sie nur nicht (`voucher_type_not_found`), ebenso der Zahlbetrag.
|
|
152
|
+
*/
|
|
153
|
+
const SORTE_ID_FORM = /^[A-Za-z0-9_-]{1,128}$/;
|
|
123
154
|
/**
|
|
124
155
|
* Wunsch der neuen Form sendbar? Bildet die Regeln des Servers ab: Serverfelder
|
|
125
156
|
* nie, Betrag/Menge ganz und positiv, Code bei Einloesung und Auszahlung,
|
|
126
157
|
* Auszahlung nur Mehrzweck/Einzweck mit Grund (1 bis 200 Zeichen), Aktion nur
|
|
127
158
|
* einloesbar, Leistung braucht Artikel und Menge (Verkauf) bzw. Positionen
|
|
128
|
-
* (Einloesung)
|
|
159
|
+
* (Einloesung), ein Wertgutschein wird nur ueber eine Sorte verkauft
|
|
160
|
+
* (`typeId`). Felder, die zu einer anderen Aktion/Art gehoeren, sind
|
|
129
161
|
* ebenfalls nicht erlaubt (der Server wiese sie ab).
|
|
130
162
|
*/
|
|
131
163
|
function newFormVoucherIsValid(v) {
|
|
164
|
+
return wunschFormGueltig(v, true);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Die Form eines Wunschs der neuen Form. `sorteNoetig: false` laesst einen
|
|
168
|
+
* Wert-Verkauf ohne `typeId` zu: so rechnet der Zahlbetrag den Verkauf eines
|
|
169
|
+
* Aufrufers bis 1.16 mit der alten Gutschein-Einstellung weiter (der Server ab
|
|
170
|
+
* Stufe 4b antwortet darauf `voucher_type_required`). Paketintern.
|
|
171
|
+
*/
|
|
172
|
+
function wunschFormGueltig(v, sorteNoetig) {
|
|
132
173
|
if (voucherServerFields(v).length > 0)
|
|
133
174
|
return false;
|
|
134
175
|
const r = v;
|
|
@@ -138,6 +179,14 @@ function newFormVoucherIsValid(v) {
|
|
|
138
179
|
}
|
|
139
180
|
if (v.valueCents != null)
|
|
140
181
|
return false;
|
|
182
|
+
// Die Sorte gehoert nur an einen Wert-Verkauf (Server: sorteId sonst voucher_invalid).
|
|
183
|
+
if (istWertVerkauf(v)) {
|
|
184
|
+
if (v.typeId == null ? sorteNoetig : (typeof v.typeId !== 'string' || !SORTE_ID_FORM.test(v.typeId)))
|
|
185
|
+
return false;
|
|
186
|
+
return v.articleId == null && v.quantity == null && v.positions == null && v.reason == null && istCent(v.amountCents);
|
|
187
|
+
}
|
|
188
|
+
if (v.typeId != null)
|
|
189
|
+
return false;
|
|
141
190
|
const allein = v.type === index_js_1.VoucherType.multi_purpose || v.type === index_js_1.VoucherType.single_purpose;
|
|
142
191
|
if (v.action === index_js_1.VoucherAction.payout) {
|
|
143
192
|
return allein && hatText(v.code) && istCent(v.amountCents) && hatText(v.reason) && v.reason.trim().length <= MAX_GRUND
|
|
@@ -148,8 +197,6 @@ function newFormVoucherIsValid(v) {
|
|
|
148
197
|
if (allein) {
|
|
149
198
|
if (v.articleId != null || v.quantity != null || v.positions != null)
|
|
150
199
|
return false;
|
|
151
|
-
if (v.action === index_js_1.VoucherAction.sell)
|
|
152
|
-
return istCent(v.amountCents);
|
|
153
200
|
if (v.action === index_js_1.VoucherAction.redeem)
|
|
154
201
|
return hatText(v.code) && istCent(v.amountCents);
|
|
155
202
|
return false;
|
|
@@ -88,6 +88,14 @@ export interface PosArticle {
|
|
|
88
88
|
* traegt (aeltere Backends) -- dann nicht aus anderen Feldern ableiten.
|
|
89
89
|
*/
|
|
90
90
|
stockTracked?: boolean | null;
|
|
91
|
+
/**
|
|
92
|
+
* Als Leistungsgutschein verkaufbar (Gutscheine Stufe 4b, Haken im
|
|
93
|
+
* Artikelstamm). Die Kachel „Leistungsgutschein“ bietet nur diese Artikel
|
|
94
|
+
* an; der Server verkauft einen anderen nicht (`voucher_service_not_allowed`).
|
|
95
|
+
* Optional wie `stockLocationIds`, der Leser setzt es immer: nur ein
|
|
96
|
+
* ausdrueckliches `true` gilt.
|
|
97
|
+
*/
|
|
98
|
+
serviceVoucher?: boolean;
|
|
91
99
|
}
|
|
92
100
|
/** Deckelt eine gewuenschte Menge an der Hoechstmenge des Artikels (null = keine Grenze). */
|
|
93
101
|
export declare function allowedQuantity(a: Pick<PosArticle, 'maxQuantity'>, wanted: number): number;
|
|
@@ -113,6 +121,7 @@ export interface PosArticlePayload {
|
|
|
113
121
|
ean?: string | null;
|
|
114
122
|
internalCode?: string | null;
|
|
115
123
|
stockTracked?: boolean | null;
|
|
124
|
+
serviceVoucher?: boolean | null;
|
|
116
125
|
}
|
|
117
126
|
export declare function fromPosArticlePayload(p: PosArticlePayload): PosArticle;
|
|
118
127
|
/**
|
package/dist/cjs/pos/artikel.js
CHANGED
|
@@ -15,10 +15,27 @@ export declare const VOUCHER_STATUSES: readonly VoucherStatus[];
|
|
|
15
15
|
/** Gueltigkeit eines Gutscheins; Daten als `YYYY-MM-DD` (Wiener Tag). Was der Server nicht nennt, fehlt. */
|
|
16
16
|
export interface VoucherValidity {
|
|
17
17
|
pattern: 'unlimited' | '1+3' | 'custom';
|
|
18
|
+
/**
|
|
19
|
+
* Gutschein einer Sorte „N Jahre einloesbar, danach 3 Jahre Rueckzahlung“:
|
|
20
|
+
* die Zahl N (1 bis 30); `pattern` ist dann `1+3` fuer jedes N. Fehlt bei
|
|
21
|
+
* Gutscheinen ohne Sorte und bei unbefristeten. Die Daten stehen trotzdem in
|
|
22
|
+
* `redeemableUntil` (+N) und `refundableUntil` (+N+3) und gelten.
|
|
23
|
+
*/
|
|
24
|
+
redeemableYears?: number;
|
|
18
25
|
redeemableUntil?: string;
|
|
19
26
|
refundableUntil?: string;
|
|
20
27
|
validUntil?: string;
|
|
21
28
|
}
|
|
29
|
+
/** Auszahlung eines Gutscheins bzw. einer Sorte: erlaubt oder nie (nur bei unbefristeter Gueltigkeit). */
|
|
30
|
+
export type VoucherPayout = 'allowed' | 'never';
|
|
31
|
+
/** Art einer Gutschein-Sorte: nur Wertgutscheine (Leistung und Aktion sind keine Sorte). */
|
|
32
|
+
export type VoucherTypeKind = 'multi_purpose' | 'single_purpose';
|
|
33
|
+
export declare const VOUCHER_PAYOUTS: readonly VoucherPayout[];
|
|
34
|
+
export declare const VOUCHER_TYPE_KINDS: readonly VoucherTypeKind[];
|
|
35
|
+
/** Betrag einer Sorte: frei an der Kasse eingegeben oder fest. */
|
|
36
|
+
export declare const VOUCHER_AMOUNT_MODES: readonly ('free' | 'fixed')[];
|
|
37
|
+
/** Gueltigkeit einer Sorte: unbefristet oder N Jahre (das Muster der Sorte, nicht das eines Gutscheins). */
|
|
38
|
+
export declare const VOUCHER_TYPE_VALIDITY_PATTERNS: readonly ('unlimited' | 'years')[];
|
|
22
39
|
/** Der Artikel eines Dienstleistungsgutscheins. */
|
|
23
40
|
export interface VoucherArticle {
|
|
24
41
|
id: string;
|
|
@@ -50,12 +67,92 @@ export interface VoucherCheck {
|
|
|
50
67
|
* inzwischen steuerpflichtigen Konto. Fehlt bei aelteren Servern.
|
|
51
68
|
*/
|
|
52
69
|
exempt?: boolean;
|
|
70
|
+
/** Name der Sorte, mit der der Gutschein verkauft wurde (beim Verkauf eingefroren); fehlt ohne Sorte. */
|
|
71
|
+
typeName?: string;
|
|
72
|
+
/**
|
|
73
|
+
* Auszahlung dieses Gutscheins (beim Verkauf eingefroren); fehlt ohne
|
|
74
|
+
* Sorte. Bei `never` lehnt der Server jede Auszahlung ab
|
|
75
|
+
* (`voucher_payout_not_allowed`); Einloesen geht unveraendert.
|
|
76
|
+
*/
|
|
77
|
+
payout?: VoucherPayout;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Etikett-Vorlage in der `/v3`-Form (Groesse, Layout, Drehung, Felder,
|
|
81
|
+
* Freitext). Das Paket zeichnet keine Etiketten: es reicht die Vorlage als
|
|
82
|
+
* Kopie durch, gezeichnet wird in der Kasse (druck-kit, Kassen-App). Weitere
|
|
83
|
+
* Schluessel eines neueren Servers bleiben erhalten.
|
|
84
|
+
*/
|
|
85
|
+
export interface VoucherLabelTemplate {
|
|
86
|
+
/** Etikettgroesse `BxH` in mm, z. B. `40x30`. */
|
|
87
|
+
size: string;
|
|
88
|
+
layout: string;
|
|
89
|
+
/** 0 oder 90 (Grad); fehlt = 0. */
|
|
90
|
+
rotation?: number;
|
|
91
|
+
fields?: Record<string, boolean>;
|
|
92
|
+
freeText?: string[];
|
|
93
|
+
[key: string]: unknown;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Gutschein-Sorte (Gutscheine Stufe 4b): eine Kachel im Reiter „Gutscheine“.
|
|
97
|
+
* Die Kasse bekommt nur verkaufbare Sorten (aktiv und gueltig), in
|
|
98
|
+
* Kachelfolge. Verkauft wird ein Wertgutschein nur ueber eine Sorte:
|
|
99
|
+
* `{ action: 'sell', type: kind, typeId: id, amountCents }` (bei `fixed` genau
|
|
100
|
+
* `amount.cents`); Art, Satz, Gueltigkeit und Auszahlung nimmt der Server aus
|
|
101
|
+
* der Sorte und friert sie am Gutschein ein.
|
|
102
|
+
*/
|
|
103
|
+
export interface PosVoucherType {
|
|
104
|
+
id: string;
|
|
105
|
+
name: string;
|
|
106
|
+
kind: VoucherTypeKind;
|
|
107
|
+
/** Satz in Basispunkten, nur bei Einzweck (> 0); Mehrzweck `null`. */
|
|
108
|
+
vatRateBp: number | null;
|
|
109
|
+
/** Betrag: frei (Zahlenfeld) oder fest (sofort in den Korb), Cent ganzzahlig. */
|
|
110
|
+
amount: {
|
|
111
|
+
mode: 'free';
|
|
112
|
+
} | {
|
|
113
|
+
mode: 'fixed';
|
|
114
|
+
cents: number;
|
|
115
|
+
};
|
|
116
|
+
/** Unbefristet oder N Jahre einloesbar, danach 3 Jahre Rueckzahlung (N 1 bis 30). */
|
|
117
|
+
validity: {
|
|
118
|
+
pattern: 'unlimited';
|
|
119
|
+
} | {
|
|
120
|
+
pattern: 'years';
|
|
121
|
+
years: number;
|
|
122
|
+
};
|
|
123
|
+
payout: VoucherPayout;
|
|
124
|
+
/** Wirksame Vorlage der Sorte (eigene, sonst die Standardvorlage); `null`, wenn die Antwort keine brauchbare traegt. */
|
|
125
|
+
label: VoucherLabelTemplate | null;
|
|
126
|
+
order: number;
|
|
127
|
+
active: boolean;
|
|
128
|
+
/** Verkaufte Gutscheine dieser Sorte (nur zur Anzeige). */
|
|
129
|
+
soldCount: number;
|
|
53
130
|
}
|
|
54
|
-
/**
|
|
131
|
+
/**
|
|
132
|
+
* Gutschein-Einstellungen der Kasse (Block `vouchers` aus `getKasseSettings`).
|
|
133
|
+
*
|
|
134
|
+
* Seit Gutscheine Stufe 4b verkauft eine Kasse ueber Sorten: Reiter und
|
|
135
|
+
* Kacheln zeigt sie mit `typeSale` (und dem Recht `voucherSell`), je Sorte aus
|
|
136
|
+
* `types` und die feste Kachel „Leistungsgutschein“ mit `serviceArticles`.
|
|
137
|
+
* `sale`, `valueVoucherType` und `vatRateBp` gelten nur Kassen vor 1.17; der
|
|
138
|
+
* Server schickt `sale` immer als `false`.
|
|
139
|
+
*
|
|
140
|
+
* Die vier neuen Felder sind optional, damit bestehende Literale von
|
|
141
|
+
* Verbrauchern weiter uebersetzen; der Leser ([posVoucherSettingsFromWire])
|
|
142
|
+
* setzt sie immer.
|
|
143
|
+
*/
|
|
55
144
|
export interface PosVoucherSettings {
|
|
56
145
|
sale: boolean;
|
|
57
146
|
valueVoucherType: 'multi_purpose' | 'single_purpose' | null;
|
|
58
147
|
vatRateBp: number | null;
|
|
148
|
+
/** Gutscheine verkaufen (Reiter „Gutscheine“): Schalter des Servers und mindestens eine Sorte oder ein Leistungsartikel. */
|
|
149
|
+
typeSale?: boolean;
|
|
150
|
+
/** Verkaufbare Sorten in Kachelfolge. */
|
|
151
|
+
types?: PosVoucherType[];
|
|
152
|
+
/** Es gibt aktive Artikel, die als Leistungsgutschein freigegeben sind (`PosArticle.serviceVoucher`). */
|
|
153
|
+
serviceArticles?: boolean;
|
|
154
|
+
/** Standardvorlage des Etiketts (Leistungsgutschein, Notausgang); `null` ohne brauchbare Vorlage. */
|
|
155
|
+
labelDefault?: VoucherLabelTemplate | null;
|
|
59
156
|
}
|
|
60
157
|
/** Ohne Block `vouchers` (alter Server, Konto ohne Schalter): Verkaufen ist aus. */
|
|
61
158
|
export declare const VOUCHER_SETTINGS_DEFAULTS: Readonly<PosVoucherSettings>;
|
|
@@ -67,7 +164,15 @@ export declare const VOUCHER_SETTINGS_DEFAULTS: Readonly<PosVoucherSettings>;
|
|
|
67
164
|
* `multi_purpose`/`single_purpose`/`null`, der Satz eine ganze Zahl >= 0 oder
|
|
68
165
|
* `null`; Mehrzweck traegt keinen Satz, Einzweck braucht einen, und ein
|
|
69
166
|
* eingeschalteter Verkauf braucht eine Art. Ein ausgeschalteter Verkauf darf
|
|
70
|
-
* eine Art behalten.
|
|
167
|
+
* eine Art behalten. `typeSale` und `serviceArticles` sind Wahrheitswerte,
|
|
168
|
+
* `types` eine Liste (fehlen sie, antwortet ein aelterer Server: aus, leer).
|
|
169
|
+
*
|
|
170
|
+
* Sorten (Gutscheine Stufe 4b) liest der Leser einzeln: eine unstimmige Sorte
|
|
171
|
+
* faellt weg ([sorteVomDraht]), die anderen bleiben; ist danach weder eine
|
|
172
|
+
* Sorte noch ein Leistungsartikel da, ist `typeSale` aus (kein leerer Reiter).
|
|
173
|
+
* Eine unbrauchbare Etikett-Vorlage schliesst nichts: sie wird `null`, die
|
|
174
|
+
* Kasse druckt dann ihren Standard (ein Verkauf scheitert nie an der Vorlage).
|
|
175
|
+
* Das alte Feld `label` (Kassen vor 1.17, Ruling R3) liest das Paket nicht.
|
|
71
176
|
*/
|
|
72
177
|
export declare function posVoucherSettingsFromWire(block: unknown): PosVoucherSettings;
|
|
73
178
|
/**
|