@kreiseck/kasseneck-api 1.10.1 → 1.11.1

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.
Files changed (152) hide show
  1. package/CHANGELOG.md +247 -0
  2. package/dist/cjs/client/aufrufe.d.ts +5 -5
  3. package/dist/cjs/client/aufrufe.js +22 -2
  4. package/dist/cjs/client/errors.js +2 -0
  5. package/dist/cjs/client/receipts.d.ts +34 -1
  6. package/dist/cjs/client/receipts.js +34 -1
  7. package/dist/cjs/index.d.ts +1 -1
  8. package/dist/cjs/index.js +11 -3
  9. package/dist/cjs/inventory/vertrag.d.ts +1 -1
  10. package/dist/cjs/inventory/vertrag.js +2 -0
  11. package/dist/cjs/invoice/vertrag.d.ts +1 -1
  12. package/dist/cjs/invoice/vertrag.js +2 -0
  13. package/dist/cjs/models/cancellation.d.ts +49 -1
  14. package/dist/cjs/models/cancellation.js +139 -1
  15. package/dist/cjs/models/index.d.ts +2 -2
  16. package/dist/cjs/models/index.js +10 -2
  17. package/dist/cjs/models/payment-errors.d.ts +1 -1
  18. package/dist/cjs/models/payment-errors.js +2 -0
  19. package/dist/cjs/models/receipt-email.d.ts +1 -1
  20. package/dist/cjs/models/receipt-email.js +2 -0
  21. package/dist/cjs/models/receipt-errors.d.ts +1 -1
  22. package/dist/cjs/models/receipt-errors.js +2 -0
  23. package/dist/cjs/models/receipt-item.d.ts +10 -0
  24. package/dist/cjs/models/receipt-item.js +3 -0
  25. package/dist/cjs/models/receipt.d.ts +19 -1
  26. package/dist/cjs/models/receipt.js +28 -4
  27. package/dist/cjs/pos/client.js +10 -0
  28. package/dist/cjs/pos/errors.d.ts +4 -3
  29. package/dist/cjs/pos/errors.js +21 -2
  30. package/dist/cjs/pos/index.d.ts +6 -2
  31. package/dist/cjs/pos/index.js +33 -3
  32. package/dist/cjs/pos/schicht-lesen.d.ts +39 -0
  33. package/dist/cjs/pos/schicht-lesen.js +405 -0
  34. package/dist/cjs/pos/schicht-typen.d.ts +380 -0
  35. package/dist/cjs/pos/schicht-typen.js +59 -0
  36. package/dist/cjs/pos/schicht.d.ts +208 -0
  37. package/dist/cjs/pos/schicht.js +235 -0
  38. package/dist/cjs/pos/settings.d.ts +37 -1
  39. package/dist/cjs/pos/settings.js +43 -3
  40. package/dist/cjs/pos/texte.d.ts +627 -0
  41. package/dist/cjs/pos/texte.js +236 -0
  42. package/dist/cjs/react/index.js +1 -1
  43. package/dist/cjs/receipt/grid.js +2 -2
  44. package/dist/cjs/receipt/layout.d.ts +5 -0
  45. package/dist/cjs/receipt/layout.js +14 -5
  46. package/dist/cjs/receipt/shift-sheet.d.ts +33 -0
  47. package/dist/cjs/receipt/shift-sheet.js +207 -0
  48. package/dist/cjs/register/errors.d.ts +1 -1
  49. package/dist/cjs/register/errors.js +2 -0
  50. package/dist/cjs/stored/draht.d.ts +1 -1
  51. package/dist/cjs/stored/draht.js +4 -3
  52. package/dist/cjs/stored/einstellungen.js +26 -3
  53. package/dist/cjs/stored/vokabular.d.ts +1 -1
  54. package/dist/cjs/stored/vokabular.js +118 -12
  55. package/dist/cjs/version.d.ts +1 -1
  56. package/dist/cjs/version.js +1 -1
  57. package/dist/esm/client/aufrufe.d.ts +5 -5
  58. package/dist/esm/client/aufrufe.js +22 -2
  59. package/dist/esm/client/errors.js +2 -0
  60. package/dist/esm/client/receipts.d.ts +34 -1
  61. package/dist/esm/client/receipts.js +35 -2
  62. package/dist/esm/index.d.ts +1 -1
  63. package/dist/esm/index.js +1 -1
  64. package/dist/esm/inventory/vertrag.d.ts +1 -1
  65. package/dist/esm/inventory/vertrag.js +2 -0
  66. package/dist/esm/invoice/vertrag.d.ts +1 -1
  67. package/dist/esm/invoice/vertrag.js +2 -0
  68. package/dist/esm/models/cancellation.d.ts +49 -1
  69. package/dist/esm/models/cancellation.js +132 -0
  70. package/dist/esm/models/index.d.ts +2 -2
  71. package/dist/esm/models/index.js +2 -2
  72. package/dist/esm/models/payment-errors.d.ts +1 -1
  73. package/dist/esm/models/payment-errors.js +2 -0
  74. package/dist/esm/models/receipt-email.d.ts +1 -1
  75. package/dist/esm/models/receipt-email.js +2 -0
  76. package/dist/esm/models/receipt-errors.d.ts +1 -1
  77. package/dist/esm/models/receipt-errors.js +2 -0
  78. package/dist/esm/models/receipt-item.d.ts +10 -0
  79. package/dist/esm/models/receipt-item.js +3 -0
  80. package/dist/esm/models/receipt.d.ts +19 -1
  81. package/dist/esm/models/receipt.js +27 -4
  82. package/dist/esm/pos/client.js +11 -1
  83. package/dist/esm/pos/errors.d.ts +4 -3
  84. package/dist/esm/pos/errors.js +21 -2
  85. package/dist/esm/pos/index.d.ts +6 -2
  86. package/dist/esm/pos/index.js +7 -2
  87. package/dist/esm/pos/schicht-lesen.d.ts +39 -0
  88. package/dist/esm/pos/schicht-lesen.js +392 -0
  89. package/dist/esm/pos/schicht-typen.d.ts +380 -0
  90. package/dist/esm/pos/schicht-typen.js +56 -0
  91. package/dist/esm/pos/schicht.d.ts +208 -0
  92. package/dist/esm/pos/schicht.js +222 -0
  93. package/dist/esm/pos/settings.d.ts +37 -1
  94. package/dist/esm/pos/settings.js +40 -2
  95. package/dist/esm/pos/texte.d.ts +627 -0
  96. package/dist/esm/pos/texte.js +236 -0
  97. package/dist/esm/react/index.js +1 -1
  98. package/dist/esm/receipt/grid.js +2 -2
  99. package/dist/esm/receipt/layout.d.ts +5 -0
  100. package/dist/esm/receipt/layout.js +15 -6
  101. package/dist/esm/receipt/shift-sheet.d.ts +33 -0
  102. package/dist/esm/receipt/shift-sheet.js +203 -0
  103. package/dist/esm/register/errors.d.ts +1 -1
  104. package/dist/esm/register/errors.js +2 -0
  105. package/dist/esm/stored/draht.d.ts +1 -1
  106. package/dist/esm/stored/draht.js +4 -3
  107. package/dist/esm/stored/einstellungen.js +27 -4
  108. package/dist/esm/stored/vokabular.d.ts +1 -1
  109. package/dist/esm/stored/vokabular.js +118 -12
  110. package/dist/esm/version.d.ts +1 -1
  111. package/dist/esm/version.js +1 -1
  112. package/fixtures/cancellation-tip-cases.json +679 -0
  113. package/fixtures/expected/cash-movement.grid32.txt +15 -0
  114. package/fixtures/expected/cash-movement.grid48.txt +15 -0
  115. package/fixtures/expected/cash-movement.lines.json +171 -0
  116. package/fixtures/expected/shift-close-blind.grid32.txt +28 -0
  117. package/fixtures/expected/shift-close-blind.grid48.txt +27 -0
  118. package/fixtures/expected/shift-close-blind.lines.json +275 -0
  119. package/fixtures/expected/shift-close-put-in.grid32.txt +38 -0
  120. package/fixtures/expected/shift-close-put-in.grid48.txt +35 -0
  121. package/fixtures/expected/shift-close-put-in.lines.json +403 -0
  122. package/fixtures/expected/shift-close-take-out.grid32.txt +38 -0
  123. package/fixtures/expected/shift-close-take-out.grid48.txt +35 -0
  124. package/fixtures/expected/shift-close-take-out.lines.json +403 -0
  125. package/fixtures/expected/shift-close.grid32.txt +37 -0
  126. package/fixtures/expected/shift-close.grid48.txt +35 -0
  127. package/fixtures/expected/shift-close.lines.json +413 -0
  128. package/fixtures/expected/shift-interim.grid32.txt +28 -0
  129. package/fixtures/expected/shift-interim.grid48.txt +27 -0
  130. package/fixtures/expected/shift-interim.lines.json +293 -0
  131. package/fixtures/hobex-hps-codes.json +1 -1
  132. package/fixtures/invoice-api.schema.json +1 -1
  133. package/fixtures/invoice-texts.json +1 -1
  134. package/fixtures/pos-message-cases.json +45 -0
  135. package/fixtures/pos-texts.json +723 -1
  136. package/fixtures/receipt-due-generated.json +1 -1
  137. package/fixtures/shift-cases.json +87 -0
  138. package/fixtures/shift-receipts.json +41 -0
  139. package/fixtures/surface.json +119 -3
  140. package/fixtures/v3/antworten/belege.json +1 -1
  141. package/fixtures/v3/antworten/belegmail.json +1 -1
  142. package/fixtures/v3/antworten/kasse-belege.json +1 -1
  143. package/fixtures/v3/antworten/kasse.json +10874 -4865
  144. package/fixtures/v3/antworten/lager.json +1 -1
  145. package/fixtures/v3/antworten/rechnungen.json +1 -1
  146. package/fixtures/v3/antworten/storno.json +1 -1
  147. package/fixtures/v3/stored/belege.json +18 -6
  148. package/fixtures/v3/stored/kasse.json +4667 -183
  149. package/fixtures/v3/stored/rechnungen.json +1 -1
  150. package/fixtures/v3/v3-vokabular.json +739 -32
  151. package/fixtures/v3/zahlbetrag-faelle.json +1 -1
  152. package/package.json +1 -1
