@kreiseck/kasseneck-api 0.7.1 → 0.8.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.
@@ -70,7 +70,7 @@ function createHpsPayments(client, target, options = {}) {
70
70
  return `Antwort mit technischem Fehler (${transaction_response_js_1.TECHNICAL_ERROR_CODE}) -- keine Aussage ueber den Vorgang, Ausgang wird geklaert`;
71
71
  }
72
72
  if ((0, transaction_response_js_1.isUnknownCode)(res)) {
73
- return `Terminal nennt einen unbekannten Code (${res.responseCode}) -- Ausgang wird geklaert`;
73
+ return `Terminal nennt einen unbekannten Code (${res.responseCode})${klartext(res)} -- Ausgang wird geklaert`;
74
74
  }
75
75
  return `Antwort ohne Aussage (${res.responseCode}) -- Ausgang wird geklaert`;
76
76
  }
@@ -83,10 +83,21 @@ function createHpsPayments(client, target, options = {}) {
83
83
  return `Status: technischer Fehler (${transaction_response_js_1.TECHNICAL_ERROR_CODE}) -- keine Aussage ueber den Vorgang`;
84
84
  }
85
85
  if ((0, transaction_response_js_1.isUnknownCode)(status)) {
86
- return `Status: unbekannter Code (${status.responseCode}) -- keine Aussage`;
86
+ return `Status: unbekannter Code (${status.responseCode})${klartext(status)} -- keine Aussage`;
87
87
  }
88
88
  return null;
89
89
  }
90
+ /**
91
+ * Der Klartext des Terminals zu einem UNBEKANNTEN Code, als Zusatz fuer den
92
+ * Nachweis -- oder leer, wenn keiner mitkam. Nur hier, nicht bei den
93
+ * gemessenen Codes: deren Bedeutung ist benannt. Bei einem unbekannten Code
94
+ * ist er dagegen das Einzige, was ein Mensch lesen kann -- "PIN falsch"
95
+ * neben `55` haette am 02.09.2026 gereicht, um nicht "bezahlt" zu buchen.
96
+ */
97
+ function klartext(res) {
98
+ const text = res.responseText?.trim();
99
+ return text ? ` "${text}"` : '';
100
+ }
90
101
  /** Ordnet eine Terminal-Antwort ein. `null`, wenn sie nichts entscheidet. */
91
102
  function fromResponse(res, id, steps) {
92
103
  if (!(0, transaction_response_js_1.isConclusive)(res))
@@ -188,9 +199,19 @@ function createHpsPayments(client, target, options = {}) {
188
199
  }
189
200
  return null;
190
201
  }
