@kreiseck/kasseneck-api 1.10.1 → 1.11.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 +241 -0
- package/dist/cjs/client/aufrufe.d.ts +5 -5
- package/dist/cjs/client/aufrufe.js +22 -2
- package/dist/cjs/client/errors.js +2 -0
- package/dist/cjs/client/receipts.d.ts +34 -1
- package/dist/cjs/client/receipts.js +34 -1
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js +9 -2
- package/dist/cjs/inventory/vertrag.d.ts +1 -1
- package/dist/cjs/inventory/vertrag.js +2 -0
- package/dist/cjs/invoice/vertrag.d.ts +1 -1
- package/dist/cjs/invoice/vertrag.js +2 -0
- package/dist/cjs/models/cancellation.d.ts +49 -1
- package/dist/cjs/models/cancellation.js +139 -1
- package/dist/cjs/models/index.d.ts +1 -1
- package/dist/cjs/models/index.js +9 -2
- package/dist/cjs/models/payment-errors.d.ts +1 -1
- package/dist/cjs/models/payment-errors.js +2 -0
- package/dist/cjs/models/receipt-email.d.ts +1 -1
- package/dist/cjs/models/receipt-email.js +2 -0
- package/dist/cjs/models/receipt-errors.d.ts +1 -1
- package/dist/cjs/models/receipt-errors.js +2 -0
- package/dist/cjs/models/receipt-item.d.ts +10 -0
- package/dist/cjs/models/receipt-item.js +3 -0
- package/dist/cjs/pos/client.js +10 -0
- package/dist/cjs/pos/errors.d.ts +4 -3
- package/dist/cjs/pos/errors.js +21 -2
- package/dist/cjs/pos/index.d.ts +6 -2
- package/dist/cjs/pos/index.js +33 -3
- package/dist/cjs/pos/schicht-lesen.d.ts +39 -0
- package/dist/cjs/pos/schicht-lesen.js +405 -0
- package/dist/cjs/pos/schicht-typen.d.ts +380 -0
- package/dist/cjs/pos/schicht-typen.js +59 -0
- package/dist/cjs/pos/schicht.d.ts +208 -0
- package/dist/cjs/pos/schicht.js +235 -0
- package/dist/cjs/pos/settings.d.ts +37 -1
- package/dist/cjs/pos/settings.js +43 -3
- package/dist/cjs/pos/texte.d.ts +627 -0
- package/dist/cjs/pos/texte.js +236 -0
- package/dist/cjs/react/index.js +1 -1
- package/dist/cjs/receipt/grid.js +2 -2
- package/dist/cjs/receipt/layout.d.ts +5 -0
- package/dist/cjs/receipt/shift-sheet.d.ts +33 -0
- package/dist/cjs/receipt/shift-sheet.js +207 -0
- package/dist/cjs/register/errors.d.ts +1 -1
- package/dist/cjs/register/errors.js +2 -0
- package/dist/cjs/stored/draht.d.ts +1 -1
- package/dist/cjs/stored/draht.js +4 -3
- package/dist/cjs/stored/einstellungen.js +26 -3
- package/dist/cjs/stored/vokabular.d.ts +1 -1
- package/dist/cjs/stored/vokabular.js +118 -12
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/client/aufrufe.d.ts +5 -5
- package/dist/esm/client/aufrufe.js +22 -2
- package/dist/esm/client/errors.js +2 -0
- package/dist/esm/client/receipts.d.ts +34 -1
- package/dist/esm/client/receipts.js +35 -2
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/inventory/vertrag.d.ts +1 -1
- package/dist/esm/inventory/vertrag.js +2 -0
- package/dist/esm/invoice/vertrag.d.ts +1 -1
- package/dist/esm/invoice/vertrag.js +2 -0
- package/dist/esm/models/cancellation.d.ts +49 -1
- package/dist/esm/models/cancellation.js +132 -0
- package/dist/esm/models/index.d.ts +1 -1
- package/dist/esm/models/index.js +1 -1
- package/dist/esm/models/payment-errors.d.ts +1 -1
- package/dist/esm/models/payment-errors.js +2 -0
- package/dist/esm/models/receipt-email.d.ts +1 -1
- package/dist/esm/models/receipt-email.js +2 -0
- package/dist/esm/models/receipt-errors.d.ts +1 -1
- package/dist/esm/models/receipt-errors.js +2 -0
- package/dist/esm/models/receipt-item.d.ts +10 -0
- package/dist/esm/models/receipt-item.js +3 -0
- package/dist/esm/pos/client.js +11 -1
- package/dist/esm/pos/errors.d.ts +4 -3
- package/dist/esm/pos/errors.js +21 -2
- package/dist/esm/pos/index.d.ts +6 -2
- package/dist/esm/pos/index.js +7 -2
- package/dist/esm/pos/schicht-lesen.d.ts +39 -0
- package/dist/esm/pos/schicht-lesen.js +392 -0
- package/dist/esm/pos/schicht-typen.d.ts +380 -0
- package/dist/esm/pos/schicht-typen.js +56 -0
- package/dist/esm/pos/schicht.d.ts +208 -0
- package/dist/esm/pos/schicht.js +222 -0
- package/dist/esm/pos/settings.d.ts +37 -1
- package/dist/esm/pos/settings.js +40 -2
- package/dist/esm/pos/texte.d.ts +627 -0
- package/dist/esm/pos/texte.js +236 -0
- package/dist/esm/react/index.js +1 -1
- package/dist/esm/receipt/grid.js +2 -2
- package/dist/esm/receipt/layout.d.ts +5 -0
- package/dist/esm/receipt/shift-sheet.d.ts +33 -0
- package/dist/esm/receipt/shift-sheet.js +203 -0
- package/dist/esm/register/errors.d.ts +1 -1
- package/dist/esm/register/errors.js +2 -0
- package/dist/esm/stored/draht.d.ts +1 -1
- package/dist/esm/stored/draht.js +4 -3
- package/dist/esm/stored/einstellungen.js +27 -4
- package/dist/esm/stored/vokabular.d.ts +1 -1
- package/dist/esm/stored/vokabular.js +118 -12
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/fixtures/cancellation-tip-cases.json +679 -0
- package/fixtures/expected/cash-movement.grid32.txt +15 -0
- package/fixtures/expected/cash-movement.grid48.txt +15 -0
- package/fixtures/expected/cash-movement.lines.json +171 -0
- package/fixtures/expected/shift-close-blind.grid32.txt +28 -0
- package/fixtures/expected/shift-close-blind.grid48.txt +27 -0
- package/fixtures/expected/shift-close-blind.lines.json +275 -0
- package/fixtures/expected/shift-close-put-in.grid32.txt +38 -0
- package/fixtures/expected/shift-close-put-in.grid48.txt +35 -0
- package/fixtures/expected/shift-close-put-in.lines.json +403 -0
- package/fixtures/expected/shift-close-take-out.grid32.txt +38 -0
- package/fixtures/expected/shift-close-take-out.grid48.txt +35 -0
- package/fixtures/expected/shift-close-take-out.lines.json +403 -0
- package/fixtures/expected/shift-close.grid32.txt +37 -0
- package/fixtures/expected/shift-close.grid48.txt +35 -0
- package/fixtures/expected/shift-close.lines.json +413 -0
- package/fixtures/expected/shift-interim.grid32.txt +28 -0
- package/fixtures/expected/shift-interim.grid48.txt +27 -0
- package/fixtures/expected/shift-interim.lines.json +293 -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/pos-message-cases.json +45 -0
- package/fixtures/pos-texts.json +723 -1
- package/fixtures/receipt-due-generated.json +1 -1
- package/fixtures/shift-cases.json +87 -0
- package/fixtures/shift-receipts.json +41 -0
- package/fixtures/surface.json +119 -3
- 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 +10874 -4865
- package/fixtures/v3/antworten/lager.json +1 -1
- package/fixtures/v3/antworten/rechnungen.json +1 -1
- package/fixtures/v3/antworten/storno.json +1 -1
- package/fixtures/v3/stored/belege.json +18 -6
- package/fixtures/v3/stored/kasse.json +4667 -183
- package/fixtures/v3/stored/rechnungen.json +1 -1
- package/fixtures/v3/v3-vokabular.json +739 -32
- package/fixtures/v3/zahlbetrag-faelle.json +1 -1
- package/package.json +1 -1
package/dist/cjs/pos/texte.js
CHANGED
|
@@ -67,6 +67,9 @@ const MELDUNGEN_ROH = {
|
|
|
67
67
|
// Wer die Abmelden-Taste ein zweites Mal drueckt, beendet die Schicht –
|
|
68
68
|
// der Satz steht in der Rueckfrage, bevor es so weit ist.
|
|
69
69
|
'logout.press_again': { text: 'Noch einmal drücken beendet die Schicht an dieser Kasse.' },
|
|
70
|
+
// Seit 1.11.0 an seiner Stelle: die Rueckfrage beim Abmelden mit vollem Warenkorb. Ein zweiter Druck meldet ab
|
|
71
|
+
// und leert den Korb; die Schicht der Kassenlade laeuft weiter (das alte Wort „Schicht“ fuehrte dort in die Irre).
|
|
72
|
+
'logout.cart_cleared': { text: 'Noch einmal drücken meldet dich ab – der Warenkorb wird geleert.' },
|
|
70
73
|
'permissions.not_changeable': { text: 'Das darfst du nicht ändern – das Recht dafür vergibt der Inhaber im Panel.' },
|
|
71
74
|
// --- Verkauf und Positionen ----------------------------------------------
|
|
72
75
|
'cashregister.load_failed': { text: 'Die Kasse konnte nicht geladen werden.' },
|
|
@@ -88,6 +91,8 @@ const MELDUNGEN_ROH = {
|
|
|
88
91
|
// Keine gesetzliche Obergrenze – steuerfrei ist aber nur ortsuebliches
|
|
89
92
|
// Trinkgeld (§ 3 Abs 1 Z 16a EStG). Eine Warnung, keine Sperre.
|
|
90
93
|
'tip.over_half': { text: 'Über 50 % Trinkgeld – wirklich? Steuerfrei ist nur ortsübliches Trinkgeld.' },
|
|
94
|
+
// Bar-Trinkgeld „gleich behalten“ (Hinweis zur Einstellung, Beschriftungen unten).
|
|
95
|
+
'tip.kept_setting_hint': { text: 'Der Mitarbeiter steckt das Bar-Trinkgeld beim Verkauf gleich ein: es zählt nicht ins Soll der Lade und gilt als schon genommen. An der Kasse lässt es sich je Verkauf umstellen.' },
|
|
91
96
|
// --- Abschluss -----------------------------------------------------------
|
|
92
97
|
'completion.failed': { text: 'Der Abschluss ist fehlgeschlagen.' },
|
|
93
98
|
'completion.unknown': { text: 'Unklar, ob der Beleg entstanden ist – die Antwort kam nicht an. Bitte nicht noch einmal abschließen: der Beleg kann bereits erstellt und signiert sein. Im Panel unter „Belege“ nachsehen; nur wenn er dort fehlt, den Verkauf erneut abschließen.' },
|
|
@@ -176,6 +181,12 @@ const MELDUNGEN_ROH = {
|
|
|
176
181
|
// (`unknown_reason`, `note_too_long`, `invalid_items`): am Server geschah
|
|
177
182
|
// nichts, der Kassier beginnt das Storno von vorn.
|
|
178
183
|
'cancellation.input_rejected': { text: 'Die Eingabe wurde abgelehnt – bitte das Storno neu beginnen.' },
|
|
184
|
+
// Storno eines Belegs mit Mitarbeiter-Trinkgeld (Schichten-Spec, Nachtrag 5): gesendet wird erst
|
|
185
|
+
// nach der Wahl, ohne Vorauswahl. Fehlt sie, steht dieser Satz unter dem Knopf.
|
|
186
|
+
'cancellation.tip_refund_missing': { text: 'Bitte wählen: Trinkgeld auch zurückgeben?' },
|
|
187
|
+
'cancellation.tip_source_missing': { text: 'Bitte wählen: Woher kommt das Trinkgeld zurück?' },
|
|
188
|
+
// Beleg mit Wertgutschein: keine Frage, das Trinkgeld geht mit (Ruling R59, asksRefundTip).
|
|
189
|
+
'cancellation.tip_refunded_with_voucher': { text: 'Beleg mit Gutschein: Das Trinkgeld wird mitstorniert.' },
|
|
179
190
|
// --- Getrennt zahlen -----------------------------------------------------
|
|
180
191
|
// Ein Tisch zahlt in Teilen, ein Beleg fuer alles. Das Teure ist eine schon
|
|
181
192
|
// belastete Karte: jeder Satz, der sie betrifft, nennt den Betrag, und keiner
|
|
@@ -308,6 +319,39 @@ const MELDUNGEN_ROH = {
|
|
|
308
319
|
'stocktake.serials_mismatch': { text: 'Je Stück genau eine Seriennummer: {count} erfasst, {quantity} gezählt.', placeholders: ['count', 'quantity'] },
|
|
309
320
|
'stocktake.reason_missing': { text: 'Bitte einen Grund für das Stornieren eingeben.' },
|
|
310
321
|
'stocktake.outcome_unknown': { text: 'Unklar, ob die Zählung angekommen ist. „Erneut senden“ schickt dieselbe Zählung – sie zählt auch dann nur einmal.' },
|
|
322
|
+
// --- Schicht und Kassenstand ---------------------------------------------
|
|
323
|
+
// Soll und Differenz nennt kein Satz: ohne Recht `cashView` wird blind
|
|
324
|
+
// gezaehlt. `{number}` ist die Schicht-Nummer, `{since}` die Startzeit
|
|
325
|
+
// („08:00“ bzw. „gestern 22:15“), `{type}` die Beschriftung der Art
|
|
326
|
+
// (`cash_movement.type_*`), `{amount}` der Betrag samt Euro-Zeichen.
|
|
327
|
+
// „Erneut senden“ schickt denselben Vorgang mit demselben Schluessel.
|
|
328
|
+
'shift.required': { text: 'Bitte zuerst die Schicht öffnen.' },
|
|
329
|
+
'shift.required_other': { text: 'Die Schicht muss ein berechtigter Mitarbeiter öffnen.' },
|
|
330
|
+
'shift.recount': { text: 'Der gezählte Betrag weicht ab – bitte noch einmal zählen.' },
|
|
331
|
+
'shift.comment_required': { text: 'Die Abweichung ist größer als erlaubt – bitte kurz begründen.' },
|
|
332
|
+
'shift.closed': { text: 'Schicht {number} geschlossen.', placeholders: ['number'] },
|
|
333
|
+
'shift.long_open': { text: 'Die Schicht läuft seit {since}.', placeholders: ['since'] },
|
|
334
|
+
'shift.already_open': { text: 'An dieser Lade läuft schon eine Schicht.' },
|
|
335
|
+
'shift.already_closed': { text: 'Diese Schicht ist schon geschlossen.' },
|
|
336
|
+
'shift.recount_exhausted': { text: 'Es wurde schon zweimal gezählt. Bitte den Betrag der zweiten Zählung senden oder den Chef rufen.' },
|
|
337
|
+
'shift.mode_off': { text: 'An dieser Lade ist der Schichtbetrieb aus. Bitte im Panel einschalten.' },
|
|
338
|
+
'shift.outcome_unknown': { text: 'Unklar, ob das angekommen ist. „Erneut senden“ schickt denselben Vorgang – er zählt nur einmal.' },
|
|
339
|
+
'cash_movement.exceeds_balance': { text: 'So viel Bargeld ist laut Kassenstand nicht in der Lade.' },
|
|
340
|
+
'cash_movement.note_required': { text: 'Bitte einen Grund eingeben.' },
|
|
341
|
+
'cash_movement.booked': { text: '{type} über {amount} gebucht.', placeholders: ['type', 'amount'] },
|
|
342
|
+
'cash_movement.type_invalid': { text: 'Diese Art der Kassenbewegung ist hier nicht möglich.' },
|
|
343
|
+
'cash_movement.same_drawer': { text: 'Eine Umbuchung in dieselbe Lade geht nicht. Bitte eine andere Lade wählen.' },
|
|
344
|
+
'tip_payout.exceeds_claim': { text: 'Mehr als der offene Anspruch kann nicht ausgezahlt werden.' },
|
|
345
|
+
'denominations.invalid': { text: 'Scheine und Münzen ergeben nicht den Betrag.' },
|
|
346
|
+
'amount.invalid': { text: 'Bitte einen gültigen Betrag eingeben.' },
|
|
347
|
+
'drawer.not_found': { text: 'Diese Lade gibt es nicht mehr. Bitte im Panel die Lade dieses Geräts prüfen.' },
|
|
348
|
+
'drawer.inactive': { text: 'Diese Lade ist stillgelegt. Bitte im Panel eine andere Lade zuordnen.' },
|
|
349
|
+
'tip_payout.recipient_required': { text: 'Bitte einen Mitarbeiter wählen.' },
|
|
350
|
+
'tip_payout.none_open': { text: 'In dieser Schicht ist kein Trinkgeld offen.' },
|
|
351
|
+
'shift.pending_hint': { text: 'Noch nicht bestätigt. „Erneut senden“ schickt denselben Vorgang – er zählt nur einmal.' },
|
|
352
|
+
// Wechselgeld der Lade (1.11.0): beim Öffnen der Schicht liegt weniger in der Lade als eingestellt.
|
|
353
|
+
// `{amount}` was fehlt, `{total}` das eingestellte Wechselgeld, beide samt Euro-Zeichen.
|
|
354
|
+
'shift.change_float_missing': { text: 'Es fehlen {amount} bis zum Wechselgeld von {total}.', placeholders: ['amount', 'total'] },
|
|
311
355
|
// --- Nur App -------------------------------------------------------------
|
|
312
356
|
'app.not_in_browser': { text: 'Die Kassen-App läuft nicht im Browser – dafür gibt es kasse.kasseneck.at.', only: ['app'] },
|
|
313
357
|
'app.open_in_browser': { text: 'Bitte im Browser öffnen: {target}', placeholders: ['target'], only: ['app'] },
|
|
@@ -360,6 +404,24 @@ exports.ERROR_RULES = [
|
|
|
360
404
|
exports.ERROR_CODE_RULES = [
|
|
361
405
|
{ kind: 'api', codes: ['dialect_mismatch', 'response_translation_failed', 'response_unreadable'], key: 'server.response_unreadable' },
|
|
362
406
|
{ kind: 'api', codes: ['route_missing', 'not_found', 'internal_translation_error'], key: 'server.connection_disturbed' },
|
|
407
|
+
// Schicht und Kassenstand (1.9.0): die Saetze des Backends nennen Felder
|
|
408
|
+
// und Schwellen; die Kasse sagt, was zu tun ist. Der Server hat in jedem
|
|
409
|
+
// dieser Faelle nichts gebucht.
|
|
410
|
+
{ kind: 'api', codes: ['shift_not_open'], key: 'shift.required' },
|
|
411
|
+
{ kind: 'api', codes: ['shift_already_open'], key: 'shift.already_open' },
|
|
412
|
+
{ kind: 'api', codes: ['shift_closed'], key: 'shift.already_closed' },
|
|
413
|
+
{ kind: 'api', codes: ['comment_required'], key: 'shift.comment_required' },
|
|
414
|
+
{ kind: 'api', codes: ['recount_exhausted'], key: 'shift.recount_exhausted' },
|
|
415
|
+
{ kind: 'api', codes: ['shift_mode_off'], key: 'shift.mode_off' },
|
|
416
|
+
{ kind: 'api', codes: ['cash_movement_exceeds_balance'], key: 'cash_movement.exceeds_balance' },
|
|
417
|
+
{ kind: 'api', codes: ['note_required'], key: 'cash_movement.note_required' },
|
|
418
|
+
{ kind: 'api', codes: ['invalid_movement_type'], key: 'cash_movement.type_invalid' },
|
|
419
|
+
{ kind: 'api', codes: ['transfer_same_drawer'], key: 'cash_movement.same_drawer' },
|
|
420
|
+
{ kind: 'api', codes: ['tip_payout_exceeds_claim'], key: 'tip_payout.exceeds_claim' },
|
|
421
|
+
{ kind: 'api', codes: ['invalid_denominations'], key: 'denominations.invalid' },
|
|
422
|
+
{ kind: 'api', codes: ['invalid_amount'], key: 'amount.invalid' },
|
|
423
|
+
{ kind: 'api', codes: ['drawer_not_found'], key: 'drawer.not_found' },
|
|
424
|
+
{ kind: 'api', codes: ['drawer_inactive'], key: 'drawer.inactive' },
|
|
363
425
|
];
|
|
364
426
|
/**
|
|
365
427
|
* Regeln je Ausgang, nach den Code-Regeln und vor der Regel der Art: eine
|
|
@@ -532,6 +594,9 @@ const BESCHRIFTUNGEN_ROH = {
|
|
|
532
594
|
'checkout.clear_tendered': { text: 'Gegeben löschen' },
|
|
533
595
|
'checkout.still_missing': { text: 'Es fehlen noch' },
|
|
534
596
|
'checkout.change': { text: 'Rückgeld' },
|
|
597
|
+
// Schalter beim Trinkgeld (nur Mitarbeiter-Trinkgeld, reine Barzahlung), vorbelegt aus der Einstellung.
|
|
598
|
+
'checkout.tip_kept': { text: 'gleich behalten' },
|
|
599
|
+
'tip.kept_setting': { text: 'Bar-Trinkgeld behält der Mitarbeiter gleich' },
|
|
535
600
|
// Die Warte-Karte, solange der Betrag am Terminal steht; `{time}` ist der
|
|
536
601
|
// Rest des Kartenfensters als m:ss.
|
|
537
602
|
'card_payment.amount_on_terminal': { text: 'Betrag steht am Terminal' },
|
|
@@ -603,6 +668,16 @@ const BESCHRIFTUNGEN_ROH = {
|
|
|
603
668
|
'cancellation.all_cash': { text: 'Alles bar' },
|
|
604
669
|
'cancellation.payment_remainder': { text: 'Rest {amount}', placeholders: ['amount'] },
|
|
605
670
|
'cancellation.difference': { text: 'Differenz' },
|
|
671
|
+
// --- Storno mit oder ohne Trinkgeld (Schichten-Spec, Nachtrag 5) -----------
|
|
672
|
+
// Erste Frage bei offenem Mitarbeiter-Trinkgeld, zweite nur bei Ja und Barrueckgabe.
|
|
673
|
+
'cancellation.tip_refund_question': { text: 'Trinkgeld auch zurückgeben?' },
|
|
674
|
+
'cancellation.tip_refund_yes': { text: 'Ja' },
|
|
675
|
+
'cancellation.tip_refund_no': { text: 'Nein' },
|
|
676
|
+
'cancellation.tip_source_question': { text: 'Woher kommt das Trinkgeld zurück?' },
|
|
677
|
+
'cancellation.tip_source_drawer': { text: 'Aus der Lade' },
|
|
678
|
+
'cancellation.tip_source_employee': { text: 'Gibt die Mitarbeiterin direkt' },
|
|
679
|
+
// Trinkgeld-Zeile im Storno-Blatt nach „Nein“ (Fix-Runde 1, R63): sie geht nicht mit.
|
|
680
|
+
'cancellation.tip_stays': { text: 'bleibt' },
|
|
606
681
|
// --- Zeichensatz-Test (Testblatt und Drucker & Lade) ----------------------
|
|
607
682
|
// Das Testblatt druckt diese Texte mit Ersatzbuchstaben (reines ASCII);
|
|
608
683
|
// die Knoepfe stehen nur am Bildschirm. `{chars}` sind die fehlenden Zeichen einer Zeile
|
|
@@ -655,6 +730,167 @@ const BESCHRIFTUNGEN_ROH = {
|
|
|
655
730
|
'stocktake.sent': { text: 'gesendet' },
|
|
656
731
|
'stocktake.unconfirmed': { text: 'unbestätigt' },
|
|
657
732
|
'stocktake.voided': { text: 'storniert' },
|
|
733
|
+
// --- Schicht und Kassenstand ---------------------------------------------
|
|
734
|
+
'shift.open_title': { text: 'Schicht öffnen' },
|
|
735
|
+
'shift.take_over': { text: 'Bestand übernehmen' },
|
|
736
|
+
'shift.count': { text: 'Zählen' },
|
|
737
|
+
'shift.by_denomination': { text: 'Nach Scheinen und Münzen' },
|
|
738
|
+
'shift.close_title': { text: 'Schicht schließen' },
|
|
739
|
+
'shift.cash_title': { text: 'Kassenstand' },
|
|
740
|
+
'shift.x_report': { text: 'Zwischenbericht' },
|
|
741
|
+
'shift.pay_out_tips': { text: 'Trinkgeld auszahlen' },
|
|
742
|
+
'drawer.reason_title': { text: 'Warum öffnen Sie die Lade?' },
|
|
743
|
+
'drawer.reason_change': { text: 'Wechselgeld' },
|
|
744
|
+
'drawer.reason_check': { text: 'Kontrolle' },
|
|
745
|
+
'drawer.reason_misoperation': { text: 'Fehlbedienung' },
|
|
746
|
+
'drawer.reason_other': { text: 'Sonstiges' },
|
|
747
|
+
// Je Art einer Kassenbewegung (auch die, die nur der Server vergibt: sie
|
|
748
|
+
// stehen auf dem Z-Bon und im Bericht).
|
|
749
|
+
'cash_movement.type_change_in': { text: 'Wechselgeld' },
|
|
750
|
+
'cash_movement.type_cash_drop': { text: 'Abschöpfung' },
|
|
751
|
+
'cash_movement.type_owner_deposit': { text: 'Privateinlage' },
|
|
752
|
+
'cash_movement.type_owner_withdrawal': { text: 'Privatentnahme' },
|
|
753
|
+
'cash_movement.type_tip_payout': { text: 'Trinkgeld-Auszahlung' },
|
|
754
|
+
'cash_movement.type_other_in': { text: 'Sonstige Einzahlung' },
|
|
755
|
+
'cash_movement.type_other_out': { text: 'Sonstige Auszahlung' },
|
|
756
|
+
'cash_movement.type_transfer_out': { text: 'Umbuchung' },
|
|
757
|
+
'cash_movement.type_transfer_in': { text: 'Umbuchung (Eingang)' },
|
|
758
|
+
'cash_movement.type_expense': { text: 'Barausgabe' },
|
|
759
|
+
'cash_movement.type_count_difference': { text: 'Zähldifferenz' },
|
|
760
|
+
'cash_movement.type_handover_difference': { text: 'Übergabedifferenz' },
|
|
761
|
+
// Bon der Schicht (Z-Bon, X-Bon, Kassenbewegung): Titel und Zeilennamen.
|
|
762
|
+
'shift_receipt.title_close': { text: 'Schichtabschluss' },
|
|
763
|
+
'shift_receipt.title_interim': { text: 'Zwischenbericht' },
|
|
764
|
+
'shift_receipt.title_movement': { text: 'Kassenbewegung' },
|
|
765
|
+
'shift_receipt.cashregister': { text: 'Kasse' },
|
|
766
|
+
'shift_receipt.drawer': { text: 'Lade' },
|
|
767
|
+
'shift_receipt.shift': { text: 'Schicht' },
|
|
768
|
+
'shift_receipt.number': { text: 'Nr. {number}', placeholders: ['number'] },
|
|
769
|
+
'shift_receipt.opened': { text: 'Geöffnet' },
|
|
770
|
+
'shift_receipt.closed': { text: 'Geschlossen' },
|
|
771
|
+
'shift_receipt.by': { text: 'von' },
|
|
772
|
+
'shift_receipt.opening_float': { text: 'Startgeld' },
|
|
773
|
+
'shift_receipt.opening_float_taken_over': { text: 'Startgeld übernommen' },
|
|
774
|
+
'shift_receipt.cash_sales': { text: 'Bar aus Verkäufen' },
|
|
775
|
+
'shift_receipt.cash_cancellations': { text: 'Bar aus Storno' },
|
|
776
|
+
'shift_receipt.movements': { text: 'Bewegungen' },
|
|
777
|
+
'shift_receipt.expected': { text: 'Soll' },
|
|
778
|
+
'shift_receipt.counted': { text: 'Ist' },
|
|
779
|
+
'shift_receipt.difference': { text: 'Differenz' },
|
|
780
|
+
// Nach der Zählung beim Abschluss (1.11.0): „Entnommen“ (negativ) bzw. „Eingelegt“, dann was bleibt (fett).
|
|
781
|
+
'shift_receipt.taken_out': { text: 'Entnommen' },
|
|
782
|
+
'shift_receipt.put_in': { text: 'Eingelegt' },
|
|
783
|
+
'shift_receipt.left_in_drawer': { text: 'Bleibt in der Kassenlade' },
|
|
784
|
+
'shift_receipt.comment': { text: 'Kommentar' },
|
|
785
|
+
'shift_receipt.non_cash': { text: 'Unbar (nur Information)' },
|
|
786
|
+
'shift_receipt.receipts': { text: 'Belege' },
|
|
787
|
+
'shift_receipt.cancellations': { text: 'Stornos' },
|
|
788
|
+
'shift_receipt.openings_without_sale': { text: 'Öffnungen ohne Verkauf' },
|
|
789
|
+
// Trinkgeld je Mitarbeiter (Bon, Kassenstand, Nachtrag 3): verdient = sofort + über Lohn, schon
|
|
790
|
+
// genommen = in dieser Schicht aus der Lade ausgezahlt, offen = Anspruch an die Lade.
|
|
791
|
+
'shift_receipt.tips': { text: 'Trinkgeld' },
|
|
792
|
+
'shift_receipt.tip_earned': { text: 'verdient' },
|
|
793
|
+
'shift_receipt.tip_retained': { text: 'über Lohn' },
|
|
794
|
+
'shift_receipt.tip_paid_out': { text: 'schon genommen' },
|
|
795
|
+
// Beim Storno von der Mitarbeiterin selbst zurueckgegeben (Fix-Runde 1, R62) – nie ein negatives „schon genommen“.
|
|
796
|
+
'shift_receipt.tip_refunded_by_employee': { text: 'selbst zurückgegeben' },
|
|
797
|
+
// Offene Forderung beim Oeffnen der Schicht (Fix-Runde 2, R64).
|
|
798
|
+
'shift_receipt.tip_carried_over': { text: 'aus früheren Schichten' },
|
|
799
|
+
'shift_receipt.tip_open': { text: 'offen' },
|
|
800
|
+
'shift_receipt.movement_number': { text: 'Nr.' },
|
|
801
|
+
'shift_receipt.type': { text: 'Art' },
|
|
802
|
+
'shift_receipt.amount': { text: 'Betrag' },
|
|
803
|
+
'shift_receipt.location': { text: 'Ort' },
|
|
804
|
+
'shift_receipt.location_bank': { text: 'Bank' },
|
|
805
|
+
'shift_receipt.location_safe': { text: 'Tresor' },
|
|
806
|
+
'shift_receipt.recipient': { text: 'Empfänger' },
|
|
807
|
+
'shift_receipt.target_drawer': { text: 'Ziel-Lade' },
|
|
808
|
+
'shift_receipt.note': { text: 'Grund' },
|
|
809
|
+
'shift_receipt.operator': { text: 'Bediener' },
|
|
810
|
+
'shift_receipt.time': { text: 'Zeit' },
|
|
811
|
+
'cash_movement.pay_in': { text: 'Einzahlung' },
|
|
812
|
+
'cash_movement.pay_out': { text: 'Auszahlung' },
|
|
813
|
+
'cash_movement.print': { text: 'Beleg drucken' },
|
|
814
|
+
'drawer.recent_openings': { text: 'Letzte Öffnungen' },
|
|
815
|
+
'drawer.reason_sale': { text: 'Verkauf' },
|
|
816
|
+
'drawer.reason_cash_movement': { text: 'Kassenbewegung' },
|
|
817
|
+
'drawer.reason_shift_open': { text: 'Schichtbeginn' },
|
|
818
|
+
'drawer.reason_shift_close': { text: 'Schichtabschluss' },
|
|
819
|
+
'shift.resend': { text: 'Erneut senden' },
|
|
820
|
+
'shift.next': { text: 'Weiter' },
|
|
821
|
+
'shift.print_close': { text: 'Schichtabschluss drucken' },
|
|
822
|
+
'shift.print_again': { text: 'Nochmals drucken' },
|
|
823
|
+
'shift.back_to_register': { text: 'Zur Kasse' },
|
|
824
|
+
'shift.later': { text: 'Später senden' },
|
|
825
|
+
'time.yesterday': { text: 'gestern' },
|
|
826
|
+
// Kassenstand an der Kasse (1.11.0): Karte „In der Kassenlade sollten sein“, Schichtkopf, Zahlungen.
|
|
827
|
+
'shift.drawer_should_have': { text: 'In der Kassenlade sollten sein' },
|
|
828
|
+
'shift.drawer_named': { text: 'Kassenlade: {name}', placeholders: ['name'] },
|
|
829
|
+
'shift.running_since': { text: 'läuft seit {duration}', placeholders: ['duration'] },
|
|
830
|
+
'shift.since': { text: 'seit {time}', placeholders: ['time'] },
|
|
831
|
+
'shift.collected_outside_drawer': { text: 'Kassiert, aber nicht in der Kassenlade' },
|
|
832
|
+
'shift.non_cash_short': { text: 'unbar' },
|
|
833
|
+
'shift.voucher_redeemed': { text: 'Gutschein eingelöst' },
|
|
834
|
+
'shift.all_payments': { text: 'Alle Zahlungen dieser Schicht (bar + unbar)' },
|
|
835
|
+
'shift.receipt_count_one': { text: '1 Beleg' },
|
|
836
|
+
'shift.receipt_count_other': { text: '{count} Belege', placeholders: ['count'] },
|
|
837
|
+
'shift.openings_without_sale_count': { text: '{count}× ohne Verkauf geöffnet', placeholders: ['count'] },
|
|
838
|
+
'cash_movement.pay_in_short': { text: 'Einzahlen' },
|
|
839
|
+
'cash_movement.pay_out_short': { text: 'Auszahlen' },
|
|
840
|
+
'drawer.recent_openings_full': { text: 'Letzte Öffnungen der Kassenlade' },
|
|
841
|
+
// Warnzeile an den Druck-Knöpfen: nur ein leiser Hinweis, die Knöpfe bleiben wie sie sind.
|
|
842
|
+
'printer.warn_unreachable': { text: 'Drucker nicht erreichbar' },
|
|
843
|
+
'printer.warn_none': { text: 'Kein Drucker eingerichtet' },
|
|
844
|
+
'printer.check': { text: 'Prüfen' },
|
|
845
|
+
'printer.set_up': { text: 'Einrichten' },
|
|
846
|
+
// Dauer (Zusammensetzung: durationText): ab 1 Tag „1 Tag 3 Std.“, sonst „8 Std. 32 Min.“, unter 1 Std. nur Minuten.
|
|
847
|
+
'duration.days_one': { text: '{days} Tag', placeholders: ['days'] },
|
|
848
|
+
'duration.days_other': { text: '{days} Tage', placeholders: ['days'] },
|
|
849
|
+
'duration.hours': { text: '{hours} Std.', placeholders: ['hours'] },
|
|
850
|
+
'duration.minutes': { text: '{minutes} Min.', placeholders: ['minutes'] },
|
|
851
|
+
// Trinkgeld auszahlen (eine Liste mit Kurzwahlen) und Trinkgeld-Karte im Kassenstand.
|
|
852
|
+
'tip_payout.open_amount': { text: 'offen {amount}', placeholders: ['amount'] },
|
|
853
|
+
'tip_payout.done': { text: 'erledigt' },
|
|
854
|
+
'tip_payout.for_all': { text: 'Für alle' },
|
|
855
|
+
'tip_payout.nothing': { text: 'Nichts' },
|
|
856
|
+
'tip_payout.all_open': { text: 'Alles Offene' },
|
|
857
|
+
'tip_payout.title': { text: 'Auszahlung' },
|
|
858
|
+
'tip_payout.persons_one': { text: '1 Person' },
|
|
859
|
+
'tip_payout.persons_other': { text: '{count} Personen', placeholders: ['count'] },
|
|
860
|
+
'tip_payout.pay_amount': { text: '{amount} auszahlen', placeholders: ['amount'] },
|
|
861
|
+
'tip_payout.pay_out': { text: 'Auszahlen' },
|
|
862
|
+
// Wechselgeld je Kassenlade (Einstellung) und Schritt „Geld entnehmen“ beim Schicht-Abschluss (1.11.0).
|
|
863
|
+
'drawer.change_float': { text: 'Wechselgeld in der Lade' },
|
|
864
|
+
'drawer.change_float_hint': { text: 'Bleibt nach jedem Schicht-Abschluss drin. Mehr wird beim Schließen entnommen.' },
|
|
865
|
+
'drawer.change_float_empty_hint': { text: 'Leer = alles bleibt in der Lade (wie bisher).' },
|
|
866
|
+
'shift.step_take_out': { text: 'Geld entnehmen' },
|
|
867
|
+
'shift.left_in_drawer': { text: 'Bleibt in der Kassenlade' },
|
|
868
|
+
'shift.change_float_next_shift': { text: 'Wechselgeld für die nächste Schicht' },
|
|
869
|
+
'shift.take_out': { text: 'Entnehmen' },
|
|
870
|
+
'shift.put_in': { text: 'Einlegen' },
|
|
871
|
+
'shift.take_out_at_most': { text: 'höchstens {amount}', placeholders: ['amount'] },
|
|
872
|
+
'shift.put_in_hint': { text: 'Geld in die Kassenlade legen' },
|
|
873
|
+
'shift.after_count_tap_hint': { text: 'Tippe auf einen Betrag, um ihn zu ändern – der andere rechnet sich selbst.' },
|
|
874
|
+
'shift.take_out_amount': { text: '{amount} entnehmen', placeholders: ['amount'] },
|
|
875
|
+
'shift.put_in_amount': { text: '{amount} einlegen', placeholders: ['amount'] },
|
|
876
|
+
'shift.continue_without_take_out': { text: 'Weiter ohne Entnahme' },
|
|
877
|
+
'shift.print_envelope_receipt': { text: 'Bon fürs Kuvert drucken' },
|
|
878
|
+
// Bedienhilfe (Vorlesetext) des Vorzeichen-Knopfs −/+ im Feld „Entnehmen“.
|
|
879
|
+
'shift.toggle_take_out_put_in': { text: 'Entnehmen oder Einlegen umschalten' },
|
|
880
|
+
'shift.put_in_change_float': { text: 'Wechselgeld einlegen' },
|
|
881
|
+
'shift.taken_over_from_shift': { text: 'von Schicht {number} übernommen', placeholders: ['number'] },
|
|
882
|
+
// Schritt „Geld entnehmen“: Zeile „Gezählt“, Knopf „Zurück“, letzter Schritt der Schrittleiste „Fertig“;
|
|
883
|
+
// Bedienhilfe der Betragsknöpfe, `{title}` ist ihre Beschriftung („Bleibt in der Kassenlade“, „Entnehmen“ …).
|
|
884
|
+
'shift.counted': { text: 'Gezählt' },
|
|
885
|
+
'shift.back': { text: 'Zurück' },
|
|
886
|
+
'shift.done': { text: 'Fertig' },
|
|
887
|
+
'shift.edit_amount': { text: '{title} ändern', placeholders: ['title'] },
|
|
888
|
+
// Kassenstand: Ein- und Auszahlungen der Schicht getrennt (Trinkgeld-Auszahlungen zählen zu den Auszahlungen);
|
|
889
|
+
// Buchungsknopf im Blatt Einzahlung/Auszahlung mit Betrag.
|
|
890
|
+
'shift.pay_ins': { text: 'Einzahlungen' },
|
|
891
|
+
'shift.pay_outs': { text: 'Auszahlungen' },
|
|
892
|
+
'cash_movement.pay_in_amount': { text: '{amount} einzahlen', placeholders: ['amount'] },
|
|
893
|
+
'cash_movement.pay_out_amount': { text: '{amount} auszahlen', placeholders: ['amount'] },
|
|
658
894
|
};
|
|
659
895
|
exports.LABELS = BESCHRIFTUNGEN_ROH;
|
|
660
896
|
/**
|
package/dist/cjs/react/index.js
CHANGED
|
@@ -51,7 +51,7 @@ function Zeile({ zeile, renderQr, qrVerdeckt, qrVerdecktText }) {
|
|
|
51
51
|
case 'text':
|
|
52
52
|
return ((0, jsx_runtime_1.jsx)("div", { className: "keck-receipt-text", style: { textAlign: AUSRICHTUNG[zeile.align], fontWeight: zeile.bold ? 'bold' : 'normal' }, children: zeile.text.length > 0 ? zeile.text : ' ' }));
|
|
53
53
|
case 'columns':
|
|
54
|
-
return ((0, jsx_runtime_1.jsx)("div", { className: "keck-receipt-row", style: { display: 'flex', width: '100%' }, children: zeile.columns.map((spalte, index) => ((0, jsx_runtime_1.jsx)("div", { className: "keck-receipt-cell", style: {
|
|
54
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: "keck-receipt-row", style: { display: 'flex', width: '100%', ...(zeile.bold === true ? { fontWeight: 'bold' } : {}) }, children: zeile.columns.map((spalte, index) => ((0, jsx_runtime_1.jsx)("div", { className: "keck-receipt-cell", style: {
|
|
55
55
|
// Die Breite ist ein Zwoelftel-Anteil (wie beim Bondrucker);
|
|
56
56
|
// so bleibt die Aufteilung auf allen Ausgabewegen dieselbe.
|
|
57
57
|
flex: `0 0 ${((spalte.width / 12) * 100).toFixed(4)}%`,
|
package/dist/cjs/receipt/grid.js
CHANGED
|
@@ -106,7 +106,7 @@ function renderReceiptGrid(layout, options = {}) {
|
|
|
106
106
|
const zelle = ausrichten(teile[i][r] ?? '', inhalt[i], c.align);
|
|
107
107
|
text += i < breiten.length - 1 ? zelle + ' '.repeat(breiten[i] - inhalt[i]) : zelle;
|
|
108
108
|
});
|
|
109
|
-
lines.push({ text: text.length === zeichen ? text : ausrichten(text, zeichen, 'left'), kind: 'columns', bold:
|
|
109
|
+
lines.push({ text: text.length === zeichen ? text : ausrichten(text, zeichen, 'left'), kind: 'columns', bold: z.bold === true });
|
|
110
110
|
}
|
|
111
111
|
if (fliesst) {
|
|
112
112
|
const i = weiterlaufend[0];
|
|
@@ -114,7 +114,7 @@ function renderReceiptGrid(layout, options = {}) {
|
|
|
114
114
|
// Bindestrich-/Hartbrueche der schmalen Spalte nicht als Leerzeichen zurueckbleiben.
|
|
115
115
|
const rest = restNach(z.columns[i].text, teile[i][0]);
|
|
116
116
|
for (const t of (0, escpos_js_1.wrapText)(rest, zeichen))
|
|
117
|
-
lines.push({ text: ausrichten(t, zeichen, z.columns[i].align), kind: 'columns', bold:
|
|
117
|
+
lines.push({ text: ausrichten(t, zeichen, z.columns[i].align), kind: 'columns', bold: z.bold === true });
|
|
118
118
|
}
|
|
119
119
|
break;
|
|
120
120
|
}
|
|
@@ -51,6 +51,11 @@ export interface LayoutTextLine {
|
|
|
51
51
|
export interface LayoutColumnsLine {
|
|
52
52
|
kind: 'columns';
|
|
53
53
|
columns: LayoutColumn[];
|
|
54
|
+
/**
|
|
55
|
+
* Die ganze Zeile fett (z. B. „Bleibt in der Kassenlade“ auf dem Z-Bon).
|
|
56
|
+
* Fehlt es, ist die Zeile normal; im Bauplan steht es nur, wenn `true`.
|
|
57
|
+
*/
|
|
58
|
+
bold?: boolean;
|
|
54
59
|
}
|
|
55
60
|
/** Eine durchgehende Trennlinie aus [char]. */
|
|
56
61
|
export interface LayoutRuleLine {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { CashMovementReceipt, ShiftSummaryReceipt } from '../pos/schicht-typen.js';
|
|
2
|
+
import type { PosPaperSize } from '../printing/escpos.js';
|
|
3
|
+
import { type ReceiptLayout } from './layout.js';
|
|
4
|
+
/**
|
|
5
|
+
* Bons der Schicht als Zeilenmodell: Z-Bon (`shift_close`), X-Bon
|
|
6
|
+
* (`shift_interim`) und Kassenbewegung (`cash_movement`), aus den Bon-Daten
|
|
7
|
+
* der Antwort (`receipt` von `closeMyShift`, `getMyShiftReport`,
|
|
8
|
+
* `recordMyCashMovement`). Gezeichnet wird wie jeder Beleg: Raster, Blatt,
|
|
9
|
+
* ESC/POS, ePOS.
|
|
10
|
+
*
|
|
11
|
+
* Kein Registrierkassenbeleg: keine Signatur, kein QR, kein DEP. Jeder Bon
|
|
12
|
+
* endet mit „Kein Registrierkassenbeleg“.
|
|
13
|
+
*
|
|
14
|
+
* **Blind** (ohne Recht `cashView`) sind Soll, Ist, Differenz, Barumsatz und
|
|
15
|
+
* die gezaehlte Stueckelung `null`: ihre Zeilen fallen weg, nie steht dort
|
|
16
|
+
* „0,00“ oder ein Strich. Dasselbe gilt fuer jede andere leere Angabe.
|
|
17
|
+
*/
|
|
18
|
+
export interface ShiftReceiptLayoutOptions {
|
|
19
|
+
/** Papierbreite fuer den Bauplan; Vorgabe `mm58`. Die Druckbreite waehlt der Druckweg. */
|
|
20
|
+
paperSize?: PosPaperSize;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Z-Bon bzw. X-Bon der Schicht. Titel nach `kind`: „Schichtabschluss“ oder
|
|
24
|
+
* „Zwischenbericht“. Wirft (`KasseneckValidationError`, `scope: 'request'`),
|
|
25
|
+
* wenn die Bon-Daten keine Z- oder X-Bon-Daten sind.
|
|
26
|
+
*/
|
|
27
|
+
export declare function shiftReceiptLayout(receipt: ShiftSummaryReceipt, options?: ShiftReceiptLayoutOptions): ReceiptLayout;
|
|
28
|
+
/**
|
|
29
|
+
* Bon einer Kassenbewegung (Einzahlung, Auszahlung, Umbuchung). Wirft
|
|
30
|
+
* (`KasseneckValidationError`, `scope: 'request'`), wenn die Bon-Daten keine
|
|
31
|
+
* Kassenbewegung sind.
|
|
32
|
+
*/
|
|
33
|
+
export declare function cashMovementLayout(receipt: CashMovementReceipt, options?: ShiftReceiptLayoutOptions): ReceiptLayout;
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.shiftReceiptLayout = shiftReceiptLayout;
|
|
4
|
+
exports.cashMovementLayout = cashMovementLayout;
|
|
5
|
+
const errors_js_1 = require("../client/errors.js");
|
|
6
|
+
const texte_js_1 = require("../pos/texte.js");
|
|
7
|
+
const schicht_lesen_js_1 = require("../pos/schicht-lesen.js");
|
|
8
|
+
const schicht_js_1 = require("../pos/schicht.js");
|
|
9
|
+
const vienna_time_js_1 = require("../vienna-time.js");
|
|
10
|
+
const layout_js_1 = require("./layout.js");
|
|
11
|
+
const PAPIER = ['mm58', 'mm80'];
|
|
12
|
+
function papier(name, options) {
|
|
13
|
+
for (const k of Object.keys(options)) {
|
|
14
|
+
if (k !== 'paperSize')
|
|
15
|
+
throw new errors_js_1.KasseneckValidationError(name, `Unbekannte Option "${k}"`, 'request');
|
|
16
|
+
}
|
|
17
|
+
const p = options.paperSize ?? 'mm58';
|
|
18
|
+
if (!PAPIER.includes(p))
|
|
19
|
+
throw new errors_js_1.KasseneckValidationError(name, 'paperSize: erlaubt sind mm58, mm80', 'request');
|
|
20
|
+
return p;
|
|
21
|
+
}
|
|
22
|
+
// ---------------------------------------------------------------- Bauteile
|
|
23
|
+
function text(t, align = 'left', bold = false) {
|
|
24
|
+
return { kind: 'text', text: t, align, bold };
|
|
25
|
+
}
|
|
26
|
+
/** Zwei Spalten: Name links, Wert rechts. */
|
|
27
|
+
function paar(links, rechts, linksBreite) {
|
|
28
|
+
return {
|
|
29
|
+
kind: 'columns',
|
|
30
|
+
columns: [
|
|
31
|
+
{ text: links, width: linksBreite, align: 'left' },
|
|
32
|
+
{ text: rechts, width: 12 - linksBreite, align: 'right' },
|
|
33
|
+
],
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** Kopfzeilen (Kasse, Zeiten, Namen): breiter Wert fuer „25.09.2026 17:00“. */
|
|
37
|
+
const kopf = (links, rechts) => paar(links, rechts, 5);
|
|
38
|
+
/** Betragszeilen: breiter Name, schmaler Betrag. */
|
|
39
|
+
const betrag = (links, cents) => paar(links, (0, layout_js_1.formatCents)(cents), 8);
|
|
40
|
+
/** Betragszeile fett (Ergebnis, z. B. „Bleibt in der Kassenlade“). */
|
|
41
|
+
const betragFett = (links, cents) => ({ ...betrag(links, cents), bold: true });
|
|
42
|
+
const anzahl = (links, n) => paar(links, String(n), 8);
|
|
43
|
+
const regel = () => ({ kind: 'rule', char: '-' });
|
|
44
|
+
/** Zeit in Wien als `DD.MM.YYYY HH:mm`; unlesbar -> `null` (die Zeile faellt weg, der Bon bleibt). */
|
|
45
|
+
function zeit(iso) {
|
|
46
|
+
if (iso === null)
|
|
47
|
+
return null;
|
|
48
|
+
try {
|
|
49
|
+
const t = (0, vienna_time_js_1.toViennaWallClock)((0, vienna_time_js_1.parseServerTimeStamp)(iso));
|
|
50
|
+
const zwei = (n) => String(n).padStart(2, '0');
|
|
51
|
+
return `${zwei(t.day)}.${zwei(t.month)}.${t.year} ${zwei(t.hour)}:${zwei(t.minute)}`;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function beschriftung(schluessel, sonst) {
|
|
58
|
+
return Object.prototype.hasOwnProperty.call(texte_js_1.LABELS, schluessel) ? (0, texte_js_1.labelText)(schluessel) : sonst;
|
|
59
|
+
}
|
|
60
|
+
const artText = (art) => beschriftung(`cash_movement.type_${art}`, art);
|
|
61
|
+
const ortText = (ort) => beschriftung(`shift_receipt.location_${ort}`, ort);
|
|
62
|
+
/** Zahlart unbar: `card` wie am Beleg „Kartenzahlung“, sonst der Wert, wie er kommt. */
|
|
63
|
+
function zahlartText(methode) {
|
|
64
|
+
return methode === 'card' ? (0, texte_js_1.labelText)('payment_method.card') : methode;
|
|
65
|
+
}
|
|
66
|
+
/** Je Schein und Muenze eine eingerueckte Zeile, vom groessten Wert abwaerts; Anzahl 0 faellt weg. */
|
|
67
|
+
function stueckelungZeilen(karte) {
|
|
68
|
+
if (karte === null)
|
|
69
|
+
return [];
|
|
70
|
+
return Object.entries(karte)
|
|
71
|
+
.map(([wert, n]) => [Number(wert), n])
|
|
72
|
+
.filter(([wert, n]) => n > 0 && Number.isSafeInteger(wert))
|
|
73
|
+
.sort((a, b) => b[0] - a[0])
|
|
74
|
+
.map(([wert, n]) => betrag(` ${n} x ${(0, layout_js_1.formatCents)(wert)}`, wert * n));
|
|
75
|
+
}
|
|
76
|
+
function wennText(zeilen, links, wert) {
|
|
77
|
+
if (wert !== null && wert !== '')
|
|
78
|
+
zeilen.push(kopf(links, wert));
|
|
79
|
+
}
|
|
80
|
+
function kopfblock(zeilen, bon, titel) {
|
|
81
|
+
zeilen.push({ kind: 'banner', text: (0, texte_js_1.labelText)(titel), tone: 'receipt_type' });
|
|
82
|
+
if (bon.business.name)
|
|
83
|
+
zeilen.push(text(bon.business.name, 'center', true));
|
|
84
|
+
wennText(zeilen, (0, texte_js_1.labelText)('shift_receipt.cashregister'), bon.cashregister.name);
|
|
85
|
+
wennText(zeilen, (0, texte_js_1.labelText)('shift_receipt.drawer'), bon.drawer.name);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Nach der Zaehlung beim Abschluss, durch eine Linie vom Zaehlblock getrennt:
|
|
89
|
+
* „Entnommen“ (negativ) bzw. „Eingelegt“, dann „Bleibt in der Kassenlade“
|
|
90
|
+
* (fett). Nur wenn Geld bewegt wurde
|
|
91
|
+
* (`afterCount`); sonst keine Zeile, der Bon bleibt wie bisher. Blind fehlt
|
|
92
|
+
* „Bleibt“ (`null`), die Entnahme selbst bleibt sichtbar. Eine unbekannte Art
|
|
93
|
+
* (kuenftiger Katalogwert) druckt keine Betragszeile.
|
|
94
|
+
*/
|
|
95
|
+
function nachZaehlungZeilen(bon) {
|
|
96
|
+
const n = bon.afterCount;
|
|
97
|
+
if (n === undefined || n === null)
|
|
98
|
+
return [];
|
|
99
|
+
const zeilen = [];
|
|
100
|
+
if (n.type === 'cash_drop')
|
|
101
|
+
zeilen.push(betrag((0, texte_js_1.labelText)('shift_receipt.taken_out'), -n.amountCents));
|
|
102
|
+
else if (n.type === 'change_in')
|
|
103
|
+
zeilen.push(betrag((0, texte_js_1.labelText)('shift_receipt.put_in'), n.amountCents));
|
|
104
|
+
const bleibt = bon.leftInDrawerCents;
|
|
105
|
+
if (bleibt !== undefined && bleibt !== null)
|
|
106
|
+
zeilen.push(betragFett((0, texte_js_1.labelText)('shift_receipt.left_in_drawer'), bleibt));
|
|
107
|
+
return zeilen.length > 0 ? [regel(), ...zeilen] : [];
|
|
108
|
+
}
|
|
109
|
+
// ------------------------------------------------------------------ Bons
|
|
110
|
+
/**
|
|
111
|
+
* Z-Bon bzw. X-Bon der Schicht. Titel nach `kind`: „Schichtabschluss“ oder
|
|
112
|
+
* „Zwischenbericht“. Wirft (`KasseneckValidationError`, `scope: 'request'`),
|
|
113
|
+
* wenn die Bon-Daten keine Z- oder X-Bon-Daten sind.
|
|
114
|
+
*/
|
|
115
|
+
function shiftReceiptLayout(receipt, options = {}) {
|
|
116
|
+
const name = 'shiftReceiptLayout';
|
|
117
|
+
const paperSize = papier(name, options);
|
|
118
|
+
const bon = (0, schicht_lesen_js_1.schichtBon)({ name, pfad: 'receipt', scope: 'request' }, receipt);
|
|
119
|
+
const zeilen = [];
|
|
120
|
+
kopfblock(zeilen, bon, bon.kind === 'shift_close' ? 'shift_receipt.title_close' : 'shift_receipt.title_interim');
|
|
121
|
+
zeilen.push(kopf((0, texte_js_1.labelText)('shift_receipt.shift'), (0, texte_js_1.labelText)('shift_receipt.number', { number: bon.shift.number })));
|
|
122
|
+
const von = (0, texte_js_1.labelText)('shift_receipt.by');
|
|
123
|
+
wennText(zeilen, (0, texte_js_1.labelText)('shift_receipt.opened'), zeit(bon.shift.openedAt));
|
|
124
|
+
wennText(zeilen, von, bon.shift.openedByName);
|
|
125
|
+
wennText(zeilen, (0, texte_js_1.labelText)('shift_receipt.closed'), zeit(bon.shift.closedAt));
|
|
126
|
+
wennText(zeilen, von, bon.shift.closedByName);
|
|
127
|
+
// Bargeld: Startgeld, Barumsatz, Bewegungen, Soll, Ist, Differenz.
|
|
128
|
+
zeilen.push(regel());
|
|
129
|
+
const start = (0, texte_js_1.labelText)(bon.openingFloatTakenOver ? 'shift_receipt.opening_float_taken_over' : 'shift_receipt.opening_float');
|
|
130
|
+
if (bon.openingFloatCents !== null)
|
|
131
|
+
zeilen.push(betrag(start, bon.openingFloatCents));
|
|
132
|
+
else if (bon.openingFloatTakenOver)
|
|
133
|
+
zeilen.push(text(start));
|
|
134
|
+
zeilen.push(...stueckelungZeilen(bon.openingDenominations));
|
|
135
|
+
if (bon.cashSalesCents !== null)
|
|
136
|
+
zeilen.push(betrag((0, texte_js_1.labelText)('shift_receipt.cash_sales'), bon.cashSalesCents));
|
|
137
|
+
if (bon.cashCancellationsCents !== null)
|
|
138
|
+
zeilen.push(betrag((0, texte_js_1.labelText)('shift_receipt.cash_cancellations'), bon.cashCancellationsCents));
|
|
139
|
+
if (bon.movements.length > 0) {
|
|
140
|
+
zeilen.push(text((0, texte_js_1.labelText)('shift_receipt.movements'), 'left', true));
|
|
141
|
+
for (const m of bon.movements) {
|
|
142
|
+
zeilen.push(betrag(`${(0, texte_js_1.labelText)('shift_receipt.number', { number: m.number })} ${artText(m.type)}`, m.amountCents));
|
|
143
|
+
if (m.note)
|
|
144
|
+
zeilen.push(text(` ${m.note}`));
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (bon.expectedCents !== null)
|
|
148
|
+
zeilen.push(betrag((0, texte_js_1.labelText)('shift_receipt.expected'), bon.expectedCents));
|
|
149
|
+
if (bon.countedCents !== null) {
|
|
150
|
+
zeilen.push(betrag((0, texte_js_1.labelText)('shift_receipt.counted'), bon.countedCents));
|
|
151
|
+
zeilen.push(...stueckelungZeilen(bon.countedDenominations));
|
|
152
|
+
}
|
|
153
|
+
if (bon.differenceCents !== null)
|
|
154
|
+
zeilen.push(betrag((0, texte_js_1.labelText)('shift_receipt.difference'), bon.differenceCents));
|
|
155
|
+
if (bon.comment)
|
|
156
|
+
zeilen.push(text(`${(0, texte_js_1.labelText)('shift_receipt.comment')}: ${bon.comment}`));
|
|
157
|
+
zeilen.push(...nachZaehlungZeilen(bon));
|
|
158
|
+
// Zur Information: unbar, Zaehler.
|
|
159
|
+
zeilen.push(regel());
|
|
160
|
+
if (bon.nonCashByMethod.length > 0) {
|
|
161
|
+
zeilen.push(text((0, texte_js_1.labelText)('shift_receipt.non_cash'), 'left', true));
|
|
162
|
+
for (const u of bon.nonCashByMethod)
|
|
163
|
+
zeilen.push(betrag(zahlartText(u.method), u.cents));
|
|
164
|
+
}
|
|
165
|
+
zeilen.push(anzahl((0, texte_js_1.labelText)('shift_receipt.receipts'), bon.receiptCount));
|
|
166
|
+
zeilen.push(anzahl((0, texte_js_1.labelText)('shift_receipt.cancellations'), bon.cancellationCount));
|
|
167
|
+
zeilen.push(anzahl((0, texte_js_1.labelText)('shift_receipt.openings_without_sale'), bon.openingsWithoutSale));
|
|
168
|
+
// Trinkgeld je Mitarbeiter (shiftTipLines): verdient immer, ueber Lohn, schon genommen und offen
|
|
169
|
+
// nur ungleich 0; wer ueberall 0 hat, entfaellt, ohne Mitarbeiter auch die Ueberschrift.
|
|
170
|
+
const trinkgeld = bon.tips.map((t) => ({ t, z: (0, schicht_js_1.shiftTipLines)(t) })).filter(({ z }) => z.length > 0);
|
|
171
|
+
if (trinkgeld.length > 0) {
|
|
172
|
+
zeilen.push(regel());
|
|
173
|
+
zeilen.push(text((0, texte_js_1.labelText)('shift_receipt.tips'), 'left', true));
|
|
174
|
+
for (const { t, z } of trinkgeld) {
|
|
175
|
+
zeilen.push(text(t.name ?? t.registerUserId));
|
|
176
|
+
for (const zeile of z)
|
|
177
|
+
zeilen.push(betrag(` ${zeile.text}`, zeile.cents));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return { lines: zeilen, paperSize, ruleset: layout_js_1.CURRENT_LAYOUT_RULESET };
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Bon einer Kassenbewegung (Einzahlung, Auszahlung, Umbuchung). Wirft
|
|
184
|
+
* (`KasseneckValidationError`, `scope: 'request'`), wenn die Bon-Daten keine
|
|
185
|
+
* Kassenbewegung sind.
|
|
186
|
+
*/
|
|
187
|
+
function cashMovementLayout(receipt, options = {}) {
|
|
188
|
+
const name = 'cashMovementLayout';
|
|
189
|
+
const paperSize = papier(name, options);
|
|
190
|
+
const bon = (0, schicht_lesen_js_1.bewegungsBon)({ name, pfad: 'receipt', scope: 'request' }, receipt);
|
|
191
|
+
const m = bon.movement;
|
|
192
|
+
const zeilen = [];
|
|
193
|
+
kopfblock(zeilen, bon, 'shift_receipt.title_movement');
|
|
194
|
+
if (bon.shift !== null)
|
|
195
|
+
zeilen.push(kopf((0, texte_js_1.labelText)('shift_receipt.shift'), (0, texte_js_1.labelText)('shift_receipt.number', { number: bon.shift.number })));
|
|
196
|
+
zeilen.push(regel());
|
|
197
|
+
zeilen.push(kopf((0, texte_js_1.labelText)('shift_receipt.movement_number'), String(m.number)));
|
|
198
|
+
zeilen.push(kopf((0, texte_js_1.labelText)('shift_receipt.type'), artText(m.type)));
|
|
199
|
+
zeilen.push(betrag((0, texte_js_1.labelText)('shift_receipt.amount'), m.amountCents));
|
|
200
|
+
wennText(zeilen, (0, texte_js_1.labelText)('shift_receipt.location'), m.location === null ? null : ortText(m.location));
|
|
201
|
+
wennText(zeilen, (0, texte_js_1.labelText)('shift_receipt.recipient'), m.recipientName);
|
|
202
|
+
wennText(zeilen, (0, texte_js_1.labelText)('shift_receipt.target_drawer'), m.targetDrawerName);
|
|
203
|
+
wennText(zeilen, (0, texte_js_1.labelText)('shift_receipt.note'), m.note);
|
|
204
|
+
wennText(zeilen, (0, texte_js_1.labelText)('shift_receipt.operator'), m.byName);
|
|
205
|
+
wennText(zeilen, (0, texte_js_1.labelText)('shift_receipt.time'), zeit(m.at));
|
|
206
|
+
return { lines: zeilen, paperSize, ruleset: layout_js_1.CURRENT_LAYOUT_RULESET };
|
|
207
|
+
}
|
|
@@ -22,7 +22,7 @@ import { KasseneckApiError } from '../client/errors.js';
|
|
|
22
22
|
* ueber `KasseneckApiError.code` lesbar; die Kasse braucht dafuer einen
|
|
23
23
|
* Rueckfallzweig.
|
|
24
24
|
*/
|
|
25
|
-
export declare const REGISTER_ERROR_CODES: readonly ["account_not_found", "admin_required", "api_not_approved", "app_check_invalid", "app_check_missing", "cashregister_in_use", "cashregister_not_assigned", "cashregister_not_found", "cashregister_token_invalid", "cashregister_token_missing", "device_bound_elsewhere", "device_not_found", "device_not_paired", "device_takeover_required", "dialect_mismatch", "internal_translation_error", "licenses_exhausted", "live_not_enabled", "location_outside", "location_required", "login_failed", "login_mode_select_user", "login_unavailable", "method_not_allowed", "mfa_required", "not_found", "pairing_code_expired", "pairing_code_unknown", "pairing_code_used", "pairing_failed", "password_change_required", "register_user_no_business", "register_user_not_allowed", "register_user_not_found", "register_user_only", "response_translation_failed", "session_ended", "session_expired", "session_not_running", "session_other_cashregister", "too_many_attempts", "unauthorized", "user_disabled", "user_verification_failed", "validation", "route_missing"];
|
|
25
|
+
export declare const REGISTER_ERROR_CODES: readonly ["account_not_found", "action_confirmation_required", "admin_required", "api_not_approved", "app_check_invalid", "app_check_missing", "cashregister_in_use", "cashregister_not_assigned", "cashregister_not_found", "cashregister_token_invalid", "cashregister_token_missing", "device_bound_elsewhere", "device_not_found", "device_not_paired", "device_takeover_required", "dialect_mismatch", "internal_translation_error", "licenses_exhausted", "live_not_enabled", "location_outside", "location_required", "login_failed", "login_mode_select_user", "login_unavailable", "method_not_allowed", "mfa_required", "not_found", "pairing_code_expired", "pairing_code_unknown", "pairing_code_used", "pairing_failed", "password_change_required", "register_user_no_business", "register_user_not_allowed", "register_user_not_found", "register_user_only", "response_translation_failed", "second_factor_required", "session_ended", "session_expired", "session_not_running", "session_other_cashregister", "too_many_attempts", "unauthorized", "user_disabled", "user_verification_failed", "validation", "route_missing"];
|
|
26
26
|
export type RegisterErrorCode = typeof REGISTER_ERROR_CODES[number];
|
|
27
27
|
export declare function isRegisterErrorCode(value: unknown): value is RegisterErrorCode;
|
|
28
28
|
/** Der Code eines geworfenen Fehlers, wenn es einer der Kassen-Anmeldung ist; sonst `undefined`. */
|
|
@@ -33,6 +33,7 @@ const fehlercodes_js_1 = require("../client/fehlercodes.js");
|
|
|
33
33
|
*/
|
|
34
34
|
exports.REGISTER_ERROR_CODES = Object.freeze([
|
|
35
35
|
'account_not_found',
|
|
36
|
+
'action_confirmation_required',
|
|
36
37
|
'admin_required',
|
|
37
38
|
'api_not_approved',
|
|
38
39
|
'app_check_invalid',
|
|
@@ -68,6 +69,7 @@ exports.REGISTER_ERROR_CODES = Object.freeze([
|
|
|
68
69
|
'register_user_not_found',
|
|
69
70
|
'register_user_only',
|
|
70
71
|
'response_translation_failed',
|
|
72
|
+
'second_factor_required',
|
|
71
73
|
'session_ended',
|
|
72
74
|
'session_expired',
|
|
73
75
|
'session_not_running',
|
|
@@ -14,7 +14,7 @@ export declare function innereNamen(schema: SchemaObjekt): Map<string, string>;
|
|
|
14
14
|
export declare const _RUECKGABE_NACH_AUSSEN: Readonly<Record<string, string>>;
|
|
15
15
|
/**
|
|
16
16
|
* Ein Belegdokument, wie Handler und Rand es vor der Uebersetzung sehen:
|
|
17
|
-
* ohne Storno-Marke
|
|
17
|
+
* ohne Storno-Marke, Lager-Standort, Lade und Schicht (storno-core.ohneInterneBelegFelder,
|
|
18
18
|
* Rand ohneStornoMarke). Alles andere bleibt woertlich, auch `pruefangaben` im
|
|
19
19
|
* Beleg selbst (der Server reicht sie so durch). Wirft, wenn es kein
|
|
20
20
|
* Belegdokument ist.
|