@@ -0,0 +1,405 @@
1
+ "use strict";
2
+ /**
3
+ * Leser der Schicht-Antworten: aus dem Draht `/v3` werden die Modelle in
4
+ * `schicht-typen.ts`. Paketintern, nicht Teil der Oberflaeche.
5
+ *
6
+ * Regel wie beim Lager: ein Betrag, eine Anzahl oder eine Nummer ist eine
7
+ * Ganzzahl, eine Kennung ein nicht leerer Text, sonst endet der Aufruf mit
8
+ * `KasseneckValidationError`. Ein Ersatzwert wie `0` waere eine falsche
9
+ * Aussage („nichts in der Lade“ statt „Antwort kaputt“). Texte sind
10
+ * nachsichtiger: ein fehlender oder fremder Wert wird `null`.
11
+ *
12
+ * Felder, die nur mit Recht kommen (`expectedCents`, `runningTotals` …),
13
+ * stehen im Modell genau dann, wenn der Server sie sendet.
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.pflichtObjekt = pflichtObjekt;
17
+ exports.schicht = schicht;
18
+ exports.ladeStand = ladeStand;
19
+ exports.bewegung = bewegung;
20
+ exports.schichtBon = schichtBon;
21
+ exports.bewegungsBon = bewegungsBon;
22
+ exports.abschluss = abschluss;
23
+ exports.geoeffnet = geoeffnet;
24
+ exports.gebucht = gebucht;
25
+ exports.gemeldet = gemeldet;
26
+ exports.bericht = bericht;
27
+ const errors_js_1 = require("../client/errors.js");
28
+ const schicht_typen_js_1 = require("./schicht-typen.js");
29
+ const hat = (o, k) => Object.prototype.hasOwnProperty.call(o, k);
30
+ const unter = (ort, teil) => ({ ...ort, pfad: ort.pfad === '' ? teil : `${ort.pfad}.${teil}` });
31
+ function fehler(ort, grund) {
32
+ return new errors_js_1.KasseneckValidationError(ort.name, `${ort.scope === 'response' ? 'Antwort' : 'Bon-Daten'}: ${grund}`, ort.scope);
33
+ }
34
+ function objekt(w) {
35
+ return w !== null && typeof w === 'object' && !Array.isArray(w) ? w : null;
36
+ }
37
+ /** Ein Objekt, das da sein muss. */
38
+ function pflichtObjekt(ort, w) {
39
+ const o = objekt(w);
40
+ if (!o)
41
+ throw fehler(ort, `${ort.pfad || 'data'} ist kein Objekt`);
42
+ return o;
43
+ }
44
+ const text = (w) => (typeof w === 'string' ? w : null);
45
+ function kennung(ort, o, feld) {
46
+ const w = o[feld];
47
+ if (typeof w !== 'string' || w === '')
48
+ throw fehler(ort, `${ort.pfad}.${feld} fehlt`);
49
+ return w;
50
+ }
51
+ function ganzzahl(ort, o, feld) {
52
+ const w = o[feld];
53
+ if (typeof w !== 'number' || !Number.isSafeInteger(w))
54
+ throw fehler(ort, `${ort.pfad}.${feld} ist keine ganze Zahl`);
55
+ return w;
56
+ }
57
+ function ganzzahlOderNull(ort, o, feld) {
58
+ const w = o[feld];
59
+ return w === undefined || w === null ? null : ganzzahl(ort, o, feld);
60
+ }
61
+ function wahr(ort, o, feld) {
62
+ const w = o[feld];
63
+ if (typeof w !== 'boolean')
64
+ throw fehler(ort, `${ort.pfad}.${feld} ist kein Wahrheitswert`);
65
+ return w;
66
+ }
67
+ function wahrOderNull(ort, o, feld) {
68
+ const w = o[feld];
69
+ return w === undefined || w === null ? null : wahr(ort, o, feld);
70
+ }
71
+ function liste(ort, o, feld, lese) {
72
+ const w = o[feld];
73
+ if (!Array.isArray(w))
74
+ throw fehler(ort, `${ort.pfad}.${feld} ist keine Liste`);
75
+ return w.map((e, i) => lese(unter(ort, `${feld}[${i}]`), e));
76
+ }
77
+ /** Setzt ein Feld nur, wenn der Server es sendet (Recht). */
78
+ function wennDa(ziel, o, feld, lese) {
79
+ if (hat(o, feld))
80
+ ziel[feld] = lese();
81
+ }
82
+ /** Setzt ein Feld nur, wenn der Server einen Wert sendet; `null` gilt wie fehlend. */
83
+ function wennWert(ziel, o, feld, lese) {
84
+ if (o[feld] !== undefined && o[feld] !== null)
85
+ ziel[feld] = lese();
86
+ }
87
+ function stueckelung(ort, o, feld) {
88
+ const w = o[feld];
89
+ if (w === undefined || w === null)
90
+ return null;
91
+ const karte = objekt(w);
92
+ if (!karte)
93
+ throw fehler(ort, `${ort.pfad}.${feld} ist keine Stueckelung`);
94
+ const raus = {};
95
+ for (const k of Object.keys(karte))
96
+ raus[k] = ganzzahl(unter(ort, feld), karte, k);
97
+ return raus;
98
+ }
99
+ function akteur(ort, w) {
100
+ if (w === undefined || w === null)
101
+ return null;
102
+ const o = pflichtObjekt(ort, w);
103
+ return { registerUserId: text(o.registerUserId), name: text(o.name), role: text(o.role) ?? '' };
104
+ }
105
+ function unbar(ort, w) {
106
+ const o = pflichtObjekt(ort, w);
107
+ return { method: kennung(ort, o, 'method'), cents: ganzzahl(ort, o, 'cents') };
108
+ }
109
+ function trinkgeld(ort, w) {
110
+ const o = pflichtObjekt(ort, w);
111
+ return {
112
+ registerUserId: kennung(ort, o, 'registerUserId'),
113
+ name: text(o.name),
114
+ receivedImmediatelyCents: ganzzahl(ort, o, 'receivedImmediatelyCents'),
115
+ retainedCents: ganzzahl(ort, o, 'retainedCents'),
116
+ paidOutCents: ganzzahl(ort, o, 'paidOutCents'),
117
+ // Fehlt bei einem Backend vor der Regel R62: dann 0, statt die ganze Antwort zu verwerfen.
118
+ refundedByEmployeeCents: o.refundedByEmployeeCents === undefined || o.refundedByEmployeeCents === null ? 0 : ganzzahl(ort, o, 'refundedByEmployeeCents'),
119
+ };
120
+ }
121
+ /** Trinkgeld mit offenem Anspruch (Kassenstand, Bon). */
122
+ function trinkgeldMitOffen(ort, w) {
123
+ const o = pflichtObjekt(ort, w);
124
+ return {
125
+ ...trinkgeld(ort, o),
126
+ // Fehlt bei einem Backend vor der Regel R64: dann 0.
127
+ carriedOverCents: o.carriedOverCents === undefined || o.carriedOverCents === null ? 0 : ganzzahl(ort, o, 'carriedOverCents'),
128
+ openCents: ganzzahl(ort, o, 'openCents'),
129
+ };
130
+ }
131
+ function laufstand(ort, w) {
132
+ const o = pflichtObjekt(ort, w);
133
+ return {
134
+ cashSalesCents: ganzzahl(ort, o, 'cashSalesCents'),
135
+ cashCancellationsCents: ganzzahl(ort, o, 'cashCancellationsCents'),
136
+ nonCashByMethod: liste(ort, o, 'nonCashByMethod', unbar),
137
+ // Fehlt bei einem Server vor dem Gutschein-Feld: dann 0.
138
+ voucherRedeemedCents: o.voucherRedeemedCents === undefined || o.voucherRedeemedCents === null ? 0 : ganzzahl(ort, o, 'voucherRedeemedCents'),
139
+ receiptCount: ganzzahl(ort, o, 'receiptCount'),
140
+ cancellationCount: ganzzahl(ort, o, 'cancellationCount'),
141
+ cashInCents: ganzzahl(ort, o, 'cashInCents'),
142
+ cashOutCents: ganzzahl(ort, o, 'cashOutCents'),
143
+ tips: liste(ort, o, 'tips', trinkgeld),
144
+ openingsWithoutSale: ganzzahl(ort, o, 'openingsWithoutSale'),
145
+ };
146
+ }
147
+ /** Entnehmen oder Einlegen nach dem Zaehlen; die Art bleibt offen fuer kuenftige Werte (Text). */
148
+ function nachZaehlung(ort, w) {
149
+ const o = pflichtObjekt(ort, w);
150
+ return { type: kennung(ort, o, 'type'), amountCents: ganzzahl(ort, o, 'amountCents') };
151
+ }
152
+ function abgleich(ort, w) {
153
+ if (w === undefined || w === null)
154
+ return null;
155
+ const o = pflichtObjekt(ort, w);
156
+ const abw = o.deviations;
157
+ let deviations = null;
158
+ if (abw !== undefined && abw !== null) {
159
+ const karte = pflichtObjekt(unter(ort, 'deviations'), abw);
160
+ deviations = {};
161
+ for (const [feld, eintrag] of Object.entries(karte)) {
162
+ const e = pflichtObjekt(unter(ort, `deviations.${feld}`), eintrag);
163
+ deviations[feld] = { stored: e.stored, recomputed: e.recomputed };
164
+ }
165
+ }
166
+ return { matches: wahr(ort, o, 'matches'), deviations };
167
+ }
168
+ /** Eine Schicht; was nur mit `cashView` kommt, steht nur, wenn gesendet. */
169
+ function schicht(ort, w) {
170
+ const o = pflichtObjekt(ort, w);
171
+ const status = o.status;
172
+ if (status !== 'open' && status !== 'closed')
173
+ throw fehler(ort, `${ort.pfad}.status ist unbekannt`);
174
+ const raus = {
175
+ id: kennung(ort, o, 'id'),
176
+ drawerId: kennung(ort, o, 'drawerId'),
177
+ cashregisterId: text(o.cashregisterId),
178
+ number: ganzzahl(ort, o, 'number'),
179
+ status,
180
+ openedAt: text(o.openedAt),
181
+ openedBy: akteur(unter(ort, 'openedBy'), o.openedBy),
182
+ };
183
+ const r = raus;
184
+ // Ohne Recht `shift` fehlen sie (Grunddaten der offenen Schicht).
185
+ wennDa(r, o, 'openedDeviceId', () => text(o.openedDeviceId));
186
+ wennDa(r, o, 'closedAt', () => text(o.closedAt));
187
+ wennDa(r, o, 'closedBy', () => akteur(unter(ort, 'closedBy'), o.closedBy));
188
+ wennDa(r, o, 'closedDeviceId', () => text(o.closedDeviceId));
189
+ wennDa(r, o, 'openingFloatCents', () => ganzzahlOderNull(ort, o, 'openingFloatCents'));
190
+ wennDa(r, o, 'openingDenominations', () => stueckelung(ort, o, 'openingDenominations'));
191
+ wennDa(r, o, 'openingFloatTakenOver', () => wahr(ort, o, 'openingFloatTakenOver'));
192
+ wennDa(r, o, 'comment', () => text(o.comment));
193
+ wennDa(r, o, 'blind', () => wahrOderNull(ort, o, 'blind'));
194
+ wennDa(r, o, 'countedCents', () => ganzzahlOderNull(ort, o, 'countedCents'));
195
+ wennDa(r, o, 'suggestedFloatCents', () => ganzzahlOderNull(ort, o, 'suggestedFloatCents'));
196
+ wennDa(r, o, 'runningTotals', () => laufstand(unter(ort, 'runningTotals'), o.runningTotals));
197
+ wennDa(r, o, 'expectedCents', () => ganzzahlOderNull(ort, o, 'expectedCents'));
198
+ wennDa(r, o, 'differenceCents', () => ganzzahlOderNull(ort, o, 'differenceCents'));
199
+ wennDa(r, o, 'reconciliation', () => abgleich(unter(ort, 'reconciliation'), o.reconciliation));
200
+ // Nur wenn beim Abschluss Geld entnommen oder eingelegt wurde.
201
+ wennWert(r, o, 'afterCount', () => nachZaehlung(unter(ort, 'afterCount'), o.afterCount));
202
+ wennWert(r, o, 'leftInDrawerCents', () => ganzzahl(ort, o, 'leftInDrawerCents'));
203
+ return raus;
204
+ }
205
+ function schichtOderNull(ort, w) {
206
+ return w === null ? null : schicht(ort, w);
207
+ }
208
+ function anspruch(ort, w) {
209
+ const o = pflichtObjekt(ort, w);
210
+ return { registerUserId: kennung(ort, o, 'registerUserId'), name: text(o.name), cents: ganzzahl(ort, o, 'cents') };
211
+ }
212
+ function oeffnung(ort, w) {
213
+ const o = pflichtObjekt(ort, w);
214
+ const von = objekt(o.by);
215
+ return {
216
+ at: text(o.at),
217
+ deviceTime: text(o.deviceTime),
218
+ reason: kennung(ort, o, 'reason'),
219
+ by: von ? { name: text(von.name) } : null,
220
+ ok: wahr(ort, o, 'ok'),
221
+ };
222
+ }
223
+ function ladeStand(ort, w) {
224
+ const o = pflichtObjekt(ort, w);
225
+ const lade = pflichtObjekt(unter(ort, 'drawer'), o.drawer);
226
+ const ladeOrt = unter(ort, 'drawer');
227
+ const rechte = pflichtObjekt(unter(ort, 'rights'), o.rights);
228
+ const rechteOrt = unter(ort, 'rights');
229
+ const raus = {
230
+ drawer: {
231
+ id: kennung(ladeOrt, lade, 'id'),
232
+ name: text(lade.name),
233
+ shiftMode: wahr(ladeOrt, lade, 'shiftMode'),
234
+ cashregisterId: text(lade.cashregisterId),
235
+ },
236
+ rights: {
237
+ shift: wahr(rechteOrt, rechte, 'shift'),
238
+ cashMove: wahr(rechteOrt, rechte, 'cashMove'),
239
+ cashView: wahr(rechteOrt, rechte, 'cashView'),
240
+ drawer: wahr(rechteOrt, rechte, 'drawer'),
241
+ },
242
+ tipClaims: liste(ort, o, 'tipClaims', anspruch),
243
+ tips: liste(ort, o, 'tips', trinkgeldMitOffen),
244
+ };
245
+ const r = raus;
246
+ wennDa(r, o, 'shift', () => schichtOderNull(unter(ort, 'shift'), o.shift));
247
+ wennDa(r, o, 'longOpenWarning', () => wahr(ort, o, 'longOpenWarning'));
248
+ wennDa(r, o, 'suggestedFloatCents', () => ganzzahlOderNull(ort, o, 'suggestedFloatCents'));
249
+ wennDa(r, o, 'expectedCents', () => ganzzahlOderNull(ort, o, 'expectedCents'));
250
+ wennDa(r, o, 'recentOpenings', () => liste(ort, o, 'recentOpenings', oeffnung));
251
+ wennWert(r, o, 'suggestedFromShiftNumber', () => ganzzahl(ort, o, 'suggestedFromShiftNumber'));
252
+ // Wechselgeld der Lade: nur wenn eingestellt.
253
+ wennWert(raus.drawer, lade, 'changeFloatCents', () => ganzzahl(ladeOrt, lade, 'changeFloatCents'));
254
+ return raus;
255
+ }
256
+ function bewegung(ort, w) {
257
+ const o = pflichtObjekt(ort, w);
258
+ const empfaenger = objekt(o.recipient);
259
+ const paar = objekt(o.counterpart);
260
+ return {
261
+ id: kennung(ort, o, 'id'),
262
+ number: ganzzahl(ort, o, 'number'),
263
+ shiftId: text(o.shiftId),
264
+ type: kennung(ort, o, 'type'),
265
+ amountCents: ganzzahl(ort, o, 'amountCents'),
266
+ location: text(o.location),
267
+ note: text(o.note),
268
+ by: akteur(unter(ort, 'by'), o.by),
269
+ at: text(o.at),
270
+ recipient: empfaenger ? { registerUserId: text(empfaenger.registerUserId), name: text(empfaenger.name) } : null,
271
+ counterpart: paar ? { drawerId: text(paar.drawerId), movementId: text(paar.movementId) } : null,
272
+ };
273
+ }
274
+ function bonKopf(ort, o) {
275
+ const art = o.kind;
276
+ if (typeof art !== 'string' || !schicht_typen_js_1.SHIFT_RECEIPT_KINDS.includes(art))
277
+ throw fehler(ort, `${ort.pfad}.kind ist unbekannt`);
278
+ const betrieb = objekt(o.business) ?? {};
279
+ const kasse = objekt(o.cashregister) ?? {};
280
+ const lade = objekt(o.drawer) ?? {};
281
+ return {
282
+ kind: art,
283
+ blind: wahr(ort, o, 'blind'),
284
+ business: { name: text(betrieb.name) },
285
+ cashregister: { id: text(kasse.id), name: text(kasse.name) },
286
+ drawer: { name: text(lade.name) },
287
+ };
288
+ }
289
+ /** Bon-Daten eines Z- oder X-Bons; eine andere Art ist ein Fehler. */
290
+ function schichtBon(ort, w) {
291
+ const o = pflichtObjekt(ort, w);
292
+ const kopf = bonKopf(ort, o);
293
+ if (kopf.kind === 'cash_movement')
294
+ throw fehler(ort, `${ort.pfad}.kind ist cash_movement, erwartet Z- oder X-Bon`);
295
+ const s = pflichtObjekt(unter(ort, 'shift'), o.shift);
296
+ const sOrt = unter(ort, 'shift');
297
+ const raus = {
298
+ ...kopf,
299
+ kind: kopf.kind,
300
+ shift: {
301
+ number: ganzzahl(sOrt, s, 'number'),
302
+ openedAt: text(s.openedAt),
303
+ closedAt: text(s.closedAt),
304
+ openedByName: text(s.openedByName),
305
+ closedByName: text(s.closedByName),
306
+ },
307
+ openingFloatCents: ganzzahlOderNull(ort, o, 'openingFloatCents'),
308
+ openingFloatTakenOver: wahr(ort, o, 'openingFloatTakenOver'),
309
+ openingDenominations: stueckelung(ort, o, 'openingDenominations'),
310
+ cashSalesCents: ganzzahlOderNull(ort, o, 'cashSalesCents'),
311
+ cashCancellationsCents: ganzzahlOderNull(ort, o, 'cashCancellationsCents'),
312
+ receiptCount: ganzzahl(ort, o, 'receiptCount'),
313
+ cancellationCount: ganzzahl(ort, o, 'cancellationCount'),
314
+ nonCashByMethod: liste(ort, o, 'nonCashByMethod', unbar),
315
+ movements: liste(ort, o, 'movements', (mOrt, mw) => {
316
+ const m = pflichtObjekt(mOrt, mw);
317
+ return {
318
+ number: ganzzahl(mOrt, m, 'number'),
319
+ type: kennung(mOrt, m, 'type'),
320
+ amountCents: ganzzahl(mOrt, m, 'amountCents'),
321
+ note: text(m.note),
322
+ byName: text(m.byName),
323
+ at: text(m.at),
324
+ };
325
+ }),
326
+ tips: liste(ort, o, 'tips', trinkgeldMitOffen),
327
+ expectedCents: ganzzahlOderNull(ort, o, 'expectedCents'),
328
+ countedCents: ganzzahlOderNull(ort, o, 'countedCents'),
329
+ countedDenominations: stueckelung(ort, o, 'countedDenominations'),
330
+ differenceCents: ganzzahlOderNull(ort, o, 'differenceCents'),
331
+ comment: text(o.comment),
332
+ openingsWithoutSale: ganzzahl(ort, o, 'openingsWithoutSale'),
333
+ };
334
+ // Nur wenn beim Abschluss Geld entnommen oder eingelegt wurde; „Bleibt“ blind `null`.
335
+ const r = raus;
336
+ wennWert(r, o, 'afterCount', () => nachZaehlung(unter(ort, 'afterCount'), o.afterCount));
337
+ wennDa(r, o, 'leftInDrawerCents', () => ganzzahlOderNull(ort, o, 'leftInDrawerCents'));
338
+ return raus;
339
+ }
340
+ /** Bon-Daten einer Kassenbewegung; eine andere Art ist ein Fehler. */
341
+ function bewegungsBon(ort, w) {
342
+ const o = pflichtObjekt(ort, w);
343
+ const kopf = bonKopf(ort, o);
344
+ if (kopf.kind !== 'cash_movement')
345
+ throw fehler(ort, `${ort.pfad}.kind ist ${kopf.kind}, erwartet cash_movement`);
346
+ const s = objekt(o.shift);
347
+ const m = pflichtObjekt(unter(ort, 'movement'), o.movement);
348
+ const mOrt = unter(ort, 'movement');
349
+ return {
350
+ ...kopf,
351
+ kind: 'cash_movement',
352
+ shift: s ? { number: ganzzahl(unter(ort, 'shift'), s, 'number') } : null,
353
+ movement: {
354
+ number: ganzzahl(mOrt, m, 'number'),
355
+ type: kennung(mOrt, m, 'type'),
356
+ amountCents: ganzzahl(mOrt, m, 'amountCents'),
357
+ note: text(m.note),
358
+ location: text(m.location),
359
+ recipientName: text(m.recipientName),
360
+ targetDrawerName: text(m.targetDrawerName),
361
+ byName: text(m.byName),
362
+ at: text(m.at),
363
+ },
364
+ };
365
+ }
366
+ function abschluss(ort, w) {
367
+ const o = pflichtObjekt(ort, w);
368
+ if (o.status === 'recount')
369
+ return { status: 'recount' };
370
+ if (o.status === 'ready')
371
+ return { status: 'ready' };
372
+ if (o.status !== 'closed')
373
+ throw fehler(ort, `${ort.pfad || 'data'}.status ist unbekannt`);
374
+ const raus = {
375
+ status: 'closed',
376
+ shift: schicht(unter(ort, 'shift'), o.shift),
377
+ receipt: schichtBon(unter(ort, 'receipt'), o.receipt),
378
+ lastShiftOfRegister: wahr(ort, o, 'lastShiftOfRegister'),
379
+ };
380
+ // Bon „Kassenbewegung“ der Entnahme bzw. Einlage, nur wenn Geld bewegt wurde.
381
+ wennWert(raus, o, 'afterCountReceipt', () => bewegungsBon(unter(ort, 'afterCountReceipt'), o.afterCountReceipt));
382
+ return raus;
383
+ }
384
+ function geoeffnet(ort, w) {
385
+ const o = pflichtObjekt(ort, w);
386
+ const raus = { shift: schicht(unter(ort, 'shift'), o.shift) };
387
+ wennDa(raus, o, 'handoverDifferenceCents', () => ganzzahlOderNull(ort, o, 'handoverDifferenceCents'));
388
+ return raus;
389
+ }
390
+ function gebucht(ort, w) {
391
+ const o = pflichtObjekt(ort, w);
392
+ return { movement: bewegung(unter(ort, 'movement'), o.movement), receipt: bewegungsBon(unter(ort, 'receipt'), o.receipt) };
393
+ }
394
+ function gemeldet(ort, w) {
395
+ const o = pflichtObjekt(ort, w);
396
+ return { accepted: ganzzahl(ort, o, 'accepted'), duplicates: ganzzahl(ort, o, 'duplicates'), drawerId: text(o.drawerId) };
397
+ }
398
+ function bericht(ort, w) {
399
+ const o = pflichtObjekt(ort, w);
400
+ return {
401
+ shift: schicht(unter(ort, 'shift'), o.shift),
402
+ movements: liste(ort, o, 'movements', bewegung),
403
+ receipt: schichtBon(unter(ort, 'receipt'), o.receipt),
404
+ };
405
+ }