@kreiseck/kasseneck-api 1.0.0-rc.4 → 1.0.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 +77 -0
- package/README.md +40 -4
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js +4 -1
- package/dist/cjs/pos/index.d.ts +1 -1
- package/dist/cjs/pos/index.js +6 -1
- package/dist/cjs/pos/texte.d.ts +95 -2
- package/dist/cjs/pos/texte.js +111 -3
- package/dist/cjs/receipt/due.d.ts +33 -0
- package/dist/cjs/receipt/due.js +61 -15
- package/dist/cjs/receipt/index.d.ts +1 -1
- package/dist/cjs/receipt/index.js +4 -1
- package/dist/cjs/stored/index.d.ts +1 -0
- package/dist/cjs/stored/index.js +7 -0
- package/dist/cjs/stored/layout.d.ts +55 -0
- package/dist/cjs/stored/layout.js +119 -0
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/pos/index.d.ts +1 -1
- package/dist/esm/pos/index.js +1 -1
- package/dist/esm/pos/texte.d.ts +95 -2
- package/dist/esm/pos/texte.js +108 -2
- package/dist/esm/receipt/due.d.ts +33 -0
- package/dist/esm/receipt/due.js +58 -15
- package/dist/esm/receipt/index.d.ts +1 -1
- package/dist/esm/receipt/index.js +1 -1
- package/dist/esm/stored/index.d.ts +1 -0
- package/dist/esm/stored/index.js +2 -0
- package/dist/esm/stored/layout.d.ts +55 -0
- package/dist/esm/stored/layout.js +113 -0
- 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-message-cases.json +31 -1
- package/fixtures/pos-texts.json +68 -1
- package/fixtures/receipt-due-errors.json +56 -0
- package/fixtures/surface.json +11 -1
- package/fixtures/v3/antworten/belege.json +1 -1
- package/fixtures/v3/antworten/belegmail.json +1 -1
- package/fixtures/v3/antworten/kasse-belege.json +1 -1
- package/fixtures/v3/antworten/kasse.json +2 -2
- package/fixtures/v3/antworten/rechnungen.json +1 -1
- package/fixtures/v3/antworten/storno.json +1 -1
- package/fixtures/v3/stored/belege.json +1 -1
- package/fixtures/v3/stored/kasse.json +2 -2
- package/fixtures/v3/stored/rechnungen.json +1 -1
- package/fixtures/v3/v3-vokabular.json +1 -1
- package/fixtures/v3/zahlbetrag-faelle.json +1 -1
- package/package.json +1 -1
package/dist/cjs/receipt/due.js
CHANGED
|
@@ -1,8 +1,54 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReceiptDueError = exports.RECEIPT_DUE_ERROR_REASONS = void 0;
|
|
4
|
+
exports.isReceiptDueError = isReceiptDueError;
|
|
3
5
|
exports.receiptDueCents = receiptDueCents;
|
|
4
6
|
exports.receiptDueBreakdown = receiptDueBreakdown;
|
|
5
7
|
const index_js_1 = require("../enums/index.js");
|
|
8
|
+
/**
|
|
9
|
+
* Warum sich der Zahlbetrag nicht rechnen laesst. Fest wie ein Backend-Code;
|
|
10
|
+
* dieselbe Liste im Dart-Zwilling und in `fixtures/receipt-due-errors.json`.
|
|
11
|
+
*/
|
|
12
|
+
exports.RECEIPT_DUE_ERROR_REASONS = Object.freeze([
|
|
13
|
+
'unknown_receipt_type',
|
|
14
|
+
'tip_not_allowed',
|
|
15
|
+
'invalid_item',
|
|
16
|
+
'invalid_voucher',
|
|
17
|
+
'invalid_tip',
|
|
18
|
+
'unknown_payment_method',
|
|
19
|
+
'tip_conflict',
|
|
20
|
+
'tip_recipient_missing',
|
|
21
|
+
'tip_without_goods',
|
|
22
|
+
]);
|
|
23
|
+
/**
|
|
24
|
+
* Der Zahlbetrag laesst sich aus dieser Eingabe nicht rechnen, etwa
|
|
25
|
+
* Trinkgeld mit Betrag ohne Ware (`reason: 'tip_without_goods'`).
|
|
26
|
+
*
|
|
27
|
+
* Eindeutig **nicht gesendet**: die Rechnung laeuft ganz im Paket, vor jedem
|
|
28
|
+
* Aufruf. `outcome` ist darum immer `'rejected'`; nichts ist geschehen, keine
|
|
29
|
+
* Belegnummer verbraucht, keine Karte belastet. Die Kasse sagt das dem
|
|
30
|
+
* Kassier, bevor sie ein Terminal anspricht. Entscheiden am `code` bzw.
|
|
31
|
+
* `reason`, nie an `message` (die ist fuers Protokoll).
|
|
32
|
+
*
|
|
33
|
+
* Bis 1.0.0-rc.4 warf die Rechnung hier einen `RangeError` ohne Code.
|
|
34
|
+
*/
|
|
35
|
+
class ReceiptDueError extends Error {
|
|
36
|
+
name = 'ReceiptDueError';
|
|
37
|
+
/** Stabiler Code fuer jede Ursache. */
|
|
38
|
+
code = 'receipt_due_unavailable';
|
|
39
|
+
/** Die Ursache im Einzelnen. */
|
|
40
|
+
reason;
|
|
41
|
+
/** Immer `'rejected'`: es ging nichts hinaus. */
|
|
42
|
+
outcome = 'rejected';
|
|
43
|
+
constructor(reason, message) {
|
|
44
|
+
super(`Zahlbetrag: ${message}`);
|
|
45
|
+
this.reason = reason;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.ReceiptDueError = ReceiptDueError;
|
|
49
|
+
function isReceiptDueError(error) {
|
|
50
|
+
return error instanceof ReceiptDueError;
|
|
51
|
+
}
|
|
6
52
|
const UMSATZ = new Set(['standard', 'cancellation', 'training']);
|
|
7
53
|
const TRINKGELD_ERLAUBT = new Set(['standard', 'training']);
|
|
8
54
|
const ZAHLARTEN = new Set(['cash', 'creditCard', 'online', 'uberApp', 'uberCard', 'uberCash', 'boltApp', 'boltCard', 'boltCash']);
|
|
@@ -15,7 +61,7 @@ function receiptDueBreakdown(items, vouchers, receiptType, options = {}) {
|
|
|
15
61
|
const art = belegArt(receiptType);
|
|
16
62
|
const trinkgelder = trinkgeldAuftraege(options);
|
|
17
63
|
if (trinkgelder.length > 0 && !TRINKGELD_ERLAUBT.has(art)) {
|
|
18
|
-
throw new
|
|
64
|
+
throw new ReceiptDueError('tip_not_allowed', `Trinkgeld gibt es nur bei standard und training, nicht bei "${art}".`);
|
|
19
65
|
}
|
|
20
66
|
if (!UMSATZ.has(art)) {
|
|
21
67
|
return { dueCents: 0, counterDeltaCents: 0, valueVoucherFlowCents: 0, bucketsCents: null };
|
|
@@ -45,7 +91,7 @@ function receiptDueBreakdown(items, vouchers, receiptType, options = {}) {
|
|
|
45
91
|
function belegArt(wert) {
|
|
46
92
|
const text = typeof wert === 'object' && wert !== null ? wert.value : wert;
|
|
47
93
|
if (typeof text !== 'string' || !Object.prototype.hasOwnProperty.call(index_js_1.ReceiptType, text)) {
|
|
48
|
-
throw new
|
|
94
|
+
throw new ReceiptDueError('unknown_receipt_type', `unbekannter Belegtyp "${String(text)}".`);
|
|
49
95
|
}
|
|
50
96
|
return text;
|
|
51
97
|
}
|
|
@@ -57,17 +103,17 @@ function euroToCent(euro) {
|
|
|
57
103
|
function innen(item, i) {
|
|
58
104
|
const satz = typeof item.vat === 'number' ? item.vat : item.vat?.rate;
|
|
59
105
|
if (typeof satz !== 'number' || !Number.isFinite(satz))
|
|
60
|
-
throw new
|
|
106
|
+
throw new ReceiptDueError('invalid_item', `Position ${i + 1} ohne Steuersatz.`);
|
|
61
107
|
if (!Number.isSafeInteger(item.priceCents))
|
|
62
|
-
throw new
|
|
108
|
+
throw new ReceiptDueError('invalid_item', `Position ${i + 1} hat keinen ganzen Cent-Preis.`);
|
|
63
109
|
if (typeof item.quantity !== 'number' || !Number.isFinite(item.quantity))
|
|
64
|
-
throw new
|
|
110
|
+
throw new ReceiptDueError('invalid_item', `Position ${i + 1} hat keine gueltige Menge.`);
|
|
65
111
|
const tip = item.kind === 'tip' ? (item.recipient?.owner === true ? 'owner' : 'staff') : null;
|
|
66
112
|
return { amount: item.quantity, priceOne: Math.round(item.priceCents) / 100, vat: satz, tip };
|
|
67
113
|
}
|
|
68
114
|
function gutscheinInnen(v, i) {
|
|
69
115
|
if (!Number.isSafeInteger(v.valueCents))
|
|
70
|
-
throw new
|
|
116
|
+
throw new ReceiptDueError('invalid_voucher', `Gutschein ${i + 1} hat keinen ganzen Cent-Wert.`);
|
|
71
117
|
return { action: String(v.action), type: String(v.type), value: Math.round(v.valueCents) / 100 };
|
|
72
118
|
}
|
|
73
119
|
/** Trinkgeld-Auftraege in der Reihenfolge des Servers: `tip`, dann je Zahlart die Summe der `tipCents`. */
|
|
@@ -75,7 +121,7 @@ function trinkgeldAuftraege(options) {
|
|
|
75
121
|
const raus = [];
|
|
76
122
|
const tipCents = (options.payments ?? []).some((z) => z != null && z.tipCents !== undefined);
|
|
77
123
|
if (options.tip != null && tipCents) {
|
|
78
|
-
throw new
|
|
124
|
+
throw new ReceiptDueError('tip_conflict', 'tip und payments[].tipCents gehen nicht zugleich (tip_conflict).');
|
|
79
125
|
}
|
|
80
126
|
if (options.tip != null) {
|
|
81
127
|
const tip = options.tip;
|
|
@@ -84,14 +130,14 @@ function trinkgeldAuftraege(options) {
|
|
|
84
130
|
const recipients = typeof tip === 'number' ? undefined : tip.recipients;
|
|
85
131
|
if (recipients != null) {
|
|
86
132
|
if (recipients.length === 0)
|
|
87
|
-
throw new
|
|
133
|
+
throw new ReceiptDueError('invalid_tip', 'recipients darf nicht leer sein.');
|
|
88
134
|
for (const r of recipients) {
|
|
89
135
|
pruefeCent(r.cents, 'Trinkgeld-Anteil');
|
|
90
136
|
if (typeof r.owner !== 'boolean')
|
|
91
|
-
throw new
|
|
137
|
+
throw new ReceiptDueError('invalid_tip', 'recipients[].owner muss true oder false sein.');
|
|
92
138
|
}
|
|
93
139
|
if (recipients.reduce((s, r) => s + r.cents, 0) !== cents) {
|
|
94
|
-
throw new
|
|
140
|
+
throw new ReceiptDueError('invalid_tip', 'die Anteile des Trinkgelds ergeben nicht den Betrag.');
|
|
95
141
|
}
|
|
96
142
|
raus.push({ empfaenger: recipients.map((r) => ({ cents: r.cents, owner: r.owner })) });
|
|
97
143
|
}
|
|
@@ -107,7 +153,7 @@ function trinkgeldAuftraege(options) {
|
|
|
107
153
|
pruefeCent(z.tipCents, 'tipCents');
|
|
108
154
|
const methode = typeof z.method === 'object' && z.method !== null ? z.method.value : z.method;
|
|
109
155
|
if (typeof methode !== 'string' || !ZAHLARTEN.has(methode))
|
|
110
|
-
throw new
|
|
156
|
+
throw new ReceiptDueError('unknown_payment_method', `unbekannte Zahlart "${String(methode)}".`);
|
|
111
157
|
je.set(methode, (je.get(methode) ?? 0) + z.tipCents);
|
|
112
158
|
}
|
|
113
159
|
for (const cents of je.values())
|
|
@@ -116,7 +162,7 @@ function trinkgeldAuftraege(options) {
|
|
|
116
162
|
}
|
|
117
163
|
function pruefeCent(wert, was) {
|
|
118
164
|
if (typeof wert !== 'number' || !Number.isInteger(wert) || wert <= 0) {
|
|
119
|
-
throw new
|
|
165
|
+
throw new ReceiptDueError('invalid_tip', `${was} muss eine ganze Zahl in Cent > 0 sein.`);
|
|
120
166
|
}
|
|
121
167
|
}
|
|
122
168
|
/** `tip-core.buildTipItems`: Personal in den Null-%-Satz, Inhaber anteilig auf die Saetze der Ware. */
|
|
@@ -124,13 +170,13 @@ function trinkgeldPositionen(auftrag, positionen, standard) {
|
|
|
124
170
|
const basis = warenCentsJeSatz(positionen);
|
|
125
171
|
const summe = Object.values(basis).reduce((s, c) => s + c, 0);
|
|
126
172
|
if (summe <= 0)
|
|
127
|
-
throw new
|
|
173
|
+
throw new ReceiptDueError('tip_without_goods', 'Trinkgeld braucht mindestens eine Position mit Betrag.');
|
|
128
174
|
const raus = [];
|
|
129
175
|
for (const e of auftrag.empfaenger) {
|
|
130
176
|
let owner = e.owner;
|
|
131
177
|
if (owner == null) {
|
|
132
178
|
if (standard !== 'owner' && standard !== 'staff') {
|
|
133
|
-
throw new
|
|
179
|
+
throw new ReceiptDueError('tip_recipient_missing', "tipRecipient fehlt ('owner' oder 'staff', wie der angemeldete Kassen-Benutzer).");
|
|
134
180
|
}
|
|
135
181
|
owner = standard === 'owner';
|
|
136
182
|
}
|
|
@@ -140,7 +186,7 @@ function trinkgeldPositionen(auftrag, positionen, standard) {
|
|
|
140
186
|
}
|
|
141
187
|
const teile = splitOwnerTip(e.cents, basis);
|
|
142
188
|
if (teile.length === 0)
|
|
143
|
-
throw new
|
|
189
|
+
throw new ReceiptDueError('tip_without_goods', 'Inhaber-Trinkgeld braucht mindestens eine Position mit Betrag.');
|
|
144
190
|
for (const teil of teile) {
|
|
145
191
|
if (teil.cents !== 0)
|
|
146
192
|
raus.push({ amount: 1, priceOne: teil.cents / 100, vat: teil.vat, tip: 'owner' });
|
|
@@ -6,4 +6,4 @@ export { type SheetLogoSize, type SheetLogo, type LogoDimensions, type SheetBloc
|
|
|
6
6
|
export { rasterizeLogo } from './bild.js';
|
|
7
7
|
export { type BrandMarkRaster, BRAND_MARK_RASTERS, BRAND_MARK_PATHS } from './marke-daten.js';
|
|
8
8
|
export { brandMarkImage } from './marke.js';
|
|
9
|
-
export { type ReceiptDueTip, type ReceiptDueTipRecipient, type ReceiptDueOptions, type ReceiptDueBuckets, type ReceiptDueBreakdown, receiptDueCents, receiptDueBreakdown, } from './due.js';
|
|
9
|
+
export { type ReceiptDueTip, type ReceiptDueTipRecipient, type ReceiptDueOptions, type ReceiptDueBuckets, type ReceiptDueBreakdown, type ReceiptDueErrorReason, receiptDueCents, receiptDueBreakdown, ReceiptDueError, RECEIPT_DUE_ERROR_REASONS, isReceiptDueError, } from './due.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.receiptDueBreakdown = exports.receiptDueCents = exports.brandMarkImage = exports.BRAND_MARK_PATHS = exports.BRAND_MARK_RASTERS = exports.rasterizeLogo = exports.receiptSheet = exports.qrSheetWidthFraction = exports.logoRasterSize = exports.isLogoPixelSizeAllowed = exports.logoDimensions = exports.paperSizeForChars = exports.DOTS_PER_LINE = exports.DOTS_PER_CHAR = exports.LOGO_MAX_PIXELS = exports.SHEET_LOGO_SIZES = exports.eposDirectStatus = exports.eposDirectPrint = exports.eposParseResponse = exports.eposSoapEnvelope = exports.eposServiceUrl = exports.eposImageXml = exports.eposXmlEscape = exports.eposPrintXmlResult = exports.eposPrintXml = exports.EposConnectionError = exports.CHARS_PER_PAPER_SIZE = exports.gridToText = exports.gridColumnWidths = exports.renderReceiptGrid = exports.escPosLayoutResult = exports.escPosLayoutBytes = exports.assertLogoRaster = exports.formatCents = exports.SMALL_BUSINESS_NOTICE = exports.CURRENT_LAYOUT_RULESET = exports.receiptZdaText = exports.receiptIsSmallBusinessConsistent = exports.receiptAmountsAreZero = exports.receiptIsZero = exports.receiptSignatureIsTest = exports.receiptSignatureFailed = exports.buildReceiptLayout = void 0;
|
|
3
|
+
exports.isReceiptDueError = exports.RECEIPT_DUE_ERROR_REASONS = exports.ReceiptDueError = exports.receiptDueBreakdown = exports.receiptDueCents = exports.brandMarkImage = exports.BRAND_MARK_PATHS = exports.BRAND_MARK_RASTERS = exports.rasterizeLogo = exports.receiptSheet = exports.qrSheetWidthFraction = exports.logoRasterSize = exports.isLogoPixelSizeAllowed = exports.logoDimensions = exports.paperSizeForChars = exports.DOTS_PER_LINE = exports.DOTS_PER_CHAR = exports.LOGO_MAX_PIXELS = exports.SHEET_LOGO_SIZES = exports.eposDirectStatus = exports.eposDirectPrint = exports.eposParseResponse = exports.eposSoapEnvelope = exports.eposServiceUrl = exports.eposImageXml = exports.eposXmlEscape = exports.eposPrintXmlResult = exports.eposPrintXml = exports.EposConnectionError = exports.CHARS_PER_PAPER_SIZE = exports.gridToText = exports.gridColumnWidths = exports.renderReceiptGrid = exports.escPosLayoutResult = exports.escPosLayoutBytes = exports.assertLogoRaster = exports.formatCents = exports.SMALL_BUSINESS_NOTICE = exports.CURRENT_LAYOUT_RULESET = exports.receiptZdaText = exports.receiptIsSmallBusinessConsistent = exports.receiptAmountsAreZero = exports.receiptIsZero = exports.receiptSignatureIsTest = exports.receiptSignatureFailed = exports.buildReceiptLayout = void 0;
|
|
4
4
|
var layout_js_1 = require("./layout.js");
|
|
5
5
|
Object.defineProperty(exports, "buildReceiptLayout", { enumerable: true, get: function () { return layout_js_1.buildReceiptLayout; } });
|
|
6
6
|
Object.defineProperty(exports, "receiptSignatureFailed", { enumerable: true, get: function () { return layout_js_1.receiptSignatureFailed; } });
|
|
@@ -53,3 +53,6 @@ Object.defineProperty(exports, "brandMarkImage", { enumerable: true, get: functi
|
|
|
53
53
|
var due_js_1 = require("./due.js");
|
|
54
54
|
Object.defineProperty(exports, "receiptDueCents", { enumerable: true, get: function () { return due_js_1.receiptDueCents; } });
|
|
55
55
|
Object.defineProperty(exports, "receiptDueBreakdown", { enumerable: true, get: function () { return due_js_1.receiptDueBreakdown; } });
|
|
56
|
+
Object.defineProperty(exports, "ReceiptDueError", { enumerable: true, get: function () { return due_js_1.ReceiptDueError; } });
|
|
57
|
+
Object.defineProperty(exports, "RECEIPT_DUE_ERROR_REASONS", { enumerable: true, get: function () { return due_js_1.RECEIPT_DUE_ERROR_REASONS; } });
|
|
58
|
+
Object.defineProperty(exports, "isReceiptDueError", { enumerable: true, get: function () { return due_js_1.isReceiptDueError; } });
|
|
@@ -107,3 +107,4 @@ export declare function invalidStoredPosSettings(stored: {
|
|
|
107
107
|
* weg.
|
|
108
108
|
*/
|
|
109
109
|
export declare function fromStoredArticle(id: string, stored: unknown): PosArticle;
|
|
110
|
+
export { fromStoredLayout, toStoredLayout, fromStoredPrintLogo, toStoredPrintLogo } from './layout.js';
|
package/dist/cjs/stored/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toStoredPrintLogo = exports.fromStoredPrintLogo = exports.toStoredLayout = exports.fromStoredLayout = void 0;
|
|
3
4
|
exports.fromStoredReceipt = fromStoredReceipt;
|
|
4
5
|
exports.fromStoredReceiptWithCompany = fromStoredReceiptWithCompany;
|
|
5
6
|
exports.fromStoredCompany = fromStoredCompany;
|
|
@@ -223,3 +224,9 @@ function invalidStoredPosSettings(stored) {
|
|
|
223
224
|
function fromStoredArticle(id, stored) {
|
|
224
225
|
return (0, artikel_js_1.fromPosArticlePayload)((0, draht_js_1._storedArticleToWire)(id, stored));
|
|
225
226
|
}
|
|
227
|
+
// ---- Zeilenmodell und Drucklogo ----------------------------------------------
|
|
228
|
+
var layout_js_2 = require("./layout.js");
|
|
229
|
+
Object.defineProperty(exports, "fromStoredLayout", { enumerable: true, get: function () { return layout_js_2.fromStoredLayout; } });
|
|
230
|
+
Object.defineProperty(exports, "toStoredLayout", { enumerable: true, get: function () { return layout_js_2.toStoredLayout; } });
|
|
231
|
+
Object.defineProperty(exports, "fromStoredPrintLogo", { enumerable: true, get: function () { return layout_js_2.fromStoredPrintLogo; } });
|
|
232
|
+
Object.defineProperty(exports, "toStoredPrintLogo", { enumerable: true, get: function () { return layout_js_2.toStoredPrintLogo; } });
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zeilenmodell und Drucklogo in der inneren Form (deutsch) <-> Form 1.0.
|
|
3
|
+
*
|
|
4
|
+
* Die innere Form ist die, die das Backend speichert und am Draht `/api`
|
|
5
|
+
* (Kanal intern) spricht, und die, in der 0.x das Zeilenmodell im Browser
|
|
6
|
+
* zwischengespeichert hat:
|
|
7
|
+
*
|
|
8
|
+
* - Zeilenmodell: `regelwerk` statt `ruleset`, Bannerzeilen mit `ton`
|
|
9
|
+
* (`belegart`, `warnung`) statt `tone` (`receipt_type`, `warning`);
|
|
10
|
+
* - Drucklogo (`createPrintJob`, Parameter `logo`): `stufe`, `pxBreite`,
|
|
11
|
+
* `pxHoehe`, `breite`, `hoehe`, `zeilen` (Base64, MSB zuerst) statt
|
|
12
|
+
* [PrintLogo] (`size`, `pixelWidth`, `pixelHeight`, `raster`).
|
|
13
|
+
*
|
|
14
|
+
* Dieselben Namen wie der Rand des Backends unter `/v3` (Vokabular
|
|
15
|
+
* `createPrintJob`/`getReceiptWithCompany`: `layout.ruleset` <-> `regelwerk`,
|
|
16
|
+
* `lines[].tone` <-> `ton`, Katalog `LAYOUT_TON`, `logo.scale` <-> `stufe` ...).
|
|
17
|
+
* Ein unbekannter Ton geht woertlich durch, wie ihn auch der Rand durchreicht.
|
|
18
|
+
*/
|
|
19
|
+
import type { ReceiptLayout } from '../receipt/layout.js';
|
|
20
|
+
import type { PrintLogo } from '../receipt/layout-escpos.js';
|
|
21
|
+
/**
|
|
22
|
+
* Ein Zeilenmodell in der inneren Form (0.x-Zwischenspeicher, Antwort unter
|
|
23
|
+
* `/api`) als [ReceiptLayout]. Nimmt auch die Form 1.0 an und laesst sie
|
|
24
|
+
* unveraendert; so liest eine Funktion alte und neue Eintraege. Die
|
|
25
|
+
* Reihenfolge der Schluessel bleibt.
|
|
26
|
+
*
|
|
27
|
+
* `null`, wenn es kein ganzes Zeilenmodell ist: fehlt, kein Objekt, keine
|
|
28
|
+
* oder leere `lines`, eine Zeile, die kein Objekt ist, oder kein `paperSize`.
|
|
29
|
+
* Dann baut der Aufrufer neu (`receiptLayoutFromResult` aus Beleg, Firma und
|
|
30
|
+
* `testCashregister`/`testSignature`), und TESTKASSE und die Warnzeilen
|
|
31
|
+
* stehen wieder da. Ein halb lesbares Zeilenmodell gewaenne sonst immer.
|
|
32
|
+
*/
|
|
33
|
+
export declare function fromStoredLayout(stored: unknown): ReceiptLayout | null;
|
|
34
|
+
/**
|
|
35
|
+
* Ein [ReceiptLayout] in der inneren Form, fuer einen Aufruf unter `/api`
|
|
36
|
+
* (`createPrintJob`, `renderBelegPdfAdmin`) oder einen Leser der 0.x-Form,
|
|
37
|
+
* in der Reihenfolge der Schluessel wie 0.31 (`lines`, `paperSize`,
|
|
38
|
+
* `regelwerk`, sofern die Eingabe sie so hat). Ohne diese Uebersetzung liest
|
|
39
|
+
* das Backend den Ton nicht, und der Rahmen der Warnzeilen (TESTKASSE,
|
|
40
|
+
* Sicherheitseinrichtung ausgefallen) und des Belegart-Aufdrucks fiele am
|
|
41
|
+
* Bon und im PDF weg.
|
|
42
|
+
*/
|
|
43
|
+
export declare function toStoredLayout(layout: ReceiptLayout): Record<string, unknown>;
|
|
44
|
+
/**
|
|
45
|
+
* Ein [PrintLogo] in der inneren Form des Druckjobs (`createPrintJob` unter
|
|
46
|
+
* `/api`): dieselben Punkte, die das Paket unter `/v3` als `logo` schickt.
|
|
47
|
+
*/
|
|
48
|
+
export declare function toStoredPrintLogo(logo: PrintLogo): Record<string, unknown>;
|
|
49
|
+
/**
|
|
50
|
+
* Ein Drucklogo in der inneren Form als [PrintLogo]. Die Zeilen sind die
|
|
51
|
+
* Rasterzeilen als Base64 (MSB zuerst, jede Zeile auf volle Bytes
|
|
52
|
+
* aufgefuellt). Wirft `KasseneckValidationError`, wenn Stufe, Masse oder
|
|
53
|
+
* Zeilen nicht zusammenpassen.
|
|
54
|
+
*/
|
|
55
|
+
export declare function fromStoredPrintLogo(stored: unknown): PrintLogo;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fromStoredLayout = fromStoredLayout;
|
|
4
|
+
exports.toStoredLayout = toStoredLayout;
|
|
5
|
+
exports.toStoredPrintLogo = toStoredPrintLogo;
|
|
6
|
+
exports.fromStoredPrintLogo = fromStoredPrintLogo;
|
|
7
|
+
const escpos_js_1 = require("../printing/escpos.js");
|
|
8
|
+
const errors_js_1 = require("../client/errors.js");
|
|
9
|
+
const istObjekt = (w) => w !== null && typeof w === 'object' && !Array.isArray(w);
|
|
10
|
+
const TON_NACH_1_0 = { belegart: 'receipt_type', warnung: 'warning' };
|
|
11
|
+
const TON_NACH_INNEN = { receipt_type: 'belegart', warning: 'warnung' };
|
|
12
|
+
/**
|
|
13
|
+
* Ein Objekt mit umbenannten Schluesseln, an derselben Stelle: die
|
|
14
|
+
* Reihenfolge bleibt, damit ein gespeicherter Eintrag byte-gleich
|
|
15
|
+
* zurueckkommt (Hash- und Cache-Vergleiche). `werte` ersetzt den Wert eines
|
|
16
|
+
* (alten) Schluessels.
|
|
17
|
+
*/
|
|
18
|
+
function umbenannt(o, namen, werte = {}) {
|
|
19
|
+
const raus = {};
|
|
20
|
+
for (const [k, w] of Object.entries(o)) {
|
|
21
|
+
const neu = namen[k] ?? k;
|
|
22
|
+
// Traegt die Eingabe beide Namen, gewinnt der schon neue.
|
|
23
|
+
if (neu !== k && Object.prototype.hasOwnProperty.call(o, neu))
|
|
24
|
+
continue;
|
|
25
|
+
raus[neu] = werte[k] ? werte[k](w) : w;
|
|
26
|
+
}
|
|
27
|
+
return raus;
|
|
28
|
+
}
|
|
29
|
+
const tonNach = (tabelle) => (w) => (typeof w === 'string' ? tabelle[w] ?? w : w);
|
|
30
|
+
/**
|
|
31
|
+
* Ein Zeilenmodell in der inneren Form (0.x-Zwischenspeicher, Antwort unter
|
|
32
|
+
* `/api`) als [ReceiptLayout]. Nimmt auch die Form 1.0 an und laesst sie
|
|
33
|
+
* unveraendert; so liest eine Funktion alte und neue Eintraege. Die
|
|
34
|
+
* Reihenfolge der Schluessel bleibt.
|
|
35
|
+
*
|
|
36
|
+
* `null`, wenn es kein ganzes Zeilenmodell ist: fehlt, kein Objekt, keine
|
|
37
|
+
* oder leere `lines`, eine Zeile, die kein Objekt ist, oder kein `paperSize`.
|
|
38
|
+
* Dann baut der Aufrufer neu (`receiptLayoutFromResult` aus Beleg, Firma und
|
|
39
|
+
* `testCashregister`/`testSignature`), und TESTKASSE und die Warnzeilen
|
|
40
|
+
* stehen wieder da. Ein halb lesbares Zeilenmodell gewaenne sonst immer.
|
|
41
|
+
*/
|
|
42
|
+
function fromStoredLayout(stored) {
|
|
43
|
+
if (!istObjekt(stored) || !Array.isArray(stored.lines) || stored.lines.length === 0)
|
|
44
|
+
return null;
|
|
45
|
+
if (!stored.lines.every(istObjekt))
|
|
46
|
+
return null;
|
|
47
|
+
if (typeof stored.paperSize !== 'string' || stored.paperSize === '')
|
|
48
|
+
return null;
|
|
49
|
+
return umbenannt(stored, { regelwerk: 'ruleset' }, {
|
|
50
|
+
lines: (zeilen) => zeilen.map((z) => umbenannt(z, { ton: 'tone' }, { ton: tonNach(TON_NACH_1_0) })),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Ein [ReceiptLayout] in der inneren Form, fuer einen Aufruf unter `/api`
|
|
55
|
+
* (`createPrintJob`, `renderBelegPdfAdmin`) oder einen Leser der 0.x-Form,
|
|
56
|
+
* in der Reihenfolge der Schluessel wie 0.31 (`lines`, `paperSize`,
|
|
57
|
+
* `regelwerk`, sofern die Eingabe sie so hat). Ohne diese Uebersetzung liest
|
|
58
|
+
* das Backend den Ton nicht, und der Rahmen der Warnzeilen (TESTKASSE,
|
|
59
|
+
* Sicherheitseinrichtung ausgefallen) und des Belegart-Aufdrucks fiele am
|
|
60
|
+
* Bon und im PDF weg.
|
|
61
|
+
*/
|
|
62
|
+
function toStoredLayout(layout) {
|
|
63
|
+
if (!istObjekt(layout) || !Array.isArray(layout.lines)) {
|
|
64
|
+
throw new errors_js_1.KasseneckValidationError('toStoredLayout', 'layout ohne lines', 'request');
|
|
65
|
+
}
|
|
66
|
+
return umbenannt(layout, { ruleset: 'regelwerk' }, {
|
|
67
|
+
lines: (zeilen) => zeilen.map((z) => (istObjekt(z) ? umbenannt(z, { tone: 'ton' }, { tone: tonNach(TON_NACH_INNEN) }) : z)),
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Ein [PrintLogo] in der inneren Form des Druckjobs (`createPrintJob` unter
|
|
72
|
+
* `/api`): dieselben Punkte, die das Paket unter `/v3` als `logo` schickt.
|
|
73
|
+
*/
|
|
74
|
+
function toStoredPrintLogo(logo) {
|
|
75
|
+
return {
|
|
76
|
+
stufe: logo.size, pxBreite: logo.pixelWidth, pxHoehe: logo.pixelHeight,
|
|
77
|
+
breite: logo.raster.width, hoehe: logo.raster.height, zeilen: (0, escpos_js_1.rasterRowsBase64)(logo.raster),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
const STUFEN = new Set(['S', 'M', 'L', 'XL']);
|
|
81
|
+
const ganz = (w) => typeof w === 'number' && Number.isInteger(w) && w > 0;
|
|
82
|
+
/**
|
|
83
|
+
* Ein Drucklogo in der inneren Form als [PrintLogo]. Die Zeilen sind die
|
|
84
|
+
* Rasterzeilen als Base64 (MSB zuerst, jede Zeile auf volle Bytes
|
|
85
|
+
* aufgefuellt). Wirft `KasseneckValidationError`, wenn Stufe, Masse oder
|
|
86
|
+
* Zeilen nicht zusammenpassen.
|
|
87
|
+
*/
|
|
88
|
+
function fromStoredPrintLogo(stored) {
|
|
89
|
+
const name = 'fromStoredPrintLogo';
|
|
90
|
+
if (!istObjekt(stored))
|
|
91
|
+
throw new errors_js_1.KasseneckValidationError(name, 'kein Logo-Objekt', 'request');
|
|
92
|
+
const { stufe, pxBreite, pxHoehe, breite, hoehe, zeilen } = stored;
|
|
93
|
+
if (typeof stufe !== 'string' || !STUFEN.has(stufe))
|
|
94
|
+
throw new errors_js_1.KasseneckValidationError(name, 'stufe ist nicht S, M, L oder XL', 'request');
|
|
95
|
+
if (!ganz(pxBreite) || !ganz(pxHoehe) || !ganz(breite) || !ganz(hoehe)) {
|
|
96
|
+
throw new errors_js_1.KasseneckValidationError(name, 'pxBreite, pxHoehe, breite und hoehe muessen ganze Zahlen > 0 sein', 'request');
|
|
97
|
+
}
|
|
98
|
+
if (typeof zeilen !== 'string')
|
|
99
|
+
throw new errors_js_1.KasseneckValidationError(name, 'zeilen fehlt', 'request');
|
|
100
|
+
let binaer;
|
|
101
|
+
try {
|
|
102
|
+
binaer = atob(zeilen);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
throw new errors_js_1.KasseneckValidationError(name, 'zeilen ist kein Base64', 'request');
|
|
106
|
+
}
|
|
107
|
+
const byteJeZeile = Math.ceil(breite / 8);
|
|
108
|
+
if (binaer.length !== byteJeZeile * hoehe)
|
|
109
|
+
throw new errors_js_1.KasseneckValidationError(name, 'zeilen passen nicht zu breite und hoehe', 'request');
|
|
110
|
+
const dots = new Uint8Array(breite * hoehe);
|
|
111
|
+
for (let y = 0; y < hoehe; y++) {
|
|
112
|
+
for (let x = 0; x < breite; x++) {
|
|
113
|
+
if (binaer.charCodeAt(y * byteJeZeile + (x >> 3)) & (0x80 >> (x & 7)))
|
|
114
|
+
dots[y * breite + x] = 1;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
const raster = { width: breite, height: hoehe, dots };
|
|
118
|
+
return { size: stufe, pixelWidth: pxBreite, pixelHeight: pxHoehe, raster };
|
|
119
|
+
}
|
package/dist/cjs/version.d.ts
CHANGED
package/dist/cjs/version.js
CHANGED
package/dist/esm/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, type Voucher, type VoucherPayload, toVoucherPayload, fromVoucherPayload, voucherIsValid, type Receipt, type RegistrationInfo, type ReceiptPayload, type ReceiptPayloadRead, toReceiptPayload, fromReceiptPayload, receiptSubSumCents, receiptSumCents, type CancellationOf, type CancellationItem, type Cancellation, type CancellationReason, type CancellationErrorCode, type CancellationStatus, CANCELLATION_REASONS, CANCELLATION_STATUSES, CANCELLATION_ERROR_CODES, CANCELLATION_RESERVATION_MS, isCancellationReason, 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, type ReceiptErrorCode, type ReceiptFieldError, RECEIPT_ERROR_CODES, isReceiptErrorCode, receiptErrorCode, isReceiptError, receiptFieldErrors, remainingQuantities, type ReceiptCompany, type ReceiptCompanyPayload, fromReceiptCompanyPayload, receiptCompanyTaxInfo, type Cashregister, type CashregisterOnboarding, type CashregisterPayload, type CashregisterOnboardingPayload, 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 KasseneckTransport, type KasseneckBinaryTransport, ALL_CALLS, type ApiCall, PUBLIC_CALLS, POS_CALLS, type PublicCall, type PosCall, createTransport, createBinaryTransport, 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, downloadDailyReport, downloadMonthlyReport, getReportV2, type ReportV2, type ReportV2Metadata, type ReportV2Options, 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, receiptDueCents, receiptDueBreakdown, } 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, } 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, } from './pos/index.js';
|
package/dist/esm/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { ReceiptType, VatRate, KeckPaymentMethod, CreditCardProvider, VoucherType, VoucherAction, StripeLinkMode, } from './enums/index.js';
|
|
2
2
|
export { toReceiptItemPayload, fromReceiptItemPayload, receiptItemTotalCents, receiptItemIsValid, negateReceiptItem, isTipItem, toVoucherPayload, fromVoucherPayload, voucherIsValid, toReceiptPayload, fromReceiptPayload, receiptSubSumCents, receiptSumCents, CANCELLATION_REASONS, CANCELLATION_STATUSES, CANCELLATION_ERROR_CODES, CANCELLATION_RESERVATION_MS, isCancellationReason, isCancellationErrorCode, cancellationErrorCode, isCancellationError, cancellationFieldErrors, fromReceiptPaymentPayload, toReceiptPaymentPayload, PAYMENT_ERROR_CODES, isPaymentErrorCode, paymentErrorCode, isPaymentError, paymentFieldErrors, RECEIPT_EMAIL_ERROR_CODES, RECEIPT_EMAIL_SEND_ERROR_CODES, RECEIPT_EMAIL_VIAS, isReceiptEmailErrorCode, receiptEmailErrorCode, isReceiptEmailError, receiptEmailFieldErrors, RECEIPT_ERROR_CODES, isReceiptErrorCode, receiptErrorCode, isReceiptError, receiptFieldErrors, remainingQuantities, fromReceiptCompanyPayload, receiptCompanyTaxInfo, fromCashregisterPayload, fromReceiptSummaryPayload, ZERO_KINDS, isZeroKind, reportMonthFromDate, previousReportMonth, nextReportMonth, reportMonthKey, reportMonthReadable, toStripeUrlSessionPayload, fromStripeUrlSessionPayload, toHobexReceiptPayload, fromHobexReceiptPayload, hobexReceiptToCardPaymentData, hobexReceiptNeedsSignature, } from './models/index.js';
|
|
3
3
|
export { apiKeyAuth, registerUserAuth, DEFAULT_BASE_URL, POS_BASE_URL, DEFAULT_TIMEOUT_MS, ALL_CALLS, PUBLIC_CALLS, POS_CALLS, createTransport, createBinaryTransport, KasseneckApiError, KasseneckAuthError, KasseneckHttpError, KasseneckNetworkError, KasseneckValidationError, CLIENT_ERROR_CODES, isKasseneckApiError, isKasseneckAuthError, isKasseneckHttpError, isKasseneckNetworkError, isKasseneckValidationError, isOutcomeUnknown, sellReceipt, sellReceiptWithCompany, paymentsExpectedCents, cardRefundReference, receiptLayoutFromResult, cancelReceipt, zeroReceipt, getReceipt, getReceiptWithCompany, generateFullReceiptId, getFirstReceiptDate, listMyReceipts, listMyCashregisters, checkVoucherCombinationError, sendReceiptEmail, downloadDailyReport, downloadMonthlyReport, getReportV2, getCashboxStatus, getSignatureStatus, createKasseneckApi, } from './client/index.js';
|
|
4
|
-
export { receiptDueCents, receiptDueBreakdown, } from './receipt/due.js';
|
|
4
|
+
export { receiptDueCents, receiptDueBreakdown, ReceiptDueError, RECEIPT_DUE_ERROR_REASONS, isReceiptDueError, } from './receipt/due.js';
|
|
5
5
|
export { parseServerTimeStamp, toViennaWallClock } from './vienna-time.js';
|
|
6
6
|
export { POS_BUSINESS_DEFAULTS, POS_DEVICE_DEFAULTS, mergePosSettings, fromArticleGroupPayload, fromPosArticlePayload, listMyArticleGroups, listMyArticles, getPosSettings, setMyPosSettings, setMyRegisterDeviceSettings, distributeDiscount, cancelScopeOf, receiptsScopeOf, } from './pos/index.js';
|
package/dist/esm/pos/index.d.ts
CHANGED
|
@@ -12,4 +12,4 @@ export { distributeDiscount } from '../receipt/discount.js';
|
|
|
12
12
|
export { cancelScopeOf, receiptsScopeOf, type RegisterScope, type RegisterUserPerms } from '../register/pairing.js';
|
|
13
13
|
export { type NetworkPrinter, type PrintJob, type PrintJobStatus, PRINT_JOB_STATUSES, type PrintJobSource, PRINT_JOB_SOURCES, isPrintJobFinished, type CreatePrintJobOptions, listMyPrinters, createPrintJob, getPrintJob, } from './drucker.js';
|
|
14
14
|
export { listMyTipRecipients } from './trinkgeld.js';
|
|
15
|
-
export { MESSAGES, ERROR_RULES, messageText, messageAppliesTo, RECEIPT_EMAIL_ERROR_MESSAGES, receiptEmailErrorMessage, CANCELLATION_PAYMENT_ERROR_MESSAGES, cancellationPaymentErrorMessage, LABELS, labelText, type TextEntry, type MessageKey, type ErrorKind, type Surface, type ReceiptEmailMessageCode, type CancellationPaymentMessageCode, type LabelKey, } from './texte.js';
|
|
15
|
+
export { MESSAGES, ERROR_RULES, ERROR_CODE_RULES, ERROR_OUTCOME_RULES, CALLS_WITH_EFFECT, findErrorRule, messageOutcome, messageText, messageAppliesTo, RECEIPT_EMAIL_ERROR_MESSAGES, receiptEmailErrorMessage, CANCELLATION_PAYMENT_ERROR_MESSAGES, cancellationPaymentErrorMessage, LABELS, labelText, type TextEntry, type MessageKey, type ErrorKind, type ErrorRule, type ErrorRuleDetail, type Surface, type ReceiptEmailMessageCode, type CancellationPaymentMessageCode, type LabelKey, } from './texte.js';
|
package/dist/esm/pos/index.js
CHANGED
|
@@ -17,4 +17,4 @@ export { cancelScopeOf, receiptsScopeOf } from '../register/pairing.js';
|
|
|
17
17
|
export { PRINT_JOB_STATUSES, PRINT_JOB_SOURCES, isPrintJobFinished, listMyPrinters, createPrintJob, getPrintJob, } from './drucker.js';
|
|
18
18
|
export { listMyTipRecipients } from './trinkgeld.js';
|
|
19
19
|
// Was die Kasse selbst sagt: ein Katalog fuer Browser-Kasse und App.
|
|
20
|
-
export { MESSAGES, ERROR_RULES, messageText, messageAppliesTo, RECEIPT_EMAIL_ERROR_MESSAGES, receiptEmailErrorMessage, CANCELLATION_PAYMENT_ERROR_MESSAGES, cancellationPaymentErrorMessage, LABELS, labelText, } from './texte.js';
|
|
20
|
+
export { MESSAGES, ERROR_RULES, ERROR_CODE_RULES, ERROR_OUTCOME_RULES, CALLS_WITH_EFFECT, findErrorRule, messageOutcome, messageText, messageAppliesTo, RECEIPT_EMAIL_ERROR_MESSAGES, receiptEmailErrorMessage, CANCELLATION_PAYMENT_ERROR_MESSAGES, cancellationPaymentErrorMessage, LABELS, labelText, } from './texte.js';
|
package/dist/esm/pos/texte.d.ts
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
* `only`), die Platzhalter und die Arten der Fehlerregeln (Abschnitte
|
|
21
21
|
* `placeholders` und `structure`).
|
|
22
22
|
*/
|
|
23
|
+
import { type ErrorOutcome } from '../client/errors.js';
|
|
23
24
|
export type Surface = 'web' | 'app';
|
|
24
25
|
export interface TextEntry {
|
|
25
26
|
readonly text: string;
|
|
@@ -35,10 +36,19 @@ declare const MELDUNGEN_ROH: {
|
|
|
35
36
|
readonly 'network.timeout': {
|
|
36
37
|
readonly text: "Der Server antwortet nicht. Bitte die Internetverbindung prüfen und erneut versuchen.";
|
|
37
38
|
};
|
|
39
|
+
readonly 'network.outcome_unknown': {
|
|
40
|
+
readonly text: "Der Server hat nicht geantwortet, der Vorgang kann trotzdem gebucht sein. Bitte vor einem neuen Versuch prüfen, ob der letzte Vorgang schon gebucht ist.";
|
|
41
|
+
};
|
|
38
42
|
readonly 'server.unexpected': {
|
|
39
43
|
readonly text: "Der Server hat unerwartet geantwortet (HTTP {status}). Bitte den Support verständigen.";
|
|
40
44
|
readonly placeholders: readonly ["status"];
|
|
41
45
|
};
|
|
46
|
+
readonly 'server.connection_disturbed': {
|
|
47
|
+
readonly text: "Die Verbindung zum Kassenserver ist gestört. Bitte kurz warten und erneut versuchen.";
|
|
48
|
+
};
|
|
49
|
+
readonly 'server.response_unreadable': {
|
|
50
|
+
readonly text: "Die Antwort des Kassenservers war nicht lesbar. Bitte die Kasse neu öffnen und vor einem neuen Versuch prüfen, ob der letzte Vorgang schon gebucht ist.";
|
|
51
|
+
};
|
|
42
52
|
readonly 'pairing.code_missing': {
|
|
43
53
|
readonly text: "Bitte den Kopplungs-Code eingeben.";
|
|
44
54
|
};
|
|
@@ -543,8 +553,8 @@ export type MessageKey = keyof typeof MELDUNGEN_ROH;
|
|
|
543
553
|
export declare const MESSAGES: Record<MessageKey, TextEntry>;
|
|
544
554
|
/**
|
|
545
555
|
* In welcher Reihenfolge ein Fehler eingeordnet wird, auf beiden Seiten
|
|
546
|
-
* dieselbe.
|
|
547
|
-
* (`behavior`) oder
|
|
556
|
+
* dieselbe. Genau eine Regel je Art (`kind`), mit einem Verhalten
|
|
557
|
+
* (`behavior`) oder dem Schluessel des Satzes (`key`). Die Arten:
|
|
548
558
|
* api - HTTP 200, `status:'error'`: der Satz des Backends, woertlich
|
|
549
559
|
* (`server_text`)
|
|
550
560
|
* plain_text - schon fuer den Bildschirm geschrieben: sein eigener Text
|
|
@@ -557,6 +567,11 @@ export declare const MESSAGES: Record<MessageKey, TextEntry>;
|
|
|
557
567
|
* (`fallback`)
|
|
558
568
|
* Unter 0.x hiessen sie `klartext`, `zeitablauf`, `netz`, `unerwartet`,
|
|
559
569
|
* `sonst` (Tabelle in `fixtures/renames-1.0.json`).
|
|
570
|
+
*
|
|
571
|
+
* Seit 1.0.0-rc.5 verfeinern [ERROR_CODE_RULES] und [ERROR_OUTCOME_RULES]
|
|
572
|
+
* diese Liste; sie stehen bewusst getrennt, damit ein Leser, der nur nach
|
|
573
|
+
* `kind` sucht, weiter genau den Satz von rc.4 zeigt. [findErrorRule] wendet
|
|
574
|
+
* alle drei in der richtigen Reihenfolge an.
|
|
560
575
|
*/
|
|
561
576
|
export declare const ERROR_RULES: readonly [{
|
|
562
577
|
readonly kind: "api";
|
|
@@ -578,6 +593,73 @@ export declare const ERROR_RULES: readonly [{
|
|
|
578
593
|
readonly behavior: "fallback";
|
|
579
594
|
}];
|
|
580
595
|
export type ErrorKind = (typeof ERROR_RULES)[number]['kind'];
|
|
596
|
+
/**
|
|
597
|
+
* Regeln je Code (`error.code`), vor der Regel der Art: sie ersetzen den
|
|
598
|
+
* technischen Satz des Pakets bzw. des Rands durch einen Menschentext. Der
|
|
599
|
+
* technische Satz bleibt in `error.message` fuers Protokoll.
|
|
600
|
+
* - `dialect_mismatch`, `response_translation_failed`, `response_unreadable`:
|
|
601
|
+
* Ausgang unklar, der Vorgang kann gebucht sein; der Satz raet nie zum
|
|
602
|
+
* Wiederholen, sondern zum Nachsehen.
|
|
603
|
+
* - `route_missing`, `not_found`, `internal_translation_error`: am Server
|
|
604
|
+
* geschah nichts, ein neuer Versuch ist sicher (auch auf den Geldwegen:
|
|
605
|
+
* alle drei stehen in `PAYMENT_CALL_REJECTED_CODES`).
|
|
606
|
+
*/
|
|
607
|
+
export declare const ERROR_CODE_RULES: readonly [{
|
|
608
|
+
readonly kind: "api";
|
|
609
|
+
readonly codes: readonly ["dialect_mismatch", "response_translation_failed", "response_unreadable"];
|
|
610
|
+
readonly key: "server.response_unreadable";
|
|
611
|
+
}, {
|
|
612
|
+
readonly kind: "api";
|
|
613
|
+
readonly codes: readonly ["route_missing", "not_found", "internal_translation_error"];
|
|
614
|
+
readonly key: "server.connection_disturbed";
|
|
615
|
+
}];
|
|
616
|
+
/**
|
|
617
|
+
* Regeln je Ausgang, nach den Code-Regeln und vor der Regel der Art: eine
|
|
618
|
+
* Frist oder ein Netzfehler auf einem Aufruf mit Wirkung (Ausgang unklar,
|
|
619
|
+
* siehe [messageOutcome]) raet nie zum Wiederholen. Ein Netzfehler auf einem
|
|
620
|
+
* Aufruf ohne Wirkung behaelt den Satz von rc.4 („erneut versuchen“).
|
|
621
|
+
*/
|
|
622
|
+
export declare const ERROR_OUTCOME_RULES: readonly [{
|
|
623
|
+
readonly kind: "timeout";
|
|
624
|
+
readonly outcome: "unknown";
|
|
625
|
+
readonly key: "network.outcome_unknown";
|
|
626
|
+
}, {
|
|
627
|
+
readonly kind: "network";
|
|
628
|
+
readonly outcome: "unknown";
|
|
629
|
+
readonly key: "network.outcome_unknown";
|
|
630
|
+
}];
|
|
631
|
+
export type ErrorRule = (typeof ERROR_RULES)[number] | (typeof ERROR_CODE_RULES)[number] | (typeof ERROR_OUTCOME_RULES)[number];
|
|
632
|
+
/** Was ueber einen Fehler bekannt ist, ausser seiner Art. */
|
|
633
|
+
export interface ErrorRuleDetail {
|
|
634
|
+
/** `error.code` eines `KasseneckApiError`. */
|
|
635
|
+
code?: string | null;
|
|
636
|
+
/** Ausgang fuer den Satz, siehe [messageOutcome]. */
|
|
637
|
+
outcome?: ErrorOutcome | null;
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* Die Regel fuer einen Fehler: zuerst eine Code-Regel mit passender Art und
|
|
641
|
+
* passendem `code`, dann eine Ausgangs-Regel mit passender Art und
|
|
642
|
+
* passendem `outcome`, sonst die Regel der Art aus [ERROR_RULES]. Beide
|
|
643
|
+
* Kassen ordnen so ein.
|
|
644
|
+
*/
|
|
645
|
+
export declare function findErrorRule(kind: ErrorKind, detail?: ErrorRuleDetail): ErrorRule;
|
|
646
|
+
/**
|
|
647
|
+
* Kassen-Aufrufe mit Wirkung, die sich nach einem Netzfehler nicht gefahrlos
|
|
648
|
+
* wiederholen lassen: die sechs, deren Ausgang das Paket selbst als unklar
|
|
649
|
+
* fuehrt (Beleg, auch Null- und Startbeleg ueber `createReceipt`, Storno,
|
|
650
|
+
* FinanzOnline, die drei Geldwege), dazu der Druckjob (zweiter Bon) und die
|
|
651
|
+
* Belegmail (zweite Mail). Ob die Anfrage vor dem Abriss schon draussen war,
|
|
652
|
+
* sieht das Paket nicht (fetch wirft in beiden Faellen gleich); darum gilt
|
|
653
|
+
* hier immer der vorsichtige Satz.
|
|
654
|
+
*/
|
|
655
|
+
export declare const CALLS_WITH_EFFECT: readonly ["createReceipt", "cancelReceipt", "financeWebService", "hobexPayApi", "hobexRefundApi", "stripeCaptureIntent", "createPrintJob", "sendReceiptEmail"];
|
|
656
|
+
/**
|
|
657
|
+
* Der Ausgang, nach dem der Satz gewaehlt wird: `'unknown'`, wenn das Paket
|
|
658
|
+
* ihn als unklar fuehrt ([isOutcomeUnknown]) oder wenn eine Frist bzw. ein
|
|
659
|
+
* Netzfehler einen Aufruf aus [CALLS_WITH_EFFECT] traf; sonst der Ausgang
|
|
660
|
+
* des Fehlers (`'rejected'`) bzw. `undefined` fuer fremde Fehler.
|
|
661
|
+
*/
|
|
662
|
+
export declare function messageOutcome(error: unknown): ErrorOutcome | undefined;
|
|
581
663
|
/**
|
|
582
664
|
* Beleg per E-Mail senden: welcher `code` des Backends welchen Satz bekommt.
|
|
583
665
|
*
|
|
@@ -662,6 +744,13 @@ declare const BESCHRIFTUNGEN_ROH: {
|
|
|
662
744
|
readonly 'pairing.pair_again': {
|
|
663
745
|
readonly text: "Neu koppeln";
|
|
664
746
|
};
|
|
747
|
+
readonly 'register.device_unnamed': {
|
|
748
|
+
readonly text: "Kasse";
|
|
749
|
+
};
|
|
750
|
+
readonly 'login.locked_seconds': {
|
|
751
|
+
readonly text: "Noch {seconds} s gesperrt";
|
|
752
|
+
readonly placeholders: readonly ["seconds"];
|
|
753
|
+
};
|
|
665
754
|
readonly 'logout.question': {
|
|
666
755
|
readonly text: "Wirklich abmelden?";
|
|
667
756
|
};
|
|
@@ -731,6 +820,10 @@ declare const BESCHRIFTUNGEN_ROH: {
|
|
|
731
820
|
readonly 'split.remaining': {
|
|
732
821
|
readonly text: "Rest";
|
|
733
822
|
};
|
|
823
|
+
readonly 'split.remaining_with_rounding': {
|
|
824
|
+
readonly text: "Rest inkl. Rundung {amount} ({cents} ct)";
|
|
825
|
+
readonly placeholders: readonly ["amount", "cents"];
|
|
826
|
+
};
|
|
734
827
|
readonly 'split.divide': {
|
|
735
828
|
readonly text: "÷ {n}";
|
|
736
829
|
readonly placeholders: readonly ["n"];
|