@kreiseck/kasseneck-api 0.6.49 → 0.6.50
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/README.md +5 -0
- package/dist/cjs/models/cancellation.d.ts +6 -0
- package/dist/cjs/models/receipt-summary.d.ts +2 -0
- package/dist/cjs/models/receipt-summary.js +4 -1
- package/dist/cjs/models/receipt.js +5 -1
- package/dist/cjs/receipt/layout.js +19 -0
- package/dist/esm/models/cancellation.d.ts +6 -0
- package/dist/esm/models/receipt-summary.d.ts +2 -0
- package/dist/esm/models/receipt-summary.js +4 -1
- package/dist/esm/models/receipt.js +5 -1
- package/dist/esm/receipt/layout.js +19 -0
- package/fixtures/belege/storno-rabatt.json +3 -2
- package/fixtures/belege/storno-teil.json +2 -1
- package/fixtures/belege/storno-voll.json +2 -1
- package/fixtures/erwartet/storno-rabatt.grid32.txt +1 -0
- package/fixtures/erwartet/storno-rabatt.grid48.txt +1 -0
- package/fixtures/erwartet/storno-rabatt.lines.json +6 -0
- package/fixtures/erwartet/storno-teil.grid32.txt +1 -0
- package/fixtures/erwartet/storno-teil.grid48.txt +1 -0
- package/fixtures/erwartet/storno-teil.lines.json +6 -0
- package/fixtures/erwartet/storno-voll.grid32.txt +1 -0
- package/fixtures/erwartet/storno-voll.grid48.txt +1 -0
- package/fixtures/erwartet/storno-voll.lines.json +6 -0
- package/fixtures/hobex-hps-codes.json +1 -1
- package/fixtures/manifest.json +12 -12
- package/fixtures/oberflaeche.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -199,6 +199,11 @@ Was ein Storno gewährt hat, steht am Eintrag in `receipt.cancellations[]` als
|
|
|
199
199
|
`promoAdjustmentCents` (Cent je Steuertopf) — die Kasse kann es im Dialog
|
|
200
200
|
zeigen, rechnen muss sie nichts.
|
|
201
201
|
|
|
202
|
+
**Bon.** Der Kopfblock des Storno-Bons nennt Bezug, Datum des Originals und
|
|
203
|
+
Grund: „STORNOBELEG / Stornobuchung zu Beleg KASSE1-ID-42 / vom 11.08.2026,
|
|
204
|
+
09:02 Uhr / Grund: Fehleingabe". Das Datum kommt aus `cancellationOf.timeStamp`
|
|
205
|
+
(Backend seit 2026-09-04); Altbelege ohne bleiben ohne die Zeile.
|
|
206
|
+
|
|
202
207
|
## Unterpfade
|
|
203
208
|
|
|
204
209
|
| Unterpfad | Inhalt |
|
|
@@ -35,6 +35,12 @@ export declare function isCancellationErrorCode(value: unknown): value is Cancel
|
|
|
35
35
|
export interface CancellationOf {
|
|
36
36
|
receiptId: string;
|
|
37
37
|
fullReceiptId: string | null;
|
|
38
|
+
/**
|
|
39
|
+
* Zeitstempel des Originals (Server-Format, Wiener Wanduhr) — das Layout
|
|
40
|
+
* nennt ihn im Kopfblock des Storno-Bons („vom 11.08.2026, 09:02 Uhr").
|
|
41
|
+
* Fehlt bei Altbelegen; dann bleibt die Zeile weg.
|
|
42
|
+
*/
|
|
43
|
+
timeStamp?: string;
|
|
38
44
|
}
|
|
39
45
|
/** Eine stornierte Position: Index im Original und Menge. */
|
|
40
46
|
export interface CancellationItem {
|
|
@@ -56,6 +56,7 @@ export interface ReceiptSummary {
|
|
|
56
56
|
/** Nur am Storno-Beleg: das Original. */
|
|
57
57
|
cancellationOf?: {
|
|
58
58
|
receiptId: string | null;
|
|
59
|
+
timeStamp?: string;
|
|
59
60
|
};
|
|
60
61
|
cancellationReason?: string;
|
|
61
62
|
/** offen | teil | voll -- Storno-Stand des Originals. */
|
|
@@ -84,6 +85,7 @@ export interface ReceiptSummaryPayload {
|
|
|
84
85
|
} | null;
|
|
85
86
|
cancellationOf?: {
|
|
86
87
|
receiptId?: string | null;
|
|
88
|
+
timeStamp?: string | null;
|
|
87
89
|
} | null;
|
|
88
90
|
cancellationReason?: string | null;
|
|
89
91
|
stornoStand?: string | null;
|
|
@@ -46,7 +46,10 @@ function fromReceiptSummaryPayload(payload) {
|
|
|
46
46
|
signatureOk: payload.signature_ok !== false,
|
|
47
47
|
items: Array.isArray(payload.items) ? payload.items.map((i) => ({ name: i?.name ?? '', quantity: typeof i?.quantity === 'number' ? i.quantity : 0 })) : [],
|
|
48
48
|
...(payload.operator ? { operator: { uid: payload.operator.uid ?? null, name: payload.operator.name ?? '' } } : {}),
|
|
49
|
-
...(payload.cancellationOf ? { cancellationOf: {
|
|
49
|
+
...(payload.cancellationOf ? { cancellationOf: {
|
|
50
|
+
receiptId: payload.cancellationOf.receiptId ?? null,
|
|
51
|
+
...(typeof payload.cancellationOf.timeStamp === 'string' && payload.cancellationOf.timeStamp ? { timeStamp: payload.cancellationOf.timeStamp } : {}),
|
|
52
|
+
} } : {}),
|
|
50
53
|
...(payload.cancellationReason ? { cancellationReason: payload.cancellationReason } : {}),
|
|
51
54
|
stornoStand: payload.stornoStand === 'teil' || payload.stornoStand === 'voll' ? payload.stornoStand : 'offen',
|
|
52
55
|
...(istZeroKind(payload.zeroKind) ? { zeroKind: payload.zeroKind } : {}),
|
|
@@ -76,7 +76,11 @@ function fromReceiptPayload(payload) {
|
|
|
76
76
|
signatureSuccess: payload.signatureSuccess ?? undefined,
|
|
77
77
|
customProjectId: payload.customProjectId ?? undefined,
|
|
78
78
|
...(typeof payload.tipCents === 'number' ? { tipCents: payload.tipCents } : {}),
|
|
79
|
-
...(payload.cancellationOf ? { cancellationOf: {
|
|
79
|
+
...(payload.cancellationOf ? { cancellationOf: {
|
|
80
|
+
receiptId: payload.cancellationOf.receiptId,
|
|
81
|
+
fullReceiptId: payload.cancellationOf.fullReceiptId ?? null,
|
|
82
|
+
...(typeof payload.cancellationOf.timeStamp === 'string' && payload.cancellationOf.timeStamp ? { timeStamp: payload.cancellationOf.timeStamp } : {}),
|
|
83
|
+
} } : {}),
|
|
80
84
|
...(payload.cancellationReason ? { cancellationReason: payload.cancellationReason } : {}),
|
|
81
85
|
...((0, receipt_summary_js_1.istZeroKind)(payload.zeroKind) ? { zeroKind: payload.zeroKind } : {}),
|
|
82
86
|
...(payload.cancellations ? { cancellations: payload.cancellations.map(leseStorno) } : {}),
|
|
@@ -48,6 +48,21 @@ function belegZeit(timeStamp) {
|
|
|
48
48
|
const zwei = (n) => String(n).padStart(2, '0');
|
|
49
49
|
return `${zwei(t.day)}.${zwei(t.month)}.${t.year} ${zwei(t.hour)}:${zwei(t.minute)}:${zwei(t.second)}`;
|
|
50
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Datum des stornierten Originals fuer den Kopfblock: „11.08.2026, 09:02 Uhr".
|
|
53
|
+
* Ein unlesbarer Zeitstempel am BEZUG ist kein Grund, den Storno-Bon zu
|
|
54
|
+
* verweigern (der Beleg selbst ist gueltig) — dann bleibt die Zeile weg.
|
|
55
|
+
*/
|
|
56
|
+
function originalDatum(timeStamp) {
|
|
57
|
+
try {
|
|
58
|
+
const t = (0, vienna_time_js_1.toViennaWallClock)((0, vienna_time_js_1.parseServerTimeStamp)(timeStamp));
|
|
59
|
+
const zwei = (n) => String(n).padStart(2, '0');
|
|
60
|
+
return `${zwei(t.day)}.${zwei(t.month)}.${t.year}, ${zwei(t.hour)}:${zwei(t.minute)} Uhr`;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
51
66
|
/**
|
|
52
67
|
* Zahlungsart als Anzeigetext. Drei Faelle, und alle drei kommen vor:
|
|
53
68
|
* bekannter Eintrag (Beschriftung), unbekannter Schluessel (roh — besser als
|
|
@@ -415,6 +430,10 @@ function belegartBlock(receipt) {
|
|
|
415
430
|
if (t === 'cancellation') {
|
|
416
431
|
aus.push(bannerZeile('STORNOBELEG'));
|
|
417
432
|
aus.push(textZeile(receipt.cancellationOf ? `Stornobuchung zu Beleg ${receipt.cancellationOf.receiptId}` : 'Stornobuchung', 'center'));
|
|
433
|
+
// Datum des Originals, wenn der Bezug es traegt (Backend seit 2026-09-04).
|
|
434
|
+
const datum = receipt.cancellationOf?.timeStamp ? originalDatum(receipt.cancellationOf.timeStamp) : null;
|
|
435
|
+
if (datum)
|
|
436
|
+
aus.push(textZeile(`vom ${datum}`, 'center'));
|
|
418
437
|
const grund = stornoGrundText(typeof receipt.cancellationReason === 'string' ? receipt.cancellationReason : undefined);
|
|
419
438
|
if (grund)
|
|
420
439
|
aus.push(textZeile(`Grund: ${grund}`, 'center'));
|
|
@@ -35,6 +35,12 @@ export declare function isCancellationErrorCode(value: unknown): value is Cancel
|
|
|
35
35
|
export interface CancellationOf {
|
|
36
36
|
receiptId: string;
|
|
37
37
|
fullReceiptId: string | null;
|
|
38
|
+
/**
|
|
39
|
+
* Zeitstempel des Originals (Server-Format, Wiener Wanduhr) — das Layout
|
|
40
|
+
* nennt ihn im Kopfblock des Storno-Bons („vom 11.08.2026, 09:02 Uhr").
|
|
41
|
+
* Fehlt bei Altbelegen; dann bleibt die Zeile weg.
|
|
42
|
+
*/
|
|
43
|
+
timeStamp?: string;
|
|
38
44
|
}
|
|
39
45
|
/** Eine stornierte Position: Index im Original und Menge. */
|
|
40
46
|
export interface CancellationItem {
|
|
@@ -56,6 +56,7 @@ export interface ReceiptSummary {
|
|
|
56
56
|
/** Nur am Storno-Beleg: das Original. */
|
|
57
57
|
cancellationOf?: {
|
|
58
58
|
receiptId: string | null;
|
|
59
|
+
timeStamp?: string;
|
|
59
60
|
};
|
|
60
61
|
cancellationReason?: string;
|
|
61
62
|
/** offen | teil | voll -- Storno-Stand des Originals. */
|
|
@@ -84,6 +85,7 @@ export interface ReceiptSummaryPayload {
|
|
|
84
85
|
} | null;
|
|
85
86
|
cancellationOf?: {
|
|
86
87
|
receiptId?: string | null;
|
|
88
|
+
timeStamp?: string | null;
|
|
87
89
|
} | null;
|
|
88
90
|
cancellationReason?: string | null;
|
|
89
91
|
stornoStand?: string | null;
|
|
@@ -41,7 +41,10 @@ export function fromReceiptSummaryPayload(payload) {
|
|
|
41
41
|
signatureOk: payload.signature_ok !== false,
|
|
42
42
|
items: Array.isArray(payload.items) ? payload.items.map((i) => ({ name: i?.name ?? '', quantity: typeof i?.quantity === 'number' ? i.quantity : 0 })) : [],
|
|
43
43
|
...(payload.operator ? { operator: { uid: payload.operator.uid ?? null, name: payload.operator.name ?? '' } } : {}),
|
|
44
|
-
...(payload.cancellationOf ? { cancellationOf: {
|
|
44
|
+
...(payload.cancellationOf ? { cancellationOf: {
|
|
45
|
+
receiptId: payload.cancellationOf.receiptId ?? null,
|
|
46
|
+
...(typeof payload.cancellationOf.timeStamp === 'string' && payload.cancellationOf.timeStamp ? { timeStamp: payload.cancellationOf.timeStamp } : {}),
|
|
47
|
+
} } : {}),
|
|
45
48
|
...(payload.cancellationReason ? { cancellationReason: payload.cancellationReason } : {}),
|
|
46
49
|
stornoStand: payload.stornoStand === 'teil' || payload.stornoStand === 'voll' ? payload.stornoStand : 'offen',
|
|
47
50
|
...(istZeroKind(payload.zeroKind) ? { zeroKind: payload.zeroKind } : {}),
|
|
@@ -70,7 +70,11 @@ export function fromReceiptPayload(payload) {
|
|
|
70
70
|
signatureSuccess: payload.signatureSuccess ?? undefined,
|
|
71
71
|
customProjectId: payload.customProjectId ?? undefined,
|
|
72
72
|
...(typeof payload.tipCents === 'number' ? { tipCents: payload.tipCents } : {}),
|
|
73
|
-
...(payload.cancellationOf ? { cancellationOf: {
|
|
73
|
+
...(payload.cancellationOf ? { cancellationOf: {
|
|
74
|
+
receiptId: payload.cancellationOf.receiptId,
|
|
75
|
+
fullReceiptId: payload.cancellationOf.fullReceiptId ?? null,
|
|
76
|
+
...(typeof payload.cancellationOf.timeStamp === 'string' && payload.cancellationOf.timeStamp ? { timeStamp: payload.cancellationOf.timeStamp } : {}),
|
|
77
|
+
} } : {}),
|
|
74
78
|
...(payload.cancellationReason ? { cancellationReason: payload.cancellationReason } : {}),
|
|
75
79
|
...(istZeroKind(payload.zeroKind) ? { zeroKind: payload.zeroKind } : {}),
|
|
76
80
|
...(payload.cancellations ? { cancellations: payload.cancellations.map(leseStorno) } : {}),
|
|
@@ -37,6 +37,21 @@ function belegZeit(timeStamp) {
|
|
|
37
37
|
const zwei = (n) => String(n).padStart(2, '0');
|
|
38
38
|
return `${zwei(t.day)}.${zwei(t.month)}.${t.year} ${zwei(t.hour)}:${zwei(t.minute)}:${zwei(t.second)}`;
|
|
39
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Datum des stornierten Originals fuer den Kopfblock: „11.08.2026, 09:02 Uhr".
|
|
42
|
+
* Ein unlesbarer Zeitstempel am BEZUG ist kein Grund, den Storno-Bon zu
|
|
43
|
+
* verweigern (der Beleg selbst ist gueltig) — dann bleibt die Zeile weg.
|
|
44
|
+
*/
|
|
45
|
+
function originalDatum(timeStamp) {
|
|
46
|
+
try {
|
|
47
|
+
const t = toViennaWallClock(parseServerTimeStamp(timeStamp));
|
|
48
|
+
const zwei = (n) => String(n).padStart(2, '0');
|
|
49
|
+
return `${zwei(t.day)}.${zwei(t.month)}.${t.year}, ${zwei(t.hour)}:${zwei(t.minute)} Uhr`;
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
40
55
|
/**
|
|
41
56
|
* Zahlungsart als Anzeigetext. Drei Faelle, und alle drei kommen vor:
|
|
42
57
|
* bekannter Eintrag (Beschriftung), unbekannter Schluessel (roh — besser als
|
|
@@ -404,6 +419,10 @@ function belegartBlock(receipt) {
|
|
|
404
419
|
if (t === 'cancellation') {
|
|
405
420
|
aus.push(bannerZeile('STORNOBELEG'));
|
|
406
421
|
aus.push(textZeile(receipt.cancellationOf ? `Stornobuchung zu Beleg ${receipt.cancellationOf.receiptId}` : 'Stornobuchung', 'center'));
|
|
422
|
+
// Datum des Originals, wenn der Bezug es traegt (Backend seit 2026-09-04).
|
|
423
|
+
const datum = receipt.cancellationOf?.timeStamp ? originalDatum(receipt.cancellationOf.timeStamp) : null;
|
|
424
|
+
if (datum)
|
|
425
|
+
aus.push(textZeile(`vom ${datum}`, 'center'));
|
|
407
426
|
const grund = stornoGrundText(typeof receipt.cancellationReason === 'string' ? receipt.cancellationReason : undefined);
|
|
408
427
|
if (grund)
|
|
409
428
|
aus.push(textZeile(`Grund: ${grund}`, 'center'));
|
|
@@ -58,11 +58,12 @@
|
|
|
58
58
|
"legalMessage": [],
|
|
59
59
|
"cancellationOf": {
|
|
60
60
|
"receiptId": "AT0-KASSE1-55",
|
|
61
|
-
"fullReceiptId": null
|
|
61
|
+
"fullReceiptId": null,
|
|
62
|
+
"timeStamp": "2026-08-11T09:02:17"
|
|
62
63
|
},
|
|
63
64
|
"cancellationReason": "fehleingabe"
|
|
64
65
|
},
|
|
65
66
|
"options": {
|
|
66
67
|
"paperSize": "mm80"
|
|
67
68
|
}
|
|
68
|
-
}
|
|
69
|
+
}
|
package/fixtures/manifest.json
CHANGED
|
@@ -80,22 +80,22 @@
|
|
|
80
80
|
"grid48": "e0f4e73c873ae0a70623c7c05673a5ca9b736822375c13f6ed0cd3351ab767f9"
|
|
81
81
|
},
|
|
82
82
|
"storno-rabatt": {
|
|
83
|
-
"eingabe": "
|
|
84
|
-
"erwartet": "
|
|
85
|
-
"grid32": "
|
|
86
|
-
"grid48": "
|
|
83
|
+
"eingabe": "d6bd978f4cc3e9c8c4315c573c7a3f5c8dfea4bf65fce6789f268056a521ec15",
|
|
84
|
+
"erwartet": "a10fc0dbbfd46366feab7431ab1608ad5a76418e80b50d2903c574ee2cb70040",
|
|
85
|
+
"grid32": "5f932ee49c9b7ee1e1dfc5fe703a18da43c782072012280ca93b177b0c535c20",
|
|
86
|
+
"grid48": "dc84efa238626d782cb049df6299d65fa2a5740795e610ecaf903ac4ca296434"
|
|
87
87
|
},
|
|
88
88
|
"storno-teil": {
|
|
89
|
-
"eingabe": "
|
|
90
|
-
"erwartet": "
|
|
91
|
-
"grid32": "
|
|
92
|
-
"grid48": "
|
|
89
|
+
"eingabe": "2f4cab11c1c9e8bb4722dd6c4a279825a9e31e3b6a9335c017bc587d97af0fd4",
|
|
90
|
+
"erwartet": "dcf388d74261171b3b004f1abb51650dd7d2d53f7b2c8a4ae453ce47ec3e01e6",
|
|
91
|
+
"grid32": "e340077738bb0e336cc64a5c8e15a6712624e7d3ecbe7a3f981580c2efe446c7",
|
|
92
|
+
"grid48": "c62513749f18d8cb230b96607cfae46e49e99b50799b57308c747f8a12973d0a"
|
|
93
93
|
},
|
|
94
94
|
"storno-voll": {
|
|
95
|
-
"eingabe": "
|
|
96
|
-
"erwartet": "
|
|
97
|
-
"grid32": "
|
|
98
|
-
"grid48": "
|
|
95
|
+
"eingabe": "11f4f58f4f06cd2d414f982b85a017c2a3f62cd23fb8c54d000c16ce1490d2f8",
|
|
96
|
+
"erwartet": "8e595d6afb36e9c2d2dd77ec71927a039435d74eafe2321c73fff48d321d3602",
|
|
97
|
+
"grid32": "e8c20dc0ea199b6ee5418205e498dcda3e1bb8fb8b1d0d639af353b1df98740c",
|
|
98
|
+
"grid48": "81aa151523ae7fa542d58b8c4835a690b686a9aeb9fb7872950419cd370f418c"
|
|
99
99
|
},
|
|
100
100
|
"testkasse-verkauf": {
|
|
101
101
|
"eingabe": "5cd594029a3d7af4a7c502719763d8b5df0063ff7e46da43c9c7dc4fd2638e1f",
|