191
- function open(id, steps) {
202
+ /**
203
+ * [letzteAntwort] ist die letzte Antwort, die das Terminal in dieser
204
+ * Klaerung gab -- als `lastResponse` fuer Anzeige und Katalog,
205
+ * ausdruecklich NICHT als `response`.
206
+ */
207
+ function open(id, steps, letzteAntwort) {
192
208
  emit('resolved', steps[steps.length - 1], id);
193
- return { outcome: 'unresolved', transactionId: id, steps: [...steps] };
209
+ return {
210
+ outcome: 'unresolved',
211
+ transactionId: id,
212
+ ...(letzteAntwort ? { lastResponse: letzteAntwort } : {}),
213
+ steps: [...steps],
214
+ };
194
215
  }
195
216
  /**
196
217
  * Fuehrt [call] aus, aber hoechstens so lange, wie vom [resolveBudgetMs]
@@ -263,7 +284,7 @@ function createHpsPayments(client, target, options = {}) {
263
284
  * [NO_STATEMENT_CODE] (`9027`) beim Pollen einen Aussagewert, den es sonst
264
285
  * nicht hat. Siehe [ausGeschlossenerAntwort].
265
286
  */
266
- async function resolve(id, steps, antwortMitCode = false) {
287
+ async function resolve(id, steps, antwortMitCode = false, letzteAntwort) {
267
288
  emit('resolving', 'Ausgang offen, Klaerung laeuft', id);
268
289
  const start = now();
269
290
  const elapsedMs = () => now() - start;
@@ -284,6 +305,7 @@ function createHpsPayments(client, target, options = {}) {
284
305
  try {
285
306
  status = await withinBudget(elapsedMs, () => client.status({ ...target, transactionId: id }));
286
307
  transportFailures = 0;
308
+ letzteAntwort = status;
287
309
  }
288
310
  catch (e) {
289
311
  transportFailures += 1;
@@ -312,7 +334,7 @@ function createHpsPayments(client, target, options = {}) {
312
334
  wait = nextWait(wait);
313
335
  }
314
336
  steps.push('Ausgang bleibt offen');
315
- return open(id, steps);
337
+ return open(id, steps, letzteAntwort);
316
338
  }
317
339
  /**
318
340
  * Liest `9027` beim Pollen als "nicht genehmigt" -- aber NUR, wenn das
@@ -372,7 +394,7 @@ function createHpsPayments(client, target, options = {}) {
372
394
  * Budget, Backoff und Transportfehler-Deckelung sind unveraendert aus
373
395
  * [resolve] uebernommen.
374
396
  */
375
- async function resolveCancel(id, steps) {
397
+ async function resolveCancel(id, steps, letzteAntwort) {
376
398
  emit('resolving', 'Ausgang offen, Klaerung laeuft', id);
377
399
  const start = now();
378
400
  const elapsedMs = () => now() - start;
@@ -393,6 +415,7 @@ function createHpsPayments(client, target, options = {}) {
393
415
  status = await withinBudget(elapsedMs, () => client.status({ ...target, transactionId: id }));
394
416
  transportFailures = 0;
395
417
  answeredQueries += 1;
418
+ letzteAntwort = status;
396
419
  }
397
420
  catch (e) {
398
421
  transportFailures += 1;
@@ -416,7 +439,7 @@ function createHpsPayments(client, target, options = {}) {
416
439
  wait = nextWait(wait);
417
440
  }
418
441
  steps.push('Ausgang bleibt offen');
419
- return open(id, steps);
442
+ return open(id, steps, letzteAntwort);
420
443
  }
421
444
  async function pay(paymentOptions) {
422
445
  const id = paymentOptions.transactionId ?? (0, transaction_id_js_1.newHpsTransactionId)();
@@ -455,7 +478,7 @@ function createHpsPayments(client, target, options = {}) {
455
478
  return settled;
456
479
  steps.push(offeneAntwort(res));
457
480
  }
458
- return resolve(id, steps, res?.responseCode !== undefined);
481
+ return resolve(id, steps, res?.responseCode !== undefined, res);
459
482
  }
460
483
  /**
461
484
  * Gutschrift mit geklaertem Ausgang -- EXAKT derselbe Klaerweg wie [pay]
@@ -499,7 +522,7 @@ function createHpsPayments(client, target, options = {}) {
499
522
  // Dieselbe Klaerfunktion wie [pay]: die Kennung ist die des NEUEN
500
523
  // Vorgangs, eine Statusabfrage darauf liefert also genau dessen Ausgang,
501
524
  // und der Abbruch ist derselbe Diskriminator wie bei einer Zahlung.
502
- return resolve(id, steps, res?.responseCode !== undefined);
525
+ return resolve(id, steps, res?.responseCode !== undefined, res);
503
526
  }
504
527
  /**
505
528
  * Aufhebung (Storno/Void) einer bestehenden Zahlung mit geklaertem Ausgang.
@@ -544,7 +567,7 @@ function createHpsPayments(client, target, options = {}) {
544
567
  if (!(0, transaction_response_js_1.isCanceled)(res))
545
568
  steps.push(offeneAntwort(res));
546
569
  }
547
- return resolveCancel(id, steps);
570
+ return resolveCancel(id, steps, res);
548
571
  }
549
572
  return { pay, refund, cancel };
550
573
  }
@@ -72,6 +72,18 @@ export declare const INVALID_AMOUNT_CODE = "9003";
72
72
  export declare const AMOUNT_OUT_OF_RANGE_CODE = "100019";
73
73
  /** Siehe [HPS_MEASURED_CODES]: Terminal-Kennung unbekannt. */
74
74
  export declare const INVALID_TID_CODE = "100108";
75
+ /**
76
+ * Siehe [HPS_MEASURED_CODES]: Host-Ablehnung, falsche PIN -- nichts belastet.
77
+ *
78
+ * Zweistellig, weil ein Antwortcode des HOSTS (ISO 8583, 55 = "Incorrect
79
+ * PIN"), kein `9xxx`-Terminalcode und kein `100xxx`-Code der HPS-Anwendung.
80
+ * Daraus folgt KEINE Regel fuer andere zweistellige Codes: in derselben
81
+ * Familie stehen Genehmigungen (`08`, `10`, `11`, `85`). Jeder andere
82
+ * Host-Code bleibt eine Wissensluecke, bis er gemessen ist -- und die
83
+ * Zwei-9027-Regel in `payments.ts` faengt ihn nicht, weil die Statusabfrage
84
+ * dann nicht 9027 antwortet, sondern mit dem Code selbst.
85
+ */
86
+ export declare const WRONG_PIN_CODE = "55";
75
87
  /**
76
88
  * HTTP `409` ("Terminal is busy"): das Terminal serialisiert und weist eine
77
89
  * zweite Anfrage ab, waehrend eine erste noch laeuft. Am 27.08.2026 gemessen:
@@ -28,7 +28,7 @@
28
28
  * sein kann, als `declined` gemeldet.
29
29
  */
30
30
  Object.defineProperty(exports, "__esModule", { value: true });
31
- exports.TERMINAL_BUSY_HTTP_STATUS = exports.INVALID_TID_CODE = exports.AMOUNT_OUT_OF_RANGE_CODE = exports.INVALID_AMOUNT_CODE = exports.NOT_ABORTABLE_CODE = exports.CARD_NOT_PRESENT_CODE = exports.ABORTED_CODE = exports.TECHNICAL_ERROR_CODE = exports.NO_STATEMENT_CODE = exports.TRANSACTION_CANCELED_CODE = exports.INVALID_TRANSACTION_CODE = exports.APPROVED_CODE = exports.HPS_MEASURED_CODES = void 0;
31
+ exports.TERMINAL_BUSY_HTTP_STATUS = exports.WRONG_PIN_CODE = exports.INVALID_TID_CODE = exports.AMOUNT_OUT_OF_RANGE_CODE = exports.INVALID_AMOUNT_CODE = exports.NOT_ABORTABLE_CODE = exports.CARD_NOT_PRESENT_CODE = exports.ABORTED_CODE = exports.TECHNICAL_ERROR_CODE = exports.NO_STATEMENT_CODE = exports.TRANSACTION_CANCELED_CODE = exports.INVALID_TRANSACTION_CODE = exports.APPROVED_CODE = exports.HPS_MEASURED_CODES = void 0;
32
32
  exports.parseHpsTransactionResponse = parseHpsTransactionResponse;
33
33
  exports.isApproved = isApproved;
34
34
  exports.isInProgress = isInProgress;
@@ -96,6 +96,15 @@ exports.HPS_MEASURED_CODES = [
96
96
  + 'nicht; der Vorgang wird abgewiesen, bevor etwas geschieht',
97
97
  conclusive: true,
98
98
  },
99
+ {
100
+ code: '55',
101
+ meaning: '"PIN falsch" -- Host-Ablehnung wegen falscher PIN, die erste '
102
+ + 'gemessene Host-Ablehnung ueberhaupt (02.09.2026 im Betrieb, TID '
103
+ + '3556988, HPS 1.11.4, Firmware 2.3.9): die Zahlung antwortete direkt '
104
+ + 'damit, die Statusabfrage danach elfmal in Folge ebenso -- eine '
105
+ + 'Host-Ablehnung bleibt am Terminal abrufbar; nichts belastet',
106
+ conclusive: true,
107
+ },
99
108
  ];
100
109
  /** `responseCode` einer genehmigten Zahlung. */
101
110
  exports.APPROVED_CODE = '0';
@@ -119,6 +128,18 @@ exports.INVALID_AMOUNT_CODE = '9003';
119
128
  exports.AMOUNT_OUT_OF_RANGE_CODE = '100019';
120
129
  /** Siehe [HPS_MEASURED_CODES]: Terminal-Kennung unbekannt. */
121
130
  exports.INVALID_TID_CODE = '100108';
131
+ /**
132
+ * Siehe [HPS_MEASURED_CODES]: Host-Ablehnung, falsche PIN -- nichts belastet.
133
+ *
134
+ * Zweistellig, weil ein Antwortcode des HOSTS (ISO 8583, 55 = "Incorrect
135
+ * PIN"), kein `9xxx`-Terminalcode und kein `100xxx`-Code der HPS-Anwendung.
136
+ * Daraus folgt KEINE Regel fuer andere zweistellige Codes: in derselben
137
+ * Familie stehen Genehmigungen (`08`, `10`, `11`, `85`). Jeder andere
138
+ * Host-Code bleibt eine Wissensluecke, bis er gemessen ist -- und die
139
+ * Zwei-9027-Regel in `payments.ts` faengt ihn nicht, weil die Statusabfrage
140
+ * dann nicht 9027 antwortet, sondern mit dem Code selbst.
141
+ */
142
+ exports.WRONG_PIN_CODE = '55';
122
143
  /**
123
144
  * HTTP `409` ("Terminal is busy"): das Terminal serialisiert und weist eine
124
145
  * zweite Anfrage ab, waehrend eine erste noch laeuft. Am 27.08.2026 gemessen:
@@ -10,3 +10,4 @@ export { verteileRabatt } from '../receipt/discount.js';
10
10
  export { cancelScopeOf, receiptsScopeOf, type RegisterScope, type RegisterUserPerms } from '../register/pairing.js';
11
11
  export { type NetzDrucker, type DruckJob, type DruckJobStatus, type CreatePrintJobOptions, listMyPrinters, createPrintJob, getPrintJob } from './drucker.js';
12
12
  export { listMyTipRecipients } from './trinkgeld.js';
13
+ export { MELDUNGEN, FEHLERREGELN, meldung, meldungGiltFuer, type Meldung, type MeldungsSchluessel, type Fehlerart, type Seite, } from './texte.js';
@@ -14,3 +14,5 @@ export { verteileRabatt } from '../receipt/discount.js';
14
14
  export { cancelScopeOf, receiptsScopeOf } from '../register/pairing.js';
15
15
  export { listMyPrinters, createPrintJob, getPrintJob } from './drucker.js';
16
16
  export { listMyTipRecipients } from './trinkgeld.js';
17
+ // Was die Kasse selbst sagt — ein Katalog fuer Browser-Kasse und App.
18
+ export { MELDUNGEN, FEHLERREGELN, meldung, meldungGiltFuer, } from './texte.js';
@@ -0,0 +1,336 @@
1
+ /**
2
+ * Was die Kasse selbst sagt — auf dem Bildschirm, in beiden Huellen.
3
+ *
4
+ * Die Browser-Kasse und die Kassen-App sind eine Kasse. Was der Kassier bei
5
+ * einem Fehler liest, steht hier genau einmal; beide Apps beziehen den Satz
6
+ * von hier, und wer ihn aendert, aendert ihn auf beiden Seiten oder gar nicht.
7
+ *
8
+ * Nicht hier: die fachlichen Saetze des Backends („Kopplungs-Code ist
9
+ * abgelaufen.", „PIN falsch, noch 2 Versuche"). Die gehen unveraendert durch.
10
+ *
11
+ * Ein Satz sagt, was los ist, und was zu tun ist. Nie Innereien.
12
+ *
13
+ * Schluessel: `bereich.name`. Ein Schluessel wird nie umgedeutet — wer den
14
+ * Sinn aendert, legt einen neuen an. `nur` nennt die Seite, wenn ein Satz nur
15
+ * auf einer Plattform vorkommen kann.
16
+ */
17
+ export type Seite = 'web' | 'app';
18
+ export interface Meldung {
19
+ readonly text: string;
20
+ /** Erlaubte Platzhalter `{name}`; muessen exakt die im Text sein. */
21
+ readonly platzhalter?: readonly string[];
22
+ /** Fehlt es, gilt der Satz fuer beide Seiten. */
23
+ readonly nur?: readonly Seite[];
24
+ }
25
+ declare const MELDUNGEN_ROH: {
26
+ readonly 'netz.keine_verbindung': {
27
+ readonly text: "Keine Verbindung zum Server. Bitte die Internetverbindung prüfen und erneut versuchen.";
28
+ };
29
+ readonly 'netz.zeitablauf': {
30
+ readonly text: "Der Server antwortet nicht. Bitte die Internetverbindung prüfen und erneut versuchen.";
31
+ };
32
+ readonly 'server.unerwartet': {
33
+ readonly text: "Der Server hat unerwartet geantwortet (HTTP {status}). Bitte den Support verständigen.";
34
+ readonly platzhalter: readonly ["status"];
35
+ };
36
+ readonly 'kopplung.code_fehlt': {
37
+ readonly text: "Bitte den Kopplungs-Code eingeben.";
38
+ };
39
+ readonly 'kopplung.fehlgeschlagen': {
40
+ readonly text: "Die Kopplung ist fehlgeschlagen. Bitte erneut versuchen.";
41
+ };
42
+ readonly 'kopplung.unvollstaendig': {
43
+ readonly text: "Die Kopplung ist unvollständig zurückgekommen. Bitte im Panel einen neuen Code erzeugen und noch einmal versuchen.";
44
+ };
45
+ readonly 'geraet.browser_speicher': {
46
+ readonly text: "Dieses Gerät konnte nicht gespeichert werden — der Browser-Speicher steht nicht zur Verfügung. Bitte den privaten Modus verlassen.";
47
+ readonly nur: readonly ["web"];
48
+ };
49
+ readonly 'anmeldung.pin_fehlt': {
50
+ readonly text: "Bitte die PIN eingeben.";
51
+ };
52
+ readonly 'anmeldung.fehlgeschlagen': {
53
+ readonly text: "Die Anmeldung ist fehlgeschlagen. Bitte erneut versuchen.";
54
+ };
55
+ readonly 'anmeldung.nicht_abgeschlossen': {
56
+ readonly text: "Die Anmeldung konnte nicht abgeschlossen werden. Bitte erneut versuchen.";
57
+ };
58
+ readonly 'anmeldung.wird_abgeschlossen': {
59
+ readonly text: "Anmeldung wird gerade abgeschlossen — bitte gleich noch einmal drücken.";
60
+ };
61
+ readonly 'sitzung.abgelaufen': {
62
+ readonly text: "Die Sitzung ist abgelaufen. Bitte erneut anmelden.";
63
+ };
64
+ readonly 'sitzung.abgelaufen_ohne_netz': {
65
+ readonly text: "Keine Verbindung zum Server — die Sitzung ist abgelaufen. Bitte erneut anmelden.";
66
+ };
67
+ readonly 'sitzung.keine': {
68
+ readonly text: "Keine Sitzung.";
69
+ };
70
+ readonly 'rechte.nicht_aenderbar': {
71
+ readonly text: "Das darfst du nicht ändern — das Recht dafür vergibt der Inhaber im Panel.";
72
+ };
73
+ readonly 'kasse.laden_fehlgeschlagen': {
74
+ readonly text: "Die Kasse konnte nicht geladen werden.";
75
+ };
76
+ readonly 'artikel.laden_fehlgeschlagen': {
77
+ readonly text: "Die Artikel konnten nicht geladen werden.";
78
+ };
79
+ readonly 'artikel.keine_freigegeben': {
80
+ readonly text: "Keine Artikel an dieser Kasse. Im Panel unter „Kacheln & Gruppen“ freischalten.";
81
+ };
82
+ readonly 'artikel.keine_gefunden': {
83
+ readonly text: "Keine Artikel gefunden.";
84
+ };
85
+ readonly 'artikel.steuersatz_unbekannt': {
86
+ readonly text: "„{name}“ hat einen Steuersatz, den die Kasse nicht kennt.";
87
+ readonly platzhalter: readonly ["name"];
88
+ };
89
+ readonly 'position.betrag_fehlt': {
90
+ readonly text: "Bitte einen Betrag eingeben.";
91
+ };
92
+ readonly 'position.bezeichnung_fehlt': {
93
+ readonly text: "Bitte eine Bezeichnung eingeben — sie steht am Beleg.";
94
+ };
95
+ readonly 'rabatt.prozent_ungueltig': {
96
+ readonly text: "Bitte einen Prozentwert zwischen 0,1 und 100 eingeben.";
97
+ };
98
+ readonly 'abschluss.fehlgeschlagen': {
99
+ readonly text: "Der Abschluss ist fehlgeschlagen.";
100
+ };
101
+ readonly 'abschluss.unklar': {
102
+ readonly 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.";
103
+ };
104
+ readonly 'abschluss.nullbeleg_fehlgeschlagen': {
105
+ readonly text: "Der Nullbeleg konnte nicht erstellt werden.";
106
+ };
107
+ readonly 'abschluss.signatur_ausgefallen': {
108
+ readonly text: "Die Signatureinheit hat nicht geantwortet. Der Beleg ist gültig und trägt den Vermerk „Sicherheitseinrichtung ausgefallen“.";
109
+ };
110
+ readonly 'kartenzahlung.nicht_moeglich': {
111
+ readonly text: "Kartenzahlung nicht möglich.";
112
+ };
113
+ readonly 'kartenzahlung.nicht_zustande': {
114
+ readonly text: "Die Kartenzahlung ist nicht zustande gekommen.";
115
+ };
116
+ readonly 'kartenzahlung.nicht_gestartet': {
117
+ readonly text: "Kartenzahlung nicht gestartet: {grund}";
118
+ readonly platzhalter: readonly ["grund"];
119
+ };
120
+ readonly 'kartenzahlung.unklar': {
121
+ readonly text: "Unklar, ob die Kartenzahlung durchgegangen ist — die Verbindung zum Terminal riss ab. Bitte am Terminal-Beleg nachsehen, BEVOR neu kassiert wird: die Karte kann belastet sein.";
122
+ };
123
+ readonly 'kartenzahlung.unklar_mit_kennung': {
124
+ readonly text: "Unklar, ob die Kartenzahlung durchgegangen ist — die Verbindung zum Terminal riss ab. Bitte am Terminal-Beleg nachsehen, BEVOR neu kassiert wird: die Karte kann belastet sein. Kennung der Zahlung: {kennung}.";
125
+ readonly platzhalter: readonly ["kennung"];
126
+ };
127
+ readonly 'kartenzahlung.connect_nicht_verbunden': {
128
+ readonly text: "Kartenzahlung nicht möglich: Kasseneck Connect ist nicht verbunden — Einstellungen → Kasseneck Connect.";
129
+ readonly nur: readonly ["web"];
130
+ };
131
+ readonly 'terminal.keines_gefunden': {
132
+ readonly text: "Kein Hobex-Terminal gefunden — ist es eingeschaltet und im selben Netz wie dieser Rechner?";
133
+ readonly nur: readonly ["web"];
134
+ };
135
+ readonly 'terminal.nicht_bereit': {
136
+ readonly text: "Terminal antwortet, ist aber nicht betriebsbereit: {antwort} — TID prüfen.";
137
+ readonly platzhalter: readonly ["antwort"];
138
+ readonly nur: readonly ["web"];
139
+ };
140
+ readonly 'gptom.app_fehlt': {
141
+ readonly text: "Die GP-Tom-App ist auf diesem Gerät nicht da.";
142
+ readonly nur: readonly ["app"];
143
+ };
144
+ readonly 'gptom.suche_fehlgeschlagen': {
145
+ readonly text: "GP Tom: Suche nach der App fehlgeschlagen: {grund}";
146
+ readonly platzhalter: readonly ["grund"];
147
+ readonly nur: readonly ["app"];
148
+ };
149
+ readonly 'gptom.zahlung_fehlgeschlagen': {
150
+ readonly text: "GP Tom: Zahlung fehlgeschlagen: {grund}";
151
+ readonly platzhalter: readonly ["grund"];
152
+ readonly nur: readonly ["app"];
153
+ };
154
+ readonly 'gptom.terminal_antwortet_nicht': {
155
+ readonly text: "Das Terminal hat nicht geantwortet: {grund}";
156
+ readonly platzhalter: readonly ["grund"];
157
+ readonly nur: readonly ["app"];
158
+ };
159
+ readonly 'gptom.zahlung_nicht_abgeschlossen': {
160
+ readonly text: "Die Zahlung wurde nicht abgeschlossen ({code}).";
161
+ readonly platzhalter: readonly ["code"];
162
+ readonly nur: readonly ["app"];
163
+ };
164
+ readonly 'belege.laden_fehlgeschlagen': {
165
+ readonly text: "Die Belege konnten nicht geladen werden.";
166
+ };
167
+ readonly 'belege.keine_im_zeitraum': {
168
+ readonly text: "Keine Belege in diesem Zeitraum.";
169
+ };
170
+ readonly 'beleg.laden_fehlgeschlagen': {
171
+ readonly text: "Der Beleg konnte nicht geladen werden.";
172
+ };
173
+ readonly 'beleg.nicht_gefunden': {
174
+ readonly text: "Der Beleg wurde nicht gefunden.";
175
+ };
176
+ readonly 'storno.fehlgeschlagen': {
177
+ readonly text: "Das Storno ist fehlgeschlagen.";
178
+ };
179
+ readonly 'storno.grund_fehlt': {
180
+ readonly text: "Bitte einen Grund wählen.";
181
+ };
182
+ readonly 'storno.position_fehlt': {
183
+ readonly text: "Bitte mindestens eine Position wählen.";
184
+ };
185
+ readonly 'druck.fehlgeschlagen': {
186
+ readonly text: "Der Ausdruck ist fehlgeschlagen.";
187
+ };
188
+ readonly 'druck.nicht_moeglich': {
189
+ readonly text: "Druck nicht möglich: {grund}";
190
+ readonly platzhalter: readonly ["grund"];
191
+ };
192
+ readonly 'druck.testdruck_fehlgeschlagen': {
193
+ readonly text: "Der Testdruck ist fehlgeschlagen.";
194
+ };
195
+ readonly 'druck.testdruck_nicht_moeglich': {
196
+ readonly text: "Der Testdruck ist fehlgeschlagen: {grund}";
197
+ readonly platzhalter: readonly ["grund"];
198
+ };
199
+ readonly 'druck.kein_drucker': {
200
+ readonly text: "Kein Bondrucker eingerichtet — in den Einstellungen unter Drucker & Lade.";
201
+ };
202
+ readonly 'druck.drucker_nicht_erreichbar': {
203
+ readonly text: "Drucker nicht erreichbar.";
204
+ };
205
+ readonly 'druck.job_abgelaufen': {
206
+ readonly text: "Drucker hat den Beleg nicht abgeholt (abgelaufen).";
207
+ readonly nur: readonly ["web"];
208
+ };
209
+ readonly 'druck.kein_drucker_gefunden': {
210
+ readonly text: "Kein Drucker gefunden — ist er eingeschaltet und im selben Netz wie dieser Rechner?";
211
+ readonly nur: readonly ["web"];
212
+ };
213
+ readonly 'druck.nur_chrome': {
214
+ readonly text: "{weg}-Druck geht nur in Chrome oder Edge (Windows, Mac, Android) — nicht in Safari und nicht am iPad.";
215
+ readonly platzhalter: readonly ["weg"];
216
+ readonly nur: readonly ["web"];
217
+ };
218
+ readonly 'druck.kein_weg_drucker': {
219
+ readonly text: "Kein {weg}-Drucker verbunden — „{weg}-Drucker verbinden“ und den Drucker im Dialog wählen.";
220
+ readonly platzhalter: readonly ["weg"];
221
+ readonly nur: readonly ["web"];
222
+ };
223
+ readonly 'bluetooth.aus': {
224
+ readonly text: "Bluetooth ist ausgeschaltet. Bitte einschalten und erneut suchen.";
225
+ readonly nur: readonly ["app"];
226
+ };
227
+ readonly 'bluetooth.freigabe_fehlt': {
228
+ readonly text: "Bitte die Freigabe in den Geräte-Einstellungen erteilen.";
229
+ readonly nur: readonly ["app"];
230
+ };
231
+ readonly 'bluetooth.suche_fehlgeschlagen': {
232
+ readonly text: "Die Suche ist fehlgeschlagen: {grund}";
233
+ readonly platzhalter: readonly ["grund"];
234
+ readonly nur: readonly ["app"];
235
+ };
236
+ readonly 'connect.antwortet_nicht': {
237
+ readonly text: "Kasseneck Connect antwortet nicht — läuft das Programm auf diesem Rechner?";
238
+ readonly nur: readonly ["web"];
239
+ };
240
+ readonly 'connect.code_abgelaufen': {
241
+ readonly text: "Der Kopplungs-Code ist abgelaufen — im Agent einen neuen erzeugen („kasseneck-connect pair“).";
242
+ readonly nur: readonly ["web"];
243
+ };
244
+ readonly 'connect.zu_viele_versuche': {
245
+ readonly text: "Zu viele Fehlversuche — eine Minute warten und noch einmal versuchen.";
246
+ readonly nur: readonly ["web"];
247
+ };
248
+ readonly 'connect.drucker_antwortet_nicht': {
249
+ readonly text: "Der Drucker antwortet nicht — Strom, Netzwerk und IP prüfen.";
250
+ readonly nur: readonly ["web"];
251
+ };
252
+ readonly 'connect.nicht_gekoppelt': {
253
+ readonly text: "Diese Kasse ist mit Kasseneck Connect nicht gekoppelt — in den Einstellungen „Koppeln“ drücken.";
254
+ readonly nur: readonly ["web"];
255
+ };
256
+ readonly 'connect.drucker_unbekannt': {
257
+ readonly text: "Diesen Drucker kennt Kasseneck Connect nicht (mehr) — bitte neu suchen.";
258
+ readonly nur: readonly ["web"];
259
+ };
260
+ readonly 'connect.ursprung_nicht_freigegeben': {
261
+ readonly text: "Kasseneck Connect nimmt von dieser Adresse nichts an (Ursprung nicht freigegeben).";
262
+ readonly nur: readonly ["web"];
263
+ };
264
+ readonly 'connect.nicht_installiert': {
265
+ readonly text: "Kasseneck Connect nicht gefunden — bitte installieren.";
266
+ readonly nur: readonly ["web"];
267
+ };
268
+ readonly 'einstellungen.laden_fehlgeschlagen': {
269
+ readonly text: "Die Einstellungen konnten nicht geladen werden.";
270
+ };
271
+ readonly 'einstellungen.speichern_fehlgeschlagen': {
272
+ readonly text: "Die Einstellung konnte nicht gespeichert werden.";
273
+ };
274
+ readonly 'einstellungen.noch_nicht_geladen': {
275
+ readonly text: "Noch nicht geladen — bitte kurz warten oder neu anmelden.";
276
+ };
277
+ readonly 'einstellungen.ip_ungueltig': {
278
+ readonly text: "Keine gültige IP-Adresse (z. B. 192.168.1.50).";
279
+ };
280
+ readonly 'entkopplung.fehlgeschlagen': {
281
+ readonly text: "Entkoppeln fehlgeschlagen.";
282
+ };
283
+ readonly 'logo.hochladen_fehlgeschlagen': {
284
+ readonly text: "Hochladen fehlgeschlagen.";
285
+ };
286
+ readonly 'logo.entfernen_fehlgeschlagen': {
287
+ readonly text: "Entfernen fehlgeschlagen.";
288
+ };
289
+ readonly 'app.nicht_im_browser': {
290
+ readonly text: "Die Kassen-App läuft nicht im Browser — dafür gibt es kasse.kasseneck.at.";
291
+ readonly nur: readonly ["app"];
292
+ };
293
+ readonly 'app.im_browser_oeffnen': {
294
+ readonly text: "Bitte im Browser öffnen: {ziel}";
295
+ readonly platzhalter: readonly ["ziel"];
296
+ readonly nur: readonly ["app"];
297
+ };
298
+ };
299
+ export type MeldungsSchluessel = keyof typeof MELDUNGEN_ROH;
300
+ export declare const MELDUNGEN: Record<MeldungsSchluessel, Meldung>;
301
+ /**
302
+ * In welcher Reihenfolge ein Fehler eingeordnet wird — auf beiden Seiten
303
+ * dieselbe. Die Arten:
304
+ * api — HTTP 200, `status:'error'`: der Satz des Backends, woertlich
305
+ * klartext — schon fuer den Bildschirm geschrieben: sein eigener Text
306
+ * zeitablauf — die Frist lief ab, die Anfrage war draussen
307
+ * netz — keine Verbindung zustande gekommen oder abgerissen
308
+ * unerwartet — der Server hat geantwortet, aber nicht wie zugesagt
309
+ * (HTML statt JSON, 500, fehlende Huelle); `status` = HTTP-Code
310
+ * sonst — alles Uebrige ist technisch: der Ersatzsatz des Vorgangs
311
+ */
312
+ export declare const FEHLERREGELN: readonly [{
313
+ readonly art: "api";
314
+ readonly verhalten: "server_text";
315
+ }, {
316
+ readonly art: "klartext";
317
+ readonly verhalten: "eigener_text";
318
+ }, {
319
+ readonly art: "zeitablauf";
320
+ readonly schluessel: "netz.zeitablauf";
321
+ }, {
322
+ readonly art: "netz";
323
+ readonly schluessel: "netz.keine_verbindung";
324
+ }, {
325
+ readonly art: "unerwartet";
326
+ readonly schluessel: "server.unerwartet";
327
+ }, {
328
+ readonly art: "sonst";
329
+ readonly verhalten: "ersatz";
330
+ }];
331
+ export type Fehlerart = (typeof FEHLERREGELN)[number]['art'];
332
+ /** Der Satz zum Schluessel, Platzhalter ersetzt. Fehlt ein Wert, wirft es — ein `{status}` am Tresen waere schlimmer. */
333
+ export declare function meldung(schluessel: MeldungsSchluessel, werte?: Record<string, string | number>): string;
334
+ /** Gilt der Satz auf dieser Seite? */
335
+ export declare function meldungGiltFuer(schluessel: MeldungsSchluessel, seite: Seite): boolean;
336
+ export {};