@kreiseck/kasseneck-api 1.11.1 → 1.13.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 +21 -0
- package/README.md +2 -1
- package/dist/cjs/client/aufrufe.d.ts +4 -4
- package/dist/cjs/client/aufrufe.js +15 -0
- package/dist/cjs/client/receipts.d.ts +5 -0
- package/dist/cjs/client/receipts.js +65 -6
- package/dist/cjs/enums/voucher-action.d.ts +2 -0
- package/dist/cjs/enums/voucher-action.js +2 -0
- package/dist/cjs/enums/voucher-type.d.ts +10 -0
- package/dist/cjs/enums/voucher-type.js +10 -0
- package/dist/cjs/index.d.ts +3 -3
- package/dist/cjs/index.js +8 -3
- package/dist/cjs/models/index.d.ts +2 -2
- package/dist/cjs/models/index.js +6 -2
- package/dist/cjs/models/receipt-errors.d.ts +1 -1
- package/dist/cjs/models/receipt-errors.js +2 -0
- package/dist/cjs/models/receipt-item.d.ts +11 -3
- package/dist/cjs/models/receipt-item.js +22 -1
- package/dist/cjs/models/receipt.d.ts +13 -1
- package/dist/cjs/models/receipt.js +18 -2
- package/dist/cjs/models/voucher.d.ts +57 -4
- package/dist/cjs/models/voucher.js +111 -3
- package/dist/cjs/partner/fehler.d.ts +1 -1
- package/dist/cjs/partner/fehler.js +2 -0
- package/dist/cjs/partner/index.d.ts +1 -1
- package/dist/cjs/partner/typen.d.ts +7 -1
- package/dist/cjs/partner/typen.js +3 -0
- package/dist/cjs/pos/client.d.ts +2 -1
- package/dist/cjs/pos/client.js +3 -1
- package/dist/cjs/pos/gutschein.d.ts +90 -0
- package/dist/cjs/pos/gutschein.js +164 -0
- package/dist/cjs/pos/index.d.ts +3 -2
- package/dist/cjs/pos/index.js +13 -2
- package/dist/cjs/pos/settings.d.ts +3 -0
- package/dist/cjs/pos/settings.js +12 -10
- package/dist/cjs/pos/texte.d.ts +229 -0
- package/dist/cjs/pos/texte.js +96 -1
- package/dist/cjs/react/index.js +8 -2
- package/dist/cjs/receipt/due.d.ts +83 -2
- package/dist/cjs/receipt/due.js +202 -36
- package/dist/cjs/receipt/grid.js +13 -1
- package/dist/cjs/receipt/gutschein-plan.d.ts +104 -0
- package/dist/cjs/receipt/gutschein-plan.js +360 -0
- package/dist/cjs/receipt/index.d.ts +1 -1
- package/dist/cjs/receipt/index.js +3 -0
- package/dist/cjs/receipt/layout.js +175 -8
- package/dist/cjs/register/pairing.d.ts +21 -1
- package/dist/cjs/register/pairing.js +17 -0
- package/dist/cjs/stored/bon-layout.d.ts +8 -0
- package/dist/cjs/stored/bon-layout.js +23 -0
- package/dist/cjs/stored/draht.d.ts +3 -1
- package/dist/cjs/stored/draht.js +53 -6
- package/dist/cjs/stored/einstellungen.js +2 -1
- package/dist/cjs/stored/gutscheine.d.ts +3 -0
- package/dist/cjs/stored/gutscheine.js +60 -0
- package/dist/cjs/stored/index.js +2 -17
- package/dist/cjs/stored/vokabular.d.ts +6 -4
- package/dist/cjs/stored/vokabular.js +48 -2
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/client/aufrufe.d.ts +4 -4
- package/dist/esm/client/aufrufe.js +15 -0
- package/dist/esm/client/receipts.d.ts +5 -0
- package/dist/esm/client/receipts.js +66 -8
- package/dist/esm/enums/voucher-action.d.ts +2 -0
- package/dist/esm/enums/voucher-action.js +2 -0
- package/dist/esm/enums/voucher-type.d.ts +10 -0
- package/dist/esm/enums/voucher-type.js +10 -0
- package/dist/esm/index.d.ts +3 -3
- package/dist/esm/index.js +3 -3
- package/dist/esm/models/index.d.ts +2 -2
- package/dist/esm/models/index.js +2 -2
- package/dist/esm/models/receipt-errors.d.ts +1 -1
- package/dist/esm/models/receipt-errors.js +2 -0
- package/dist/esm/models/receipt-item.d.ts +11 -3
- package/dist/esm/models/receipt-item.js +20 -1
- package/dist/esm/models/receipt.d.ts +13 -1
- package/dist/esm/models/receipt.js +18 -2
- package/dist/esm/models/voucher.d.ts +57 -4
- package/dist/esm/models/voucher.js +108 -3
- package/dist/esm/partner/fehler.d.ts +1 -1
- package/dist/esm/partner/fehler.js +2 -0
- package/dist/esm/partner/index.d.ts +1 -1
- package/dist/esm/partner/typen.d.ts +7 -1
- package/dist/esm/partner/typen.js +3 -0
- package/dist/esm/pos/client.d.ts +2 -1
- package/dist/esm/pos/client.js +3 -1
- package/dist/esm/pos/gutschein.d.ts +90 -0
- package/dist/esm/pos/gutschein.js +158 -0
- package/dist/esm/pos/index.d.ts +3 -2
- package/dist/esm/pos/index.js +4 -2
- package/dist/esm/pos/settings.d.ts +3 -0
- package/dist/esm/pos/settings.js +2 -0
- package/dist/esm/pos/texte.d.ts +229 -0
- package/dist/esm/pos/texte.js +94 -0
- package/dist/esm/react/index.js +8 -2
- package/dist/esm/receipt/due.d.ts +83 -2
- package/dist/esm/receipt/due.js +198 -34
- package/dist/esm/receipt/grid.js +13 -1
- package/dist/esm/receipt/gutschein-plan.d.ts +104 -0
- package/dist/esm/receipt/gutschein-plan.js +352 -0
- package/dist/esm/receipt/index.d.ts +1 -1
- package/dist/esm/receipt/index.js +1 -1
- package/dist/esm/receipt/layout.js +175 -8
- package/dist/esm/register/pairing.d.ts +21 -1
- package/dist/esm/register/pairing.js +16 -0
- package/dist/esm/stored/bon-layout.d.ts +8 -0
- package/dist/esm/stored/bon-layout.js +20 -0
- package/dist/esm/stored/draht.d.ts +3 -1
- package/dist/esm/stored/draht.js +52 -6
- package/dist/esm/stored/einstellungen.js +3 -2
- package/dist/esm/stored/gutscheine.d.ts +3 -0
- package/dist/esm/stored/gutscheine.js +56 -0
- package/dist/esm/stored/index.js +2 -17
- package/dist/esm/stored/vokabular.d.ts +6 -4
- package/dist/esm/stored/vokabular.js +48 -2
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/fixtures/expected/voucher-cancellation.grid32.txt +30 -0
- package/fixtures/expected/voucher-cancellation.grid48.txt +29 -0
- package/fixtures/expected/voucher-cancellation.lines.json +252 -0
- package/fixtures/expected/voucher-cancellation.sheet32.json +206 -0
- package/fixtures/expected/voucher-cancellation.sheet48.json +200 -0
- package/fixtures/expected/voucher-multi-purpose-redeem.grid32.txt +25 -0
- package/fixtures/expected/voucher-multi-purpose-redeem.grid48.txt +25 -0
- package/fixtures/expected/voucher-multi-purpose-redeem.lines.json +259 -0
- package/fixtures/expected/voucher-multi-purpose-redeem.sheet32.json +176 -0
- package/fixtures/expected/voucher-multi-purpose-redeem.sheet48.json +176 -0
- package/fixtures/expected/voucher-multi-purpose-sale.grid32.txt +24 -0
- package/fixtures/expected/voucher-multi-purpose-sale.grid48.txt +23 -0
- package/fixtures/expected/voucher-multi-purpose-sale.lines.json +216 -0
- package/fixtures/expected/voucher-multi-purpose-sale.sheet32.json +170 -0
- package/fixtures/expected/voucher-multi-purpose-sale.sheet48.json +164 -0
- package/fixtures/expected/voucher-payout.grid32.txt +23 -0
- package/fixtures/expected/voucher-payout.grid48.txt +22 -0
- package/fixtures/expected/voucher-payout.lines.json +216 -0
- package/fixtures/expected/voucher-payout.sheet32.json +164 -0
- package/fixtures/expected/voucher-payout.sheet48.json +158 -0
- package/fixtures/expected/voucher-service-redeem.grid32.txt +26 -0
- package/fixtures/expected/voucher-service-redeem.grid48.txt +25 -0
- package/fixtures/expected/voucher-service-redeem.lines.json +261 -0
- package/fixtures/expected/voucher-service-redeem.sheet32.json +182 -0
- package/fixtures/expected/voucher-service-redeem.sheet48.json +176 -0
- package/fixtures/expected/voucher-single-purpose-redeem-exempt.grid32.txt +30 -0
- package/fixtures/expected/voucher-single-purpose-redeem-exempt.grid48.txt +29 -0
- package/fixtures/expected/voucher-single-purpose-redeem-exempt.lines.json +331 -0
- package/fixtures/expected/voucher-single-purpose-redeem-exempt.sheet32.json +206 -0
- package/fixtures/expected/voucher-single-purpose-redeem-exempt.sheet48.json +200 -0
- package/fixtures/expected/voucher-single-purpose-redeem.grid32.txt +25 -0
- package/fixtures/expected/voucher-single-purpose-redeem.grid48.txt +24 -0
- package/fixtures/expected/voucher-single-purpose-redeem.lines.json +246 -0
- package/fixtures/expected/voucher-single-purpose-redeem.sheet32.json +176 -0
- package/fixtures/expected/voucher-single-purpose-redeem.sheet48.json +170 -0
- package/fixtures/expected/voucher-single-purpose-sale.grid32.txt +26 -0
- package/fixtures/expected/voucher-single-purpose-sale.grid48.txt +24 -0
- package/fixtures/expected/voucher-single-purpose-sale.lines.json +225 -0
- package/fixtures/expected/voucher-single-purpose-sale.sheet32.json +182 -0
- package/fixtures/expected/voucher-single-purpose-sale.sheet48.json +170 -0
- 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/manifest.json +64 -0
- package/fixtures/pos-texts.json +257 -1
- package/fixtures/receipt-due-generated.json +1 -1
- package/fixtures/receipt-due-voucher-generated.json +494 -0
- package/fixtures/receipts/voucher-cancellation.json +76 -0
- package/fixtures/receipts/voucher-multi-purpose-redeem.json +62 -0
- package/fixtures/receipts/voucher-multi-purpose-sale.json +63 -0
- package/fixtures/receipts/voucher-payout.json +65 -0
- package/fixtures/receipts/voucher-service-redeem.json +82 -0
- package/fixtures/receipts/voucher-single-purpose-redeem-exempt.json +86 -0
- package/fixtures/receipts/voucher-single-purpose-redeem.json +71 -0
- package/fixtures/receipts/voucher-single-purpose-sale.json +88 -0
- package/fixtures/surface.json +35 -5
- package/fixtures/v3/antworten/belege.json +3405 -3
- package/fixtures/v3/antworten/belegmail.json +5 -2
- package/fixtures/v3/antworten/kasse-belege.json +3423 -3
- package/fixtures/v3/antworten/kasse.json +621 -14
- package/fixtures/v3/antworten/lager.json +1 -1
- package/fixtures/v3/antworten/rechnungen.json +5 -2
- package/fixtures/v3/antworten/storno.json +214 -3
- package/fixtures/v3/stored/belege.json +5 -2
- package/fixtures/v3/stored/kasse.json +225 -4
- package/fixtures/v3/stored/rechnungen.json +5 -2
- package/fixtures/v3/v3-vokabular.json +1375 -23
- package/fixtures/v3/zahlbetrag-faelle.json +293 -3
- package/package.json +4 -1
|
@@ -9,6 +9,18 @@ export function isTipItem(item) {
|
|
|
9
9
|
export function isDiscountItem(item) {
|
|
10
10
|
return item != null && item.kind === 'discount';
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Gutschein-Position (Server, neue Gutscheinform)? `voucher` ist eine
|
|
14
|
+
* Einloesung oder ein Verkauf mit Umsatzsteuer-Wirkung, siehe
|
|
15
|
+
* [isVoucherFloatItem] fuer den durchlaufenden Posten.
|
|
16
|
+
*/
|
|
17
|
+
export function isVoucherItem(item) {
|
|
18
|
+
return item != null && item.kind === 'voucher';
|
|
19
|
+
}
|
|
20
|
+
/** Gutschein-Position als durchlaufender Posten (Mehrzweck: Verkauf, Auszahlung)? */
|
|
21
|
+
export function isVoucherFloatItem(item) {
|
|
22
|
+
return item != null && item.kind === 'voucher_float';
|
|
23
|
+
}
|
|
12
24
|
export function toReceiptItemPayload(item) {
|
|
13
25
|
// Schreibpfad bleibt streng: ein unaufgeloester (unbekannter) Steuersatz
|
|
14
26
|
// darf nicht unbesehen wieder hinausgehen.
|
|
@@ -37,6 +49,11 @@ export function toReceiptItemPayload(item) {
|
|
|
37
49
|
// am Bon wieder als gewoehnliche Warenzeile mit "1 x" an.
|
|
38
50
|
if (item.kind === 'discount')
|
|
39
51
|
nutzlast.kind = 'discount';
|
|
52
|
+
// Gutschein-Positionen (vom Server) reisen mit: der Cache der Kasse schreibt
|
|
53
|
+
// gelesene Belege wieder, und ein Wunsch an den Server traegt sie nie
|
|
54
|
+
// (createReceipt weist sie als voucher_invalid ab).
|
|
55
|
+
if (item.kind === 'voucher' || item.kind === 'voucher_float')
|
|
56
|
+
nutzlast.kind = item.kind;
|
|
40
57
|
// Artikel-Verweis reist mit (Erloesgruppen im Bericht); leere Werte nicht.
|
|
41
58
|
if (item.articleId != null && item.articleId !== '')
|
|
42
59
|
nutzlast.articleId = item.articleId;
|
|
@@ -81,7 +98,9 @@ export function fromReceiptItemPayload(payload) {
|
|
|
81
98
|
}
|
|
82
99
|
: payload.kind === 'discount'
|
|
83
100
|
? { kind: 'discount' }
|
|
84
|
-
:
|
|
101
|
+
: payload.kind === 'voucher' || payload.kind === 'voucher_float'
|
|
102
|
+
? { kind: payload.kind }
|
|
103
|
+
: {}),
|
|
85
104
|
// Artikel-Verweis erhalten (Storno-Spiegelung schreibt ihn wieder mit).
|
|
86
105
|
...(typeof payload.articleId === 'string' && payload.articleId !== '' ? { articleId: payload.articleId } : {}),
|
|
87
106
|
// Lager: Bezug und Rueckgabe-Wahl einer Storno-Zeile (nur gelesen; ein
|
|
@@ -162,10 +162,22 @@ export declare function receiptValueVoucherSign(receipt: Receipt): 1 | -1;
|
|
|
162
162
|
* mindert nichts: den Rabatt nimmt der Server dort ueber Ausgleichspositionen
|
|
163
163
|
* (`kind: 'discount'`) zurueck, und belegToepfe verteilt einen Promo-Eintrag
|
|
164
164
|
* nur auf eine positive Topfsumme, die ein Storno nie hat.
|
|
165
|
+
*
|
|
166
|
+
* Gutscheine der neuen Form (Spec 2026-10-14): ihr Betrag steht als Position
|
|
167
|
+
* (`kind: 'voucher'` bei Einzweck/Leistung, `'voucher_float'` im 0-%-Topf) und
|
|
168
|
+
* zaehlt hier schon mit den Positionen. Ein Eintrag mit `zeroRateBucket`
|
|
169
|
+
* (Server: `imNullTopf`, Mehrzweck-Verkauf ab dem Stichtag, Auszahlung) zaehlt
|
|
170
|
+
* darum nicht noch einmal -- sonst stuende der Betrag doppelt am Bon
|
|
171
|
+
* (Vorfall 16.10.2026: Verkauf ueber 30 € mit „Gesamt 60,00“). Eintraege der
|
|
172
|
+
* Arten `single_purpose`/`service` tragen keinen Fluss (wie
|
|
173
|
+
* gutschein-beleg.zahlbetrag, das nur `value`/`promo` an den Fluss gibt).
|
|
165
174
|
*/
|
|
166
175
|
export declare function receiptSubSumCents(receipt: Receipt): number;
|
|
167
176
|
/**
|
|
168
177
|
* Gesamtsumme in **Cent** — Zwischensumme minus eingeloeste Wertgutscheine
|
|
169
|
-
* (am Storno-Beleg plus, siehe [receiptValueVoucherSign]).
|
|
178
|
+
* (am Storno-Beleg plus, siehe [receiptValueVoucherSign]). Zwilling von
|
|
179
|
+
* zahlungen-core.wertgutscheinFlussCents: eine Auszahlung (`payout`) eines
|
|
180
|
+
* Wertgutscheins ohne `zeroRateBucket` mindert wie eine Einloesung; mit
|
|
181
|
+
* `zeroRateBucket` steht sie als Position und zaehlt nur dort.
|
|
170
182
|
*/
|
|
171
183
|
export declare function receiptSumCents(receipt: Receipt): number;
|
|
@@ -149,11 +149,22 @@ export function receiptValueVoucherSign(receipt) {
|
|
|
149
149
|
* mindert nichts: den Rabatt nimmt der Server dort ueber Ausgleichspositionen
|
|
150
150
|
* (`kind: 'discount'`) zurueck, und belegToepfe verteilt einen Promo-Eintrag
|
|
151
151
|
* nur auf eine positive Topfsumme, die ein Storno nie hat.
|
|
152
|
+
*
|
|
153
|
+
* Gutscheine der neuen Form (Spec 2026-10-14): ihr Betrag steht als Position
|
|
154
|
+
* (`kind: 'voucher'` bei Einzweck/Leistung, `'voucher_float'` im 0-%-Topf) und
|
|
155
|
+
* zaehlt hier schon mit den Positionen. Ein Eintrag mit `zeroRateBucket`
|
|
156
|
+
* (Server: `imNullTopf`, Mehrzweck-Verkauf ab dem Stichtag, Auszahlung) zaehlt
|
|
157
|
+
* darum nicht noch einmal -- sonst stuende der Betrag doppelt am Bon
|
|
158
|
+
* (Vorfall 16.10.2026: Verkauf ueber 30 € mit „Gesamt 60,00“). Eintraege der
|
|
159
|
+
* Arten `single_purpose`/`service` tragen keinen Fluss (wie
|
|
160
|
+
* gutschein-beleg.zahlbetrag, das nur `value`/`promo` an den Fluss gibt).
|
|
152
161
|
*/
|
|
153
162
|
export function receiptSubSumCents(receipt) {
|
|
154
163
|
const vz = receiptValueVoucherSign(receipt);
|
|
155
164
|
let cents = receipt.items.reduce((acc, item) => acc + receiptItemTotalCents(item), 0);
|
|
156
165
|
for (const voucher of receipt.vouchers) {
|
|
166
|
+
if (voucher.zeroRateBucket === true)
|
|
167
|
+
continue;
|
|
157
168
|
if (vz === 1 && voucher.action === VoucherAction.redeem && voucher.type === VoucherType.promo) {
|
|
158
169
|
cents -= voucher.valueCents ?? 0;
|
|
159
170
|
}
|
|
@@ -165,13 +176,18 @@ export function receiptSubSumCents(receipt) {
|
|
|
165
176
|
}
|
|
166
177
|
/**
|
|
167
178
|
* Gesamtsumme in **Cent** — Zwischensumme minus eingeloeste Wertgutscheine
|
|
168
|
-
* (am Storno-Beleg plus, siehe [receiptValueVoucherSign]).
|
|
179
|
+
* (am Storno-Beleg plus, siehe [receiptValueVoucherSign]). Zwilling von
|
|
180
|
+
* zahlungen-core.wertgutscheinFlussCents: eine Auszahlung (`payout`) eines
|
|
181
|
+
* Wertgutscheins ohne `zeroRateBucket` mindert wie eine Einloesung; mit
|
|
182
|
+
* `zeroRateBucket` steht sie als Position und zaehlt nur dort.
|
|
169
183
|
*/
|
|
170
184
|
export function receiptSumCents(receipt) {
|
|
171
185
|
const vz = receiptValueVoucherSign(receipt);
|
|
172
186
|
let cents = receiptSubSumCents(receipt);
|
|
173
187
|
for (const voucher of receipt.vouchers) {
|
|
174
|
-
if (voucher.
|
|
188
|
+
if (voucher.zeroRateBucket === true || voucher.type !== VoucherType.value)
|
|
189
|
+
continue;
|
|
190
|
+
if (voucher.action === VoucherAction.redeem || voucher.action === VoucherAction.payout) {
|
|
175
191
|
cents -= vz * (voucher.valueCents ?? 0);
|
|
176
192
|
}
|
|
177
193
|
}
|
|
@@ -16,11 +16,41 @@ export interface Voucher {
|
|
|
16
16
|
action: VoucherAction | string;
|
|
17
17
|
type: VoucherType | string;
|
|
18
18
|
valueCents?: number;
|
|
19
|
+
/** Neue Form: Betrag in Cent (Verkauf, Einloesung, Auszahlung). */
|
|
20
|
+
amountCents?: number;
|
|
21
|
+
/** Neue Form, Leistungsgutschein: verkaufter Artikel. */
|
|
22
|
+
articleId?: string;
|
|
23
|
+
/** Neue Form, Leistungsgutschein: Menge (Verkauf) bzw. eingeloeste Menge. */
|
|
24
|
+
quantity?: number;
|
|
25
|
+
/** Neue Form, Leistungsgutschein einloesen: Indizes der Belegpositionen. */
|
|
26
|
+
positions?: number[];
|
|
27
|
+
/** Neue Form, Auszahlung: Grund, 1 bis 200 Zeichen. */
|
|
28
|
+
reason?: string;
|
|
29
|
+
voucherType?: string;
|
|
30
|
+
voucherId?: string;
|
|
31
|
+
/** Letzte vier Zeichen des Codes; der Klartext steht nie am Beleg. */
|
|
32
|
+
codeSuffix?: string;
|
|
33
|
+
vatRateBp?: number;
|
|
34
|
+
article?: VoucherArticle;
|
|
35
|
+
balanceAfterCents?: number;
|
|
36
|
+
remainingQuantityAfter?: number;
|
|
37
|
+
taxedWith?: string;
|
|
38
|
+
exempt?: boolean;
|
|
39
|
+
zeroRateBucket?: boolean;
|
|
40
|
+
}
|
|
41
|
+
/** Artikel eines Leistungsgutscheins, wie der Server ihn am Beleg festhaelt. */
|
|
42
|
+
export interface VoucherArticle {
|
|
43
|
+
id: string;
|
|
44
|
+
name: string;
|
|
45
|
+
vatRateBp: number;
|
|
46
|
+
priceCents: number;
|
|
19
47
|
}
|
|
20
48
|
/**
|
|
21
|
-
* Nutzlast eines Gutscheins.
|
|
22
|
-
*
|
|
23
|
-
*
|
|
49
|
+
* Nutzlast eines Gutscheins. Altform: nur `valueCents` (ganze Cent); `value`
|
|
50
|
+
* (Euro) kommt nur beim Lesen vor: der Server legt es in seinen Antworten
|
|
51
|
+
* daneben, gelesen wird es nur, wenn `valueCents` fehlt. Neue Form: roh mit
|
|
52
|
+
* `amountCents` und den weiteren Feldern; gesetzte Feldern gehen hinaus,
|
|
53
|
+
* fehlende fehlen (kein `valueCents: null` an der neuen Form).
|
|
24
54
|
* `name` und `code` gehen nur hinaus, wenn sie gesetzt sind.
|
|
25
55
|
*/
|
|
26
56
|
export interface VoucherPayload {
|
|
@@ -29,8 +59,31 @@ export interface VoucherPayload {
|
|
|
29
59
|
action: string;
|
|
30
60
|
type: string;
|
|
31
61
|
value?: number | null;
|
|
32
|
-
valueCents
|
|
62
|
+
valueCents?: number | null;
|
|
63
|
+
amountCents?: number;
|
|
64
|
+
articleId?: string;
|
|
65
|
+
quantity?: number;
|
|
66
|
+
positions?: number[];
|
|
67
|
+
reason?: string;
|
|
68
|
+
voucherType?: string;
|
|
69
|
+
voucherId?: string;
|
|
70
|
+
codeSuffix?: string;
|
|
71
|
+
vatRateBp?: number;
|
|
72
|
+
article?: VoucherArticle;
|
|
73
|
+
balanceAfterCents?: number;
|
|
74
|
+
remainingQuantityAfter?: number;
|
|
75
|
+
taxedWith?: string;
|
|
76
|
+
exempt?: boolean;
|
|
77
|
+
zeroRateBucket?: boolean;
|
|
33
78
|
}
|
|
79
|
+
/** Arten der neuen Gutscheinform (die Altwerte sind `value` und `promo`). */
|
|
80
|
+
export declare const NEUE_GUTSCHEINARTEN: readonly string[];
|
|
81
|
+
/** Gehoert der Gutschein zur neuen Form (Art oder Aktion `payout`)? */
|
|
82
|
+
export declare function isNewFormVoucher(voucher: Pick<Voucher, 'type' | 'action'>): boolean;
|
|
83
|
+
/** Felder, die nur der Server setzt; an einem Wunsch sind sie `voucher_invalid`. */
|
|
84
|
+
export declare const GUTSCHEIN_SERVERFELDER: readonly ["voucherId", "codeSuffix", "zeroRateBucket", "voucherType"];
|
|
85
|
+
/** Welche Serverfelder tragt der Gutschein (leere Liste = keines)? */
|
|
86
|
+
export declare function voucherServerFields(voucher: Voucher): string[];
|
|
34
87
|
export declare function toVoucherPayload(voucher: Voucher): VoucherPayload;
|
|
35
88
|
/**
|
|
36
89
|
* Ist der Gutschein an das Backend sendbar? Zwilling von `KeckVoucher.isValid`
|
|
@@ -1,13 +1,46 @@
|
|
|
1
1
|
import { VoucherAction, VoucherType } from '../enums/index.js';
|
|
2
2
|
import { euroToCents } from '../money.js';
|
|
3
3
|
import { readEnumKey, requireEnumKey } from './enum-payload.js';
|
|
4
|
+
/** Arten der neuen Gutscheinform (die Altwerte sind `value` und `promo`). */
|
|
5
|
+
export const NEUE_GUTSCHEINARTEN = [
|
|
6
|
+
VoucherType.multi_purpose,
|
|
7
|
+
VoucherType.single_purpose,
|
|
8
|
+
VoucherType.service,
|
|
9
|
+
VoucherType.promotion,
|
|
10
|
+
];
|
|
11
|
+
/** Gehoert der Gutschein zur neuen Form (Art oder Aktion `payout`)? */
|
|
12
|
+
export function isNewFormVoucher(voucher) {
|
|
13
|
+
return NEUE_GUTSCHEINARTEN.includes(voucher.type) || voucher.action === VoucherAction.payout;
|
|
14
|
+
}
|
|
15
|
+
/** Felder, die nur der Server setzt; an einem Wunsch sind sie `voucher_invalid`. */
|
|
16
|
+
export const GUTSCHEIN_SERVERFELDER = ['voucherId', 'codeSuffix', 'zeroRateBucket', 'voucherType'];
|
|
17
|
+
/** Welche Serverfelder tragt der Gutschein (leere Liste = keines)? */
|
|
18
|
+
export function voucherServerFields(voucher) {
|
|
19
|
+
return GUTSCHEIN_SERVERFELDER.filter((feld) => voucher[feld] != null);
|
|
20
|
+
}
|
|
21
|
+
const NEUE_FELDER = [
|
|
22
|
+
'amountCents', 'articleId', 'quantity', 'positions', 'reason', 'voucherType', 'voucherId', 'codeSuffix',
|
|
23
|
+
'vatRateBp', 'article', 'balanceAfterCents', 'remainingQuantityAfter', 'taxedWith', 'exempt', 'zeroRateBucket',
|
|
24
|
+
];
|
|
4
25
|
export function toVoucherPayload(voucher) {
|
|
26
|
+
const action = requireEnumKey(VoucherAction, voucher.action, 'Gutschein-Aktion');
|
|
27
|
+
const type = requireEnumKey(VoucherType, voucher.type, 'Gutscheinart');
|
|
28
|
+
// Felder der neuen Form gehen roh hinaus, soweit gesetzt (auch an einem
|
|
29
|
+
// gelesenen Altbeleg: dort fehlen sie, die Nutzlast bleibt byte-gleich).
|
|
30
|
+
const roh = voucher;
|
|
31
|
+
const neu = {};
|
|
32
|
+
for (const feld of NEUE_FELDER)
|
|
33
|
+
if (roh[feld] != null)
|
|
34
|
+
neu[feld] = roh[feld];
|
|
5
35
|
return {
|
|
6
|
-
action
|
|
7
|
-
type
|
|
8
|
-
|
|
36
|
+
action,
|
|
37
|
+
type,
|
|
38
|
+
// Die neue Form kennt kein `valueCents`; nur ein gelesener Eintrag (die
|
|
39
|
+
// Auszahlung steht beim Server als Wert mit Cent) traegt es weiter.
|
|
40
|
+
...(isNewFormVoucher(voucher) && voucher.valueCents == null ? {} : { valueCents: voucher.valueCents ?? null }),
|
|
9
41
|
...(voucher.code != null ? { code: voucher.code } : {}),
|
|
10
42
|
...(voucher.name != null ? { name: voucher.name } : {}),
|
|
43
|
+
...neu,
|
|
11
44
|
};
|
|
12
45
|
}
|
|
13
46
|
/**
|
|
@@ -17,6 +50,8 @@ export function toVoucherPayload(voucher) {
|
|
|
17
50
|
* gesetzter Wert muss positiv sein.
|
|
18
51
|
*/
|
|
19
52
|
export function voucherIsValid(voucher) {
|
|
53
|
+
if (isNewFormVoucher(voucher))
|
|
54
|
+
return newFormVoucherIsValid(voucher);
|
|
20
55
|
if (voucher.type === VoucherType.value && voucher.valueCents == null) {
|
|
21
56
|
return false;
|
|
22
57
|
}
|
|
@@ -58,5 +93,75 @@ export function fromVoucherPayload(payload) {
|
|
|
58
93
|
action: readEnumKey(VoucherAction, payload.action),
|
|
59
94
|
type: readEnumKey(VoucherType, payload.type),
|
|
60
95
|
valueCents,
|
|
96
|
+
...lesenNeu(payload),
|
|
61
97
|
};
|
|
62
98
|
}
|
|
99
|
+
/** Felder der neuen Form beim Lesen: nur was dasteht (Altbelege bleiben schlank). */
|
|
100
|
+
function lesenNeu(payload) {
|
|
101
|
+
const roh = payload;
|
|
102
|
+
const neu = {};
|
|
103
|
+
for (const feld of NEUE_FELDER)
|
|
104
|
+
if (roh[feld] != null)
|
|
105
|
+
neu[feld] = roh[feld];
|
|
106
|
+
return neu;
|
|
107
|
+
}
|
|
108
|
+
/** Grenzen wie der Server (gutschein-beleg): Betrag 1 bis 1.000.000 Cent, Menge 1 bis 100. */
|
|
109
|
+
const MAX_BETRAG_CENTS = 1_000_000;
|
|
110
|
+
const MAX_STUECK = 100;
|
|
111
|
+
const MAX_GRUND = 200;
|
|
112
|
+
const istCent = (n) => typeof n === 'number' && Number.isInteger(n) && n >= 1 && n <= MAX_BETRAG_CENTS;
|
|
113
|
+
const istMenge = (n) => typeof n === 'number' && Number.isInteger(n) && n >= 1 && n <= MAX_STUECK;
|
|
114
|
+
const hatText = (t) => typeof t === 'string' && t.trim().length > 0;
|
|
115
|
+
/**
|
|
116
|
+
* Wunsch der neuen Form sendbar? Bildet die Regeln des Servers ab: Serverfelder
|
|
117
|
+
* nie, Betrag/Menge ganz und positiv, Code bei Einloesung und Auszahlung,
|
|
118
|
+
* Auszahlung nur Mehrzweck/Einzweck mit Grund (1 bis 200 Zeichen), Aktion nur
|
|
119
|
+
* einloesbar, Leistung braucht Artikel und Menge (Verkauf) bzw. Positionen
|
|
120
|
+
* (Einloesung). Felder, die zu einer anderen Aktion/Art gehoeren, sind
|
|
121
|
+
* ebenfalls nicht erlaubt (der Server wiese sie ab).
|
|
122
|
+
*/
|
|
123
|
+
function newFormVoucherIsValid(v) {
|
|
124
|
+
if (voucherServerFields(v).length > 0)
|
|
125
|
+
return false;
|
|
126
|
+
const r = v;
|
|
127
|
+
for (const feld of ['vatRateBp', 'article', 'balanceAfterCents', 'remainingQuantityAfter', 'taxedWith', 'exempt']) {
|
|
128
|
+
if (r[feld] != null)
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
if (v.valueCents != null)
|
|
132
|
+
return false;
|
|
133
|
+
const allein = v.type === VoucherType.multi_purpose || v.type === VoucherType.single_purpose;
|
|
134
|
+
if (v.action === VoucherAction.payout) {
|
|
135
|
+
return allein && hatText(v.code) && istCent(v.amountCents) && hatText(v.reason) && v.reason.trim().length <= MAX_GRUND
|
|
136
|
+
&& v.articleId == null && v.quantity == null && v.positions == null;
|
|
137
|
+
}
|
|
138
|
+
if (v.reason != null)
|
|
139
|
+
return false;
|
|
140
|
+
if (allein) {
|
|
141
|
+
if (v.articleId != null || v.quantity != null || v.positions != null)
|
|
142
|
+
return false;
|
|
143
|
+
if (v.action === VoucherAction.sell)
|
|
144
|
+
return istCent(v.amountCents);
|
|
145
|
+
if (v.action === VoucherAction.redeem)
|
|
146
|
+
return hatText(v.code) && istCent(v.amountCents);
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
if (v.type === VoucherType.service) {
|
|
150
|
+
if (v.amountCents != null)
|
|
151
|
+
return false;
|
|
152
|
+
if (v.action === VoucherAction.sell) {
|
|
153
|
+
return hatText(v.articleId) && istMenge(v.quantity) && v.positions == null;
|
|
154
|
+
}
|
|
155
|
+
if (v.action === VoucherAction.redeem) {
|
|
156
|
+
return hatText(v.code) && Array.isArray(v.positions) && v.positions.length > 0
|
|
157
|
+
&& v.positions.every((i) => Number.isInteger(i) && i >= 0) && new Set(v.positions).size === v.positions.length && v.articleId == null && v.quantity == null;
|
|
158
|
+
}
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
if (v.type === VoucherType.promotion) {
|
|
162
|
+
return v.action === VoucherAction.redeem && hatText(v.code)
|
|
163
|
+
&& v.amountCents == null && v.articleId == null && v.quantity == null && v.positions == null;
|
|
164
|
+
}
|
|
165
|
+
// Altart mit neuer Aktion (payout + value/promo): nicht sendbar.
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
@@ -61,7 +61,7 @@ import { KasseneckApiError } from '../client/errors.js';
|
|
|
61
61
|
*
|
|
62
62
|
* Reihenfolge und Bestand wie im Abzug des Backends.
|
|
63
63
|
*/
|
|
64
|
-
export declare const PARTNER_ERROR_CODES: readonly ["validation", "rate_limited", "app_not_found", "app_not_accepted", "live_not_allowed", "customer_exists", "customer_conflict", "customer_limit", "access_not_allowed", "email_taken", "no_email", "tax_number_missing", "fon_missing", "signature_pending", "signature_missing", "signature_unknown", "signature_ambiguous", "signature_not_ready", "signature_limit", "signature_failed", "module_inactive", "cashregister_limit", "cashregister_not_found", "contracts_pending", "kind_not_allowed", "mode_not_allowed", "power_of_attorney_missing", "not_found", "no_version", "unknown_version", "text_changed", "already_accepted", "activation_failed", "webhook_limit", "webhook_inactive", "event_not_subscribed"];
|
|
64
|
+
export declare const PARTNER_ERROR_CODES: readonly ["validation", "rate_limited", "app_not_found", "app_not_accepted", "live_not_allowed", "customer_exists", "customer_conflict", "customer_limit", "access_not_allowed", "email_taken", "no_email", "tax_number_missing", "fon_missing", "signature_pending", "signature_missing", "signature_unknown", "signature_ambiguous", "signature_not_ready", "signature_limit", "signature_failed", "module_inactive", "cashregister_limit", "cashregister_not_found", "contracts_pending", "kind_not_allowed", "mode_not_allowed", "power_of_attorney_missing", "not_found", "no_version", "unknown_version", "text_changed", "already_accepted", "activation_failed", "activation_in_progress", "webhook_limit", "webhook_inactive", "event_not_subscribed"];
|
|
65
65
|
/**
|
|
66
66
|
* Die Codes, die nur im **Partner-Portal** entstehen — beim Pflegen der App,
|
|
67
67
|
* der Schluessel, der Mitglieder und der Signaturkarten.
|
|
@@ -101,6 +101,7 @@ export const PARTNER_ERROR_CODES = [
|
|
|
101
101
|
'text_changed',
|
|
102
102
|
'already_accepted',
|
|
103
103
|
'activation_failed',
|
|
104
|
+
'activation_in_progress',
|
|
104
105
|
// Webhooks
|
|
105
106
|
'webhook_limit',
|
|
106
107
|
'webhook_inactive',
|
|
@@ -208,6 +209,7 @@ const RAT = {
|
|
|
208
209
|
text_changed: 'Der gezeigte Vertragstext hat sich seit dem Laden geaendert (data.textHash traegt die aktuell geltende Pruefsumme). Neu laden und danach erneut bestaetigen lassen.',
|
|
209
210
|
already_accepted: 'Diese Fassung ist bereits bestaetigt (data.contractId). Nichts weiter zu tun.',
|
|
210
211
|
activation_failed: 'Die Inbetriebnahme blieb an data.step haengen (ggf. data.rc). activateCashregister erneut aufrufen — jeder Schritt ist idempotent, der Lauf setzt an der Bruchstelle an.',
|
|
212
|
+
activation_in_progress: 'Die Inbetriebnahme dieser Kasse laeuft bereits. Kurz warten und den Stand abfragen, nicht erneut anstossen.',
|
|
211
213
|
webhook_limit: 'Hoechstens 10 Webhook-Endpunkte je Partner. Einen ungenutzten loeschen.',
|
|
212
214
|
webhook_inactive: 'Der Webhook steht auf active:false. Zuerst aktivieren, dann erneut proben.',
|
|
213
215
|
event_not_subscribed: 'Der Endpunkt abonniert dieses Ereignis nicht — auch eine Probe bekommt nur, was in seiner events-Liste steht. events erweitern und erneut versuchen.',
|
|
@@ -28,6 +28,6 @@ export { getPartnerInfo, createPartnerCustomer, listPartnerCustomers, checkPartn
|
|
|
28
28
|
export { createPartnerWebhook, listPartnerWebhooks, rotatePartnerWebhookSecret, updatePartnerWebhook, deletePartnerWebhook, sendPartnerWebhookTest, listPartnerWebhookDeliveries, parseWebhookEvent, isPartnerWebhookEvent, PARTNER_WEBHOOK_EVENTS, WEBHOOK_ENVELOPE_FIELDS, WEBHOOK_DELIVERY_STATUSES, type PartnerWebhookEvent, type PartnerWebhookEventType, type PartnerWebhook, type CreateWebhookOptions, type CreateWebhookResult, type DeleteWebhookResult, type WebhookApiVersion, type WebhookDeliveryStatus, type WebhookTestDelivery, type ContractAcceptedEventData, type SignatureFailedEventData, type CashregisterFailedEventData, type WebhookPatch, type WebhookList, type WebhookDelivery, type WebhookTestResult, type WebhookEventResult, } from './webhooks.js';
|
|
29
29
|
export { verifyWebhookSignature, parseSignatureHeader, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_EVENT_HEADER, WEBHOOK_DELIVERY_HEADER, WEBHOOK_TOLERANCE_SEC, WEBHOOK_RETRY_PLAN_SEC, WEBHOOK_MAX_ATTEMPTS, WEBHOOK_TIMEOUT_MS, WEBHOOK_LIMIT, type VerifyWebhookOptions, type WebhookVerifyResult, type WebhookVerifyReason, } from './webhook-signatur.js';
|
|
30
30
|
export { PARTNER_ENVS, LEGAL_FORMS, AUSTRIAN_STATES, CONTACT_ROLES, AVV_MODES, FEE_INTERVALS, CONTRACT_KINDS, CONTRACT_SOURCES, SIGNATURE_HISTORY_REASONS, SIGNATURE_ERROR_CODES, } from './typen.js';
|
|
31
|
-
export type { PartnerEnv, PartnerScope, PartnerApp, PartnerInfo, LegalForm, AustrianState, ContactRole, AvvMode, FeeInterval, PartnerFee, SignatureHistoryReason, SignatureErrorCode, RequestSignatureOptions, CustomerSignature, ContractKind, ContractSource, ReportCustomerContractOptions, ReportCustomerContractResult, BusinessAddress, BusinessTaxDetails, BusinessContact, BusinessTaxAdvisor, Business, CreateCustomerOptions, CreateCustomerResult, PartnerCustomerStatus, PartnerCustomerSummary, AvvStatus, ContractStatus, PartnerCustomerFonStatus, ListCustomersOptions, PartnerCustomerList, PartnerCustomer, FonLinkResult, SignatureRequestStatus, SignatureHistoryEntry, SignatureRequest, RequestSignatureResult, CustomerSignatureStatus, CashregisterActivationStep, CustomerCashregisterStatus, CustomerCashregister, CreateCashregisterOptions, CreateCashregisterResult, ActivateCashregisterResult, CustomerCashregisterList, CustomerCashregisterCredential, CustomerCredentials, } from './typen.js';
|
|
31
|
+
export type { PartnerEnv, PartnerScope, PartnerApp, PartnerInfo, LegalForm, AustrianState, ContactRole, AvvMode, FeeInterval, PartnerFee, SignatureHistoryReason, SignatureFulfillment, SignatureErrorCode, RequestSignatureOptions, CustomerSignature, ContractKind, ContractSource, ReportCustomerContractOptions, ReportCustomerContractResult, BusinessAddress, BusinessTaxDetails, BusinessContact, BusinessTaxAdvisor, Business, CreateCustomerOptions, CreateCustomerResult, PartnerCustomerStatus, PartnerCustomerSummary, AvvStatus, ContractStatus, PartnerCustomerFonStatus, ListCustomersOptions, PartnerCustomerList, PartnerCustomer, FonLinkResult, SignatureRequestStatus, SignatureHistoryEntry, SignatureRequest, RequestSignatureResult, CustomerSignatureStatus, CashregisterActivationStep, CustomerCashregisterStatus, CustomerCashregister, CreateCashregisterOptions, CreateCashregisterResult, ActivateCashregisterResult, CustomerCashregisterList, CustomerCashregisterCredential, CustomerCredentials, } from './typen.js';
|
|
32
32
|
/** `credentials:read` — nicht im Standardsatz, siehe typen.ts. */
|
|
33
33
|
export { SCOPE_CREDENTIALS } from './typen.js';
|
|
@@ -382,7 +382,7 @@ export type SignatureRequestStatus = 'requested' | 'assigned' | 'registered' | '
|
|
|
382
382
|
* Gruende in der Historie eines Signaturantrags. `card_entered` und
|
|
383
383
|
* `finanzonline` hiessen unter `/v1` `karte_eingetragen` und `fon`.
|
|
384
384
|
*/
|
|
385
|
-
export declare const SIGNATURE_HISTORY_REASONS: readonly ["api", "portal", "card_entered", "finanzonline", "automation_off", "test_environment", "no_stock"];
|
|
385
|
+
export declare const SIGNATURE_HISTORY_REASONS: readonly ["api", "portal", "card_entered", "finanzonline", "automation_off", "test_environment", "no_stock", "card_pool_activated", "activation_run", "finanzonline_completed"];
|
|
386
386
|
/** Offen fuer spaeter ergaenzte Gruende, siehe [SIGNATURE_HISTORY_REASONS]. */
|
|
387
387
|
export type SignatureHistoryReason = typeof SIGNATURE_HISTORY_REASONS[number] | (string & {});
|
|
388
388
|
/**
|
|
@@ -400,6 +400,8 @@ export interface SignatureHistoryEntry {
|
|
|
400
400
|
at: number;
|
|
401
401
|
reason: SignatureHistoryReason | null;
|
|
402
402
|
}
|
|
403
|
+
/** Erfuellungsweg eines Signaturantrags; offen fuer spaeter ergaenzte Werte. */
|
|
404
|
+
export type SignatureFulfillment = 'automatic' | 'manual' | (string & {});
|
|
403
405
|
export interface SignatureRequest {
|
|
404
406
|
requestId: string;
|
|
405
407
|
status: SignatureRequestStatus;
|
|
@@ -408,6 +410,8 @@ export interface SignatureRequest {
|
|
|
408
410
|
kind: string;
|
|
409
411
|
vdaId: string | null;
|
|
410
412
|
signatureId: string | null;
|
|
413
|
+
/** Wie der Antrag erfuellt wird: aus dem Kartenvorrat oder von Hand. */
|
|
414
|
+
fulfillment?: SignatureFulfillment;
|
|
411
415
|
error: {
|
|
412
416
|
code: SignatureErrorCode | null;
|
|
413
417
|
message: string | null;
|
|
@@ -442,6 +446,8 @@ export interface CustomerSignature {
|
|
|
442
446
|
status: SignatureRequestStatus | 'decommissioned';
|
|
443
447
|
statusText: string;
|
|
444
448
|
inProgress: boolean;
|
|
449
|
+
/** Wie der Antrag erfuellt wird: aus dem Kartenvorrat oder von Hand. */
|
|
450
|
+
fulfillment?: SignatureFulfillment;
|
|
445
451
|
ready: boolean;
|
|
446
452
|
kind: string;
|
|
447
453
|
vdaId: string | null;
|
|
@@ -97,6 +97,9 @@ export const SIGNATURE_HISTORY_REASONS = [
|
|
|
97
97
|
'automation_off',
|
|
98
98
|
'test_environment',
|
|
99
99
|
'no_stock',
|
|
100
|
+
'card_pool_activated',
|
|
101
|
+
'activation_run',
|
|
102
|
+
'finanzonline_completed',
|
|
100
103
|
];
|
|
101
104
|
/**
|
|
102
105
|
* `error.code` eines Signaturantrags oder einer Signatur (`SignatureRequest`,
|
package/dist/esm/pos/client.d.ts
CHANGED
|
@@ -4,10 +4,11 @@ import { type PosSettings, type PosBusinessSettings, type PosDeviceSettings } fr
|
|
|
4
4
|
export declare function getPosSettings(transport: InternerTransport, options?: {
|
|
5
5
|
deviceId?: string;
|
|
6
6
|
}): Promise<PosSettings>;
|
|
7
|
-
/** `{business, device}` einer Antwort, gemischt mit den Standardwerten. */
|
|
7
|
+
/** `{business, device, vouchers}` einer Antwort, gemischt mit den Standardwerten. */
|
|
8
8
|
export declare function posSettingsFromWire(data: {
|
|
9
9
|
business?: unknown;
|
|
10
10
|
device?: unknown;
|
|
11
|
+
vouchers?: unknown;
|
|
11
12
|
} | null | undefined): PosSettings;
|
|
12
13
|
/** Betriebsweite Einstellungen schreiben (Recht `layout`); liefert den gemischten Stand. */
|
|
13
14
|
export declare function setMyPosSettings(transport: InternerTransport, business: Partial<PosBusinessSettings>): Promise<PosBusinessSettings>;
|
package/dist/esm/pos/client.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { KasseneckValidationError } from '../client/errors.js';
|
|
2
|
+
import { posVoucherSettingsFromWire } from './gutschein.js';
|
|
2
3
|
import { POS_BUSINESS_DEFAULTS, POS_DEVICE_DEFAULTS, POS_BUSINESS_VALUES, POS_DEVICE_VALUES, POS_SHORTCUT_ACTIONS, POS_DEVICE_OPTIONAL_FIELDS, POS_BUSINESS_OPTIONAL_FIELDS, mergePosSettings, posShortcutConflict, _istAltwert0x, _optionalerWert, } from './settings.js';
|
|
3
4
|
/*
|
|
4
5
|
* Die Einstellungs-Aufrufe am Draht `/api/v3`: Parameter und Antwort heissen
|
|
@@ -27,9 +28,10 @@ export async function getPosSettings(transport, options = {}) {
|
|
|
27
28
|
const daten = await transport('getKasseSettings', params);
|
|
28
29
|
return posSettingsFromWire(daten);
|
|
29
30
|
}
|
|
30
|
-
/** `{business, device}` einer Antwort, gemischt mit den Standardwerten. */
|
|
31
|
+
/** `{business, device, vouchers}` einer Antwort, gemischt mit den Standardwerten. */
|
|
31
32
|
export function posSettingsFromWire(data) {
|
|
32
33
|
return {
|
|
34
|
+
vouchers: posVoucherSettingsFromWire(data?.vouchers),
|
|
33
35
|
business: mergePosSettings(POS_BUSINESS_DEFAULTS, objekt(data?.business)),
|
|
34
36
|
device: mergePosSettings(POS_DEVICE_DEFAULTS, objekt(data?.device)),
|
|
35
37
|
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { InternerTransport } from '../client/aufrufe.js';
|
|
2
|
+
/**
|
|
3
|
+
* Gutschein pruefen und Etikett nachdrucken an der Kasse (Backend
|
|
4
|
+
* gutschein-endpoints). Beide Aufrufe gibt es nur ueber den Kassenweg
|
|
5
|
+
* `/api/v3`.
|
|
6
|
+
*
|
|
7
|
+
* Der Klartext-Code lebt nur im Speicher des Aufrufs: er wird weder
|
|
8
|
+
* protokolliert noch in einer Fehlermeldung genannt. Die Kasse bekommt nach
|
|
9
|
+
* dem Pruefen nur die letzten vier Zeichen (`codeSuffix`) zurueck.
|
|
10
|
+
*/
|
|
11
|
+
export type VoucherKind = 'multi_purpose' | 'single_purpose' | 'service' | 'promotion';
|
|
12
|
+
export type VoucherStatus = 'active' | 'used_up' | 'expired' | 'paid_out' | 'cancelled' | 'blocked';
|
|
13
|
+
export declare const VOUCHER_KINDS: readonly VoucherKind[];
|
|
14
|
+
export declare const VOUCHER_STATUSES: readonly VoucherStatus[];
|
|
15
|
+
/** Gueltigkeit eines Gutscheins; Daten als `YYYY-MM-DD` (Wiener Tag). Was der Server nicht nennt, fehlt. */
|
|
16
|
+
export interface VoucherValidity {
|
|
17
|
+
pattern: 'unlimited' | '1+3' | 'custom';
|
|
18
|
+
redeemableUntil?: string;
|
|
19
|
+
refundableUntil?: string;
|
|
20
|
+
validUntil?: string;
|
|
21
|
+
}
|
|
22
|
+
/** Der Artikel eines Dienstleistungsgutscheins. */
|
|
23
|
+
export interface VoucherArticle {
|
|
24
|
+
id: string;
|
|
25
|
+
name: string;
|
|
26
|
+
vatRateBp: number;
|
|
27
|
+
priceCents: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Stand eines Gutscheins nach dem Code-Eingeben. Felder, die zur Art nicht
|
|
31
|
+
* passen oder die der Server nicht sendet, fehlen im Modell (nie `null`).
|
|
32
|
+
*/
|
|
33
|
+
export interface VoucherCheck {
|
|
34
|
+
type: VoucherKind;
|
|
35
|
+
status: VoucherStatus;
|
|
36
|
+
/** Die letzten vier Zeichen des Codes, fuer Anzeige und Beleg. */
|
|
37
|
+
codeSuffix: string;
|
|
38
|
+
balanceCents?: number;
|
|
39
|
+
faceValueCents?: number;
|
|
40
|
+
quantity?: number;
|
|
41
|
+
remainingQuantity?: number;
|
|
42
|
+
vatRateBp?: number;
|
|
43
|
+
article?: VoucherArticle;
|
|
44
|
+
discountCents?: number;
|
|
45
|
+
discountPercentBp?: number;
|
|
46
|
+
validity?: VoucherValidity;
|
|
47
|
+
/**
|
|
48
|
+
* Befreit verkauft (Kleinunternehmer beim Verkauf, Satz 0): eine Einloesung
|
|
49
|
+
* verteilt sich anteilig auf alle Saetze des Korbs, auch in einem
|
|
50
|
+
* inzwischen steuerpflichtigen Konto. Fehlt bei aelteren Servern.
|
|
51
|
+
*/
|
|
52
|
+
exempt?: boolean;
|
|
53
|
+
}
|
|
54
|
+
/** Gutschein-Einstellungen der Kasse (Block `vouchers` aus `getKasseSettings`). */
|
|
55
|
+
export interface PosVoucherSettings {
|
|
56
|
+
sale: boolean;
|
|
57
|
+
valueVoucherType: 'multi_purpose' | 'single_purpose' | null;
|
|
58
|
+
vatRateBp: number | null;
|
|
59
|
+
}
|
|
60
|
+
/** Ohne Block `vouchers` (alter Server, Konto ohne Schalter): Verkaufen ist aus. */
|
|
61
|
+
export declare const VOUCHER_SETTINGS_DEFAULTS: Readonly<PosVoucherSettings>;
|
|
62
|
+
/**
|
|
63
|
+
* Block `vouchers` einer Einstellungs-Antwort, geschlossen im Zweifel: ist
|
|
64
|
+
* irgendein Feld unstimmig, gilt der ganze Block als nicht gelesen und
|
|
65
|
+
* Verkaufen bleibt aus (kein Wurf, sonst ginge das Laden aller Einstellungen
|
|
66
|
+
* verloren). Stimmig heisst: `sale` ein Wahrheitswert, die Art
|
|
67
|
+
* `multi_purpose`/`single_purpose`/`null`, der Satz eine ganze Zahl >= 0 oder
|
|
68
|
+
* `null`; Mehrzweck traegt keinen Satz, Einzweck braucht einen, und ein
|
|
69
|
+
* eingeschalteter Verkauf braucht eine Art. Ein ausgeschalteter Verkauf darf
|
|
70
|
+
* eine Art behalten.
|
|
71
|
+
*/
|
|
72
|
+
export declare function posVoucherSettingsFromWire(block: unknown): PosVoucherSettings;
|
|
73
|
+
/**
|
|
74
|
+
* Gutschein am Code pruefen (Gutschein-Recht `voucherRedeem`). Der Code wird
|
|
75
|
+
* tolerant eingelesen (Gross/klein, Bindestriche, `O`/`0`, `I`/`L`/`1`) und
|
|
76
|
+
* vor dem Senden auf sein Pruefzeichen geprueft: ein Tippfehler geht nie ueber
|
|
77
|
+
* das Netz, sondern endet mit `KasseneckValidationError`. Fachliche Fehler
|
|
78
|
+
* kommen als `KasseneckApiError` mit dem Code des Servers
|
|
79
|
+
* (`voucher_not_found`, `too_many_voucher_checks`, `not_permitted` …).
|
|
80
|
+
*/
|
|
81
|
+
export declare function checkVoucher(transport: InternerTransport, code: string): Promise<VoucherCheck>;
|
|
82
|
+
/**
|
|
83
|
+
* Etikett eines Gutscheins noch einmal drucken (Gutschein-Recht
|
|
84
|
+
* `voucherManage`). Antwort ist der Klartext-Code zum Drucken; er gehoert
|
|
85
|
+
* nur in den Speicher bis zum Druck. Aufrufer duerfen ihn nicht protokollieren,
|
|
86
|
+
* speichern oder in Meldungen nennen; Lesefehler dieser Antwort nennen ihn nie.
|
|
87
|
+
*/
|
|
88
|
+
export declare function reprintVoucherLabel(transport: InternerTransport, id: string): Promise<{
|
|
89
|
+
code: string;
|
|
90
|
+
}>;
|