@kreiseck/kasseneck-api 1.11.0 → 1.12.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 +21 -0
- package/README.md +2 -1
- package/dist/cjs/client/aufrufe.d.ts +4 -4
- package/dist/cjs/client/aufrufe.js +15 -0
- package/dist/cjs/client/receipts.d.ts +5 -0
- package/dist/cjs/client/receipts.js +65 -6
- package/dist/cjs/enums/voucher-action.d.ts +2 -0
- package/dist/cjs/enums/voucher-action.js +2 -0
- package/dist/cjs/enums/voucher-type.d.ts +10 -0
- package/dist/cjs/enums/voucher-type.js +10 -0
- package/dist/cjs/index.d.ts +3 -3
- package/dist/cjs/index.js +9 -3
- package/dist/cjs/models/index.d.ts +3 -3
- package/dist/cjs/models/index.js +7 -2
- 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 +11 -3
- package/dist/cjs/models/receipt-item.js +22 -1
- package/dist/cjs/models/receipt.d.ts +31 -1
- package/dist/cjs/models/receipt.js +45 -5
- package/dist/cjs/models/voucher.d.ts +57 -4
- package/dist/cjs/models/voucher.js +111 -3
- package/dist/cjs/partner/fehler.d.ts +1 -1
- package/dist/cjs/partner/fehler.js +2 -0
- package/dist/cjs/partner/index.d.ts +1 -1
- package/dist/cjs/partner/typen.d.ts +7 -1
- package/dist/cjs/partner/typen.js +3 -0
- package/dist/cjs/pos/client.d.ts +2 -1
- package/dist/cjs/pos/client.js +3 -1
- package/dist/cjs/pos/gutschein.d.ts +90 -0
- package/dist/cjs/pos/gutschein.js +164 -0
- package/dist/cjs/pos/index.d.ts +3 -2
- package/dist/cjs/pos/index.js +13 -2
- package/dist/cjs/pos/settings.d.ts +3 -0
- package/dist/cjs/pos/settings.js +12 -10
- package/dist/cjs/pos/texte.d.ts +156 -0
- package/dist/cjs/pos/texte.js +72 -1
- package/dist/cjs/react/index.js +8 -2
- package/dist/cjs/receipt/due.d.ts +83 -2
- package/dist/cjs/receipt/due.js +202 -36
- package/dist/cjs/receipt/grid.js +13 -1
- package/dist/cjs/receipt/gutschein-plan.d.ts +104 -0
- package/dist/cjs/receipt/gutschein-plan.js +360 -0
- package/dist/cjs/receipt/index.d.ts +1 -1
- package/dist/cjs/receipt/index.js +3 -0
- package/dist/cjs/receipt/layout.js +186 -10
- package/dist/cjs/register/pairing.d.ts +21 -1
- package/dist/cjs/register/pairing.js +17 -0
- package/dist/cjs/stored/bon-layout.d.ts +8 -0
- package/dist/cjs/stored/bon-layout.js +23 -0
- package/dist/cjs/stored/draht.d.ts +3 -1
- package/dist/cjs/stored/draht.js +53 -6
- package/dist/cjs/stored/einstellungen.js +2 -1
- package/dist/cjs/stored/gutscheine.d.ts +3 -0
- package/dist/cjs/stored/gutscheine.js +60 -0
- package/dist/cjs/stored/index.js +2 -17
- package/dist/cjs/stored/vokabular.d.ts +6 -4
- package/dist/cjs/stored/vokabular.js +48 -2
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/client/aufrufe.d.ts +4 -4
- package/dist/esm/client/aufrufe.js +15 -0
- package/dist/esm/client/receipts.d.ts +5 -0
- package/dist/esm/client/receipts.js +66 -8
- package/dist/esm/enums/voucher-action.d.ts +2 -0
- package/dist/esm/enums/voucher-action.js +2 -0
- package/dist/esm/enums/voucher-type.d.ts +10 -0
- package/dist/esm/enums/voucher-type.js +10 -0
- package/dist/esm/index.d.ts +3 -3
- package/dist/esm/index.js +3 -3
- package/dist/esm/models/index.d.ts +3 -3
- package/dist/esm/models/index.js +3 -3
- 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 +11 -3
- package/dist/esm/models/receipt-item.js +20 -1
- package/dist/esm/models/receipt.d.ts +31 -1
- package/dist/esm/models/receipt.js +44 -5
- package/dist/esm/models/voucher.d.ts +57 -4
- package/dist/esm/models/voucher.js +108 -3
- package/dist/esm/partner/fehler.d.ts +1 -1
- package/dist/esm/partner/fehler.js +2 -0
- package/dist/esm/partner/index.d.ts +1 -1
- package/dist/esm/partner/typen.d.ts +7 -1
- package/dist/esm/partner/typen.js +3 -0
- package/dist/esm/pos/client.d.ts +2 -1
- package/dist/esm/pos/client.js +3 -1
- package/dist/esm/pos/gutschein.d.ts +90 -0
- package/dist/esm/pos/gutschein.js +158 -0
- package/dist/esm/pos/index.d.ts +3 -2
- package/dist/esm/pos/index.js +4 -2
- package/dist/esm/pos/settings.d.ts +3 -0
- package/dist/esm/pos/settings.js +2 -0
- package/dist/esm/pos/texte.d.ts +156 -0
- package/dist/esm/pos/texte.js +70 -0
- package/dist/esm/react/index.js +8 -2
- package/dist/esm/receipt/due.d.ts +83 -2
- package/dist/esm/receipt/due.js +198 -34
- package/dist/esm/receipt/grid.js +13 -1
- package/dist/esm/receipt/gutschein-plan.d.ts +104 -0
- package/dist/esm/receipt/gutschein-plan.js +352 -0
- package/dist/esm/receipt/index.d.ts +1 -1
- package/dist/esm/receipt/index.js +1 -1
- package/dist/esm/receipt/layout.js +187 -11
- package/dist/esm/register/pairing.d.ts +21 -1
- package/dist/esm/register/pairing.js +16 -0
- package/dist/esm/stored/bon-layout.d.ts +8 -0
- package/dist/esm/stored/bon-layout.js +20 -0
- package/dist/esm/stored/draht.d.ts +3 -1
- package/dist/esm/stored/draht.js +52 -6
- package/dist/esm/stored/einstellungen.js +3 -2
- package/dist/esm/stored/gutscheine.d.ts +3 -0
- package/dist/esm/stored/gutscheine.js +56 -0
- package/dist/esm/stored/index.js +2 -17
- package/dist/esm/stored/vokabular.d.ts +6 -4
- package/dist/esm/stored/vokabular.js +48 -2
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/fixtures/expected/voucher-cancellation.grid32.txt +30 -0
- package/fixtures/expected/voucher-cancellation.grid48.txt +29 -0
- package/fixtures/expected/voucher-cancellation.lines.json +252 -0
- package/fixtures/expected/voucher-cancellation.sheet32.json +206 -0
- package/fixtures/expected/voucher-cancellation.sheet48.json +200 -0
- package/fixtures/expected/voucher-multi-purpose-redeem.grid32.txt +25 -0
- package/fixtures/expected/voucher-multi-purpose-redeem.grid48.txt +25 -0
- package/fixtures/expected/voucher-multi-purpose-redeem.lines.json +259 -0
- package/fixtures/expected/voucher-multi-purpose-redeem.sheet32.json +176 -0
- package/fixtures/expected/voucher-multi-purpose-redeem.sheet48.json +176 -0
- package/fixtures/expected/voucher-multi-purpose-sale.grid32.txt +24 -0
- package/fixtures/expected/voucher-multi-purpose-sale.grid48.txt +23 -0
- package/fixtures/expected/voucher-multi-purpose-sale.lines.json +216 -0
- package/fixtures/expected/voucher-multi-purpose-sale.sheet32.json +170 -0
- package/fixtures/expected/voucher-multi-purpose-sale.sheet48.json +164 -0
- package/fixtures/expected/voucher-payout.grid32.txt +23 -0
- package/fixtures/expected/voucher-payout.grid48.txt +22 -0
- package/fixtures/expected/voucher-payout.lines.json +216 -0
- package/fixtures/expected/voucher-payout.sheet32.json +164 -0
- package/fixtures/expected/voucher-payout.sheet48.json +158 -0
- package/fixtures/expected/voucher-service-redeem.grid32.txt +26 -0
- package/fixtures/expected/voucher-service-redeem.grid48.txt +25 -0
- package/fixtures/expected/voucher-service-redeem.lines.json +261 -0
- package/fixtures/expected/voucher-service-redeem.sheet32.json +182 -0
- package/fixtures/expected/voucher-service-redeem.sheet48.json +176 -0
- package/fixtures/expected/voucher-single-purpose-redeem-exempt.grid32.txt +30 -0
- package/fixtures/expected/voucher-single-purpose-redeem-exempt.grid48.txt +29 -0
- package/fixtures/expected/voucher-single-purpose-redeem-exempt.lines.json +331 -0
- package/fixtures/expected/voucher-single-purpose-redeem-exempt.sheet32.json +206 -0
- package/fixtures/expected/voucher-single-purpose-redeem-exempt.sheet48.json +200 -0
- package/fixtures/expected/voucher-single-purpose-redeem.grid32.txt +25 -0
- package/fixtures/expected/voucher-single-purpose-redeem.grid48.txt +24 -0
- package/fixtures/expected/voucher-single-purpose-redeem.lines.json +246 -0
- package/fixtures/expected/voucher-single-purpose-redeem.sheet32.json +176 -0
- package/fixtures/expected/voucher-single-purpose-redeem.sheet48.json +170 -0
- package/fixtures/expected/voucher-single-purpose-sale.grid32.txt +26 -0
- package/fixtures/expected/voucher-single-purpose-sale.grid48.txt +24 -0
- package/fixtures/expected/voucher-single-purpose-sale.lines.json +225 -0
- package/fixtures/expected/voucher-single-purpose-sale.sheet32.json +182 -0
- package/fixtures/expected/voucher-single-purpose-sale.sheet48.json +170 -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/manifest.json +64 -0
- package/fixtures/pos-texts.json +170 -1
- package/fixtures/receipt-due-generated.json +1 -1
- package/fixtures/receipt-due-voucher-generated.json +494 -0
- package/fixtures/receipts/voucher-cancellation.json +76 -0
- package/fixtures/receipts/voucher-multi-purpose-redeem.json +62 -0
- package/fixtures/receipts/voucher-multi-purpose-sale.json +63 -0
- package/fixtures/receipts/voucher-payout.json +65 -0
- package/fixtures/receipts/voucher-service-redeem.json +82 -0
- package/fixtures/receipts/voucher-single-purpose-redeem-exempt.json +86 -0
- package/fixtures/receipts/voucher-single-purpose-redeem.json +71 -0
- package/fixtures/receipts/voucher-single-purpose-sale.json +88 -0
- package/fixtures/surface.json +35 -5
- package/fixtures/v3/antworten/belege.json +3405 -3
- package/fixtures/v3/antworten/belegmail.json +5 -2
- package/fixtures/v3/antworten/kasse-belege.json +3423 -3
- package/fixtures/v3/antworten/kasse.json +621 -14
- package/fixtures/v3/antworten/lager.json +1 -1
- package/fixtures/v3/antworten/rechnungen.json +5 -2
- package/fixtures/v3/antworten/storno.json +214 -3
- package/fixtures/v3/stored/belege.json +5 -2
- package/fixtures/v3/stored/kasse.json +225 -4
- package/fixtures/v3/stored/rechnungen.json +5 -2
- package/fixtures/v3/v3-vokabular.json +1375 -23
- package/fixtures/v3/zahlbetrag-faelle.json +293 -3
- package/package.json +4 -1
|
@@ -199,6 +199,12 @@ export interface RegisterUserPerms {
|
|
|
199
199
|
stocktakeClose?: boolean;
|
|
200
200
|
/** Standort der Kasse waehlen (setMyCashregisterStockLocation). */
|
|
201
201
|
stockLocation?: boolean;
|
|
202
|
+
/** Gutschein verkaufen (fehlt bei altem Server: gilt wie beim Kassier, siehe [voucherPermsOf]). */
|
|
203
|
+
voucherSell?: boolean;
|
|
204
|
+
/** Gutschein einloesen (fehlt bei altem Server: gilt wie beim Kassier). */
|
|
205
|
+
voucherRedeem?: boolean;
|
|
206
|
+
/** Gutscheine verwalten, z. B. Etikett nachdrucken (fehlt: verweigert). */
|
|
207
|
+
voucherManage?: boolean;
|
|
202
208
|
[weiteresRecht: string]: boolean | RegisterScope | undefined;
|
|
203
209
|
}
|
|
204
210
|
/**
|
|
@@ -209,7 +215,7 @@ export interface RegisterUserPerms {
|
|
|
209
215
|
* nicht fuehrt (Tippfehler, umbenanntes Recht), kommt hier nicht durch.
|
|
210
216
|
* Die Gegenrichtung schliesst [_RechteVollstaendig] direkt darunter.
|
|
211
217
|
*/
|
|
212
|
-
export declare const REGISTER_PERMS: readonly ["sell", "cancel", "articles", "layout", "reports", "takeover", "cancelScope", "receiptsScope", "drawer", "discount", "tipAssign", "stockView", "stockCosts", "stockMove", "stockLoss", "stocktakeCount", "stocktakeClose", "stockLocation"];
|
|
218
|
+
export declare const REGISTER_PERMS: readonly ["sell", "cancel", "articles", "layout", "reports", "takeover", "cancelScope", "receiptsScope", "drawer", "discount", "tipAssign", "stockView", "stockCosts", "stockMove", "stockLoss", "stocktakeCount", "stocktakeClose", "stockLocation", "voucherSell", "voucherRedeem", "voucherManage"];
|
|
213
219
|
/** Reichweite lesen, mit der Migration des Backends (register-auth.js). */
|
|
214
220
|
export declare function cancelScopeOf(perms: RegisterUserPerms | null | undefined): RegisterScope;
|
|
215
221
|
export declare function receiptsScopeOf(perms: RegisterUserPerms | null | undefined): RegisterScope;
|
|
@@ -219,6 +225,20 @@ export declare function receiptsScopeOf(perms: RegisterUserPerms | null | undefi
|
|
|
219
225
|
* sperrt; alle anderen Lager-Rechte gelten ohne Schluessel als verweigert.
|
|
220
226
|
*/
|
|
221
227
|
export declare function stockViewOf(perms: RegisterUserPerms | null | undefined): boolean;
|
|
228
|
+
/** Die drei Gutschein-Rechte, aufgeloest (kein Schluessel fehlt mehr). */
|
|
229
|
+
export interface VoucherPerms {
|
|
230
|
+
voucherSell: boolean;
|
|
231
|
+
voucherRedeem: boolean;
|
|
232
|
+
voucherManage: boolean;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Gutschein-Rechte lesen. Das Backend loest sie bei der Anmeldung auf; ein
|
|
236
|
+
* alter Server (und `/api`-Antworten) kennt sie nicht. Dann gilt je fehlendem
|
|
237
|
+
* Schluessel die Vorgabe des Kassiers: verkaufen und einloesen ja, verwalten
|
|
238
|
+
* nein. Ein ausdrueckliches `false` sperrt; was kein Wahrheitswert ist,
|
|
239
|
+
* erteilt nichts.
|
|
240
|
+
*/
|
|
241
|
+
export declare function voucherPermsOf(perms: Partial<RegisterUserPerms> | null | undefined): VoucherPerms;
|
|
222
242
|
/** Der angemeldete Kassen-Benutzer. */
|
|
223
243
|
export interface RegisterUser {
|
|
224
244
|
id: string;
|
|
@@ -50,6 +50,7 @@ export const REGISTER_PERMS = [
|
|
|
50
50
|
'sell', 'cancel', 'articles', 'layout', 'reports', 'takeover',
|
|
51
51
|
'cancelScope', 'receiptsScope', 'drawer', 'discount', 'tipAssign',
|
|
52
52
|
'stockView', 'stockCosts', 'stockMove', 'stockLoss', 'stocktakeCount', 'stocktakeClose', 'stockLocation',
|
|
53
|
+
'voucherSell', 'voucherRedeem', 'voucherManage',
|
|
53
54
|
];
|
|
54
55
|
/** Reichweite lesen, mit der Migration des Backends (register-auth.js). */
|
|
55
56
|
export function cancelScopeOf(perms) {
|
|
@@ -76,6 +77,21 @@ export function stockViewOf(perms) {
|
|
|
76
77
|
return false;
|
|
77
78
|
return perms.stockView === undefined ? true : perms.stockView === true;
|
|
78
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Gutschein-Rechte lesen. Das Backend loest sie bei der Anmeldung auf; ein
|
|
82
|
+
* alter Server (und `/api`-Antworten) kennt sie nicht. Dann gilt je fehlendem
|
|
83
|
+
* Schluessel die Vorgabe des Kassiers: verkaufen und einloesen ja, verwalten
|
|
84
|
+
* nein. Ein ausdrueckliches `false` sperrt; was kein Wahrheitswert ist,
|
|
85
|
+
* erteilt nichts.
|
|
86
|
+
*/
|
|
87
|
+
export function voucherPermsOf(perms) {
|
|
88
|
+
const lies = (wert, vorgabe) => (wert === undefined ? vorgabe : wert === true);
|
|
89
|
+
return {
|
|
90
|
+
voucherSell: lies(perms?.voucherSell, true),
|
|
91
|
+
voucherRedeem: lies(perms?.voucherRedeem, true),
|
|
92
|
+
voucherManage: lies(perms?.voucherManage, false),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
79
95
|
/**
|
|
80
96
|
* Geraet koppeln: der Kopplungs-Code wird gegen den dauerhaften Ausweis dieses
|
|
81
97
|
* Geraets getauscht. **Ohne Anmeldung** — der Code ist der Nachweis.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ReceiptWithCompany } from '../client/receipts.js';
|
|
2
|
+
import { type ReceiptLayout } from '../receipt/layout.js';
|
|
3
|
+
/**
|
|
4
|
+
* Layout wie `beleg-layout.layoutFuerBeleg`: 80 mm, Regelwerk mindestens das
|
|
5
|
+
* aktuelle. Kann der Server es nicht bauen, liefert er `null` (dann baut
|
|
6
|
+
* [receiptLayoutFromResult] selbst); ebenso hier.
|
|
7
|
+
*/
|
|
8
|
+
export declare function layoutWieServer(b: ReceiptWithCompany, regelwerk: unknown): ReceiptLayout | null;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { buildReceiptLayout, CURRENT_LAYOUT_RULESET } from '../receipt/layout.js';
|
|
2
|
+
import { gutscheineFuerPaket, wieVendortesPaket } from './gutscheine.js';
|
|
3
|
+
/**
|
|
4
|
+
* Layout wie `beleg-layout.layoutFuerBeleg`: 80 mm, Regelwerk mindestens das
|
|
5
|
+
* aktuelle. Kann der Server es nicht bauen, liefert er `null` (dann baut
|
|
6
|
+
* [receiptLayoutFromResult] selbst); ebenso hier.
|
|
7
|
+
*/
|
|
8
|
+
export function layoutWieServer(b, regelwerk) {
|
|
9
|
+
const ruleset = Math.max(Number(regelwerk) || 1, CURRENT_LAYOUT_RULESET);
|
|
10
|
+
try {
|
|
11
|
+
// Wie layoutFuerBeleg: Gutscheine mit Code stehen am Bon als Positionen,
|
|
12
|
+
// die uebrigen Eintraege so, wie das vendorte Paket des Servers sie liest.
|
|
13
|
+
return buildReceiptLayout(wieVendortesPaket(gutscheineFuerPaket(b.receipt)), b.company, {
|
|
14
|
+
paperSize: 'mm80', ruleset, testCashregister: b.testCashregister, testSignature: b.testSignature, registrationInfo: b.registrationInfo,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type SchemaEintrag, type SchemaObjekt } from './vokabular.js';
|
|
1
|
+
import { type SchemaEintrag, type SchemaObjekt, type Wertverweis } from './vokabular.js';
|
|
2
2
|
export type Objekt = Record<string, unknown>;
|
|
3
3
|
export declare const hat: (o: object, k: string) => boolean;
|
|
4
4
|
export declare const istObjekt: (w: unknown) => w is Objekt;
|
|
@@ -10,6 +10,8 @@ export declare function regel(eintrag: SchemaEintrag): {
|
|
|
10
10
|
};
|
|
11
11
|
/** Innere Namen einer Schema-Ebene (was der Server innen an dieser Stelle kennt). */
|
|
12
12
|
export declare function innereNamen(schema: SchemaObjekt): Map<string, string>;
|
|
13
|
+
/** Zuordnung eines Wertverweises: benannter Katalog oder eingebettet. */
|
|
14
|
+
export declare function katalogVon(verweis: Wertverweis): Readonly<Record<string, string>> | undefined;
|
|
13
15
|
/** Rueckgabe-Wahl innen -> aussen (Katalog RUECKGABE; stored.test.ts vergleicht mit dem Vertrag). */
|
|
14
16
|
export declare const _RUECKGABE_NACH_AUSSEN: Readonly<Record<string, string>>;
|
|
15
17
|
/**
|
package/dist/esm/stored/draht.js
CHANGED
|
@@ -67,16 +67,21 @@ function anPfad(obj, teile, fn) {
|
|
|
67
67
|
*/
|
|
68
68
|
function werteNachAussen(obj, werte) {
|
|
69
69
|
let raus = obj;
|
|
70
|
-
for (const [pfad,
|
|
71
|
-
const katalog =
|
|
70
|
+
for (const [pfad, verweis] of Object.entries(werte)) {
|
|
71
|
+
const katalog = katalogVon(verweis);
|
|
72
72
|
if (!katalog)
|
|
73
|
-
throw new Error(`stored: Katalog ${
|
|
73
|
+
throw new Error(`stored: Katalog ${verweis.$catalog} fehlt im Vokabular`);
|
|
74
74
|
raus = anPfad(raus, pfad.split('.'), (v) => (typeof v === 'string' && hat(katalog, v) ? katalog[v] : v));
|
|
75
75
|
}
|
|
76
76
|
return raus;
|
|
77
77
|
}
|
|
78
|
+
/** Zuordnung eines Wertverweises: benannter Katalog oder eingebettet. */
|
|
79
|
+
export function katalogVon(verweis) {
|
|
80
|
+
const name = verweis.$catalog;
|
|
81
|
+
return typeof name === 'string' ? KATALOGE[name] : verweis;
|
|
82
|
+
}
|
|
78
83
|
/** Englische Werte eines Katalogs (was an dieser Stelle hinaus darf). */
|
|
79
|
-
const aeussereWerte = (
|
|
84
|
+
const aeussereWerte = (verweis) => new Set(Object.values(katalogVon(verweis) ?? {}));
|
|
80
85
|
// ---- Belege -----------------------------------------------------------------
|
|
81
86
|
/**
|
|
82
87
|
* Interne Marke der Storno-Reservierung: `stornoMarke` am Storno-Beleg,
|
|
@@ -131,6 +136,47 @@ function belegRueckgabeNachAussen(beleg) {
|
|
|
131
136
|
}
|
|
132
137
|
return raus;
|
|
133
138
|
}
|
|
139
|
+
// ---- Gutschein-Eintraege am Beleg ---------------------------------------------
|
|
140
|
+
/** Zwilling von `BELEG_GUTSCHEIN` (api-vokabular-v3): aussen -> innen. */
|
|
141
|
+
const BELEG_GUTSCHEIN = {
|
|
142
|
+
voucherType: 'art', voucherId: 'gutscheinId', codeSuffix: 'codeEnde', amountCents: 'betragCents', vatRateBp: 'satzBp',
|
|
143
|
+
article: 'artikel', articleId: 'artikelId', quantity: 'stueck', positions: 'positionen',
|
|
144
|
+
balanceAfterCents: 'saldoNachCents', remainingQuantityAfter: 'stueckOffenNach', taxedWith: 'versteuertMit', exempt: 'befreit',
|
|
145
|
+
reason: 'grund', zeroRateBucket: 'imNullTopf',
|
|
146
|
+
};
|
|
147
|
+
const BELEG_GUTSCHEIN_AUSSEN = Object.fromEntries(Object.entries(BELEG_GUTSCHEIN).map(([aussen, innen]) => [innen, aussen]));
|
|
148
|
+
const GUTSCHEIN_ARTIKEL_AUSSEN = { satzBp: 'vatRateBp', preisCents: 'priceCents' };
|
|
149
|
+
function umbenannt(o, namen) {
|
|
150
|
+
return Object.fromEntries(Object.entries(o).map(([k, w]) => [hat(namen, k) ? namen[k] : k, w]));
|
|
151
|
+
}
|
|
152
|
+
/** Zwilling von `gutscheinEintragNachAussen`: ohne deutschen Schluessel/Wert dasselbe Objekt (Altbeleg). */
|
|
153
|
+
function gutscheinEintragNachAussen(v) {
|
|
154
|
+
if (!istObjekt(v))
|
|
155
|
+
return v;
|
|
156
|
+
const art = KATALOGE.GUTSCHEIN_ART ?? {};
|
|
157
|
+
const typNeu = typeof v.type === 'string' && hat(art, v.type);
|
|
158
|
+
if (!typNeu && !Object.keys(v).some((k) => hat(BELEG_GUTSCHEIN_AUSSEN, k)))
|
|
159
|
+
return v;
|
|
160
|
+
const raus = {};
|
|
161
|
+
for (const [k, w] of Object.entries(v)) {
|
|
162
|
+
if (k === 'type')
|
|
163
|
+
raus.type = typNeu ? art[w] : w;
|
|
164
|
+
else if (k === 'art')
|
|
165
|
+
raus.voucherType = typeof w === 'string' && hat(art, w) ? art[w] : w;
|
|
166
|
+
else if (k === 'artikel')
|
|
167
|
+
raus.article = istObjekt(w) ? umbenannt(w, GUTSCHEIN_ARTIKEL_AUSSEN) : w;
|
|
168
|
+
else
|
|
169
|
+
raus[hat(BELEG_GUTSCHEIN_AUSSEN, k) ? BELEG_GUTSCHEIN_AUSSEN[k] : k] = w;
|
|
170
|
+
}
|
|
171
|
+
return raus;
|
|
172
|
+
}
|
|
173
|
+
/** Zwilling von `belegGutscheineNachAussen`: `vouchers[]` eines Belegs an Ort und Stelle nach aussen. */
|
|
174
|
+
function belegGutscheineNachAussen(beleg) {
|
|
175
|
+
if (!Array.isArray(beleg.vouchers))
|
|
176
|
+
return beleg;
|
|
177
|
+
const neu = beleg.vouchers.map(gutscheinEintragNachAussen);
|
|
178
|
+
return neu.every((v, i) => v === beleg.vouchers[i]) ? beleg : { ...beleg, vouchers: neu };
|
|
179
|
+
}
|
|
134
180
|
/**
|
|
135
181
|
* Zwilling von `beleg-pruefangaben.alsIso`: leer (auch 0, '') -> null;
|
|
136
182
|
* Firestore-Zeitstempel, Zahl oder Zeichenkette -> ISO-Zeitpunkt in UTC;
|
|
@@ -182,7 +228,7 @@ export function pruefangabenDerHuelle(p) {
|
|
|
182
228
|
export function _receiptEnvelopeToWire(huelle) {
|
|
183
229
|
const schema = SCHEMAS.getReceipt;
|
|
184
230
|
const draht = werteNachAussen(schluesselNachAussen(huelle, schema.data), schema.werte);
|
|
185
|
-
return istObjekt(draht.receipt) ? { ...draht, receipt: belegRueckgabeNachAussen(draht.receipt) } : draht;
|
|
231
|
+
return istObjekt(draht.receipt) ? { ...draht, receipt: belegGutscheineNachAussen(belegRueckgabeNachAussen(draht.receipt)) } : draht;
|
|
186
232
|
}
|
|
187
233
|
/**
|
|
188
234
|
* Ein Belegdokument (`users/{uid}/cashregisters/{id}/receipts/{id}`) in der
|
|
@@ -238,7 +284,7 @@ export function _storedArticleToWire(id, doc, functionName = 'fromStoredArticle'
|
|
|
238
284
|
const schema = SCHEMAS.listMyArticles;
|
|
239
285
|
const huelle = werteNachAussen(schluesselNachAussen({ articles: [handler] }, schema.data), schema.werte);
|
|
240
286
|
const artikel = huelle.articles[0];
|
|
241
|
-
const katalog = (pfad) => aeussereWerte(schema.werte[pfad]
|
|
287
|
+
const katalog = (pfad) => aeussereWerte(schema.werte[pfad]);
|
|
242
288
|
const raus = nurBekannte(artikel, new Set(ARTIKEL_FELDER), {
|
|
243
289
|
quantityRule: katalog('articles[].quantityRule'), e1aGroup: katalog('articles[].e1aGroup'),
|
|
244
290
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { POS_BUSINESS_DEFAULTS, POS_BUSINESS_VALUES, POS_DEVICE_DEFAULTS, POS_DEVICE_OPTIONAL_FIELDS, POS_DEVICE_VALUES, POS_SHORTCUT_DEFAULTS, POS_SHORTCUT_SHARED_PAIRS, POS_BUSINESS_OPTIONAL_FIELDS, _optionalerWert, } from '../pos/settings.js';
|
|
2
2
|
import { hat, innereNamen, istObjekt, regel } from './draht.js';
|
|
3
|
-
import {
|
|
3
|
+
import { katalogVon } from './draht.js';
|
|
4
|
+
import { SCHEMAS } from './vokabular.js';
|
|
4
5
|
const bool = (v) => typeof v === 'boolean';
|
|
5
6
|
const hex = (v) => typeof v === 'string' && /^#[0-9a-fA-F]{6}$/.test(v);
|
|
6
7
|
const kuerzel = (v) => typeof v === 'string' && /^[A-Za-z0-9]{1,3}$/.test(v);
|
|
@@ -71,7 +72,7 @@ function teilSchema(teil) {
|
|
|
71
72
|
}
|
|
72
73
|
function katalogFuer(teil, aussen) {
|
|
73
74
|
const verweis = SCHEMAS.getKasseSettings.werte[`${teil}.${aussen}`];
|
|
74
|
-
return verweis ?
|
|
75
|
+
return verweis ? katalogVon(verweis) ?? null : null;
|
|
75
76
|
}
|
|
76
77
|
/** Tasten: aeussere und innere Aktionsnamen, Vorgabe und Paare in innerer Form. */
|
|
77
78
|
const TASTEN_SCHEMA = regel(teilSchema('device').shortcuts).unter;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Zwilling von `gutscheineFuerPaket` (functions/beleg-layout.js): der Bon
|
|
3
|
+
* kennt Gutscheine mit Code nur als Positionen. Eintraege, deren Betrag schon
|
|
4
|
+
* als Position am Beleg steht (Einzweck, Leistung, Mehrzweck im 0-%-Topf),
|
|
5
|
+
* fallen fuer das Zeilenmodell weg, sonst zaehlte es sie ein zweites Mal; die
|
|
6
|
+
* maskierte Code-Endung wandert an die passende Position. Nur Darstellung,
|
|
7
|
+
* der Beleg selbst bleibt unberuehrt.
|
|
8
|
+
*/
|
|
9
|
+
const POSITIONS_ARTEN = ['single_purpose', 'service'];
|
|
10
|
+
const centsDerPosition = (it) => Math.round(Math.abs(it.priceCents * it.quantity));
|
|
11
|
+
const centsDesEintrags = (v) => Number.isInteger(v.amountCents) ? Math.abs(v.amountCents) : Math.abs(v.valueCents ?? 0);
|
|
12
|
+
export function gutscheineFuerPaket(receipt) {
|
|
13
|
+
const positionen = receipt.items.map((it) => ({ ...it }));
|
|
14
|
+
const vergeben = new Set();
|
|
15
|
+
const codeAnPosition = (v, kinds) => {
|
|
16
|
+
const cents = centsDesEintrags(v);
|
|
17
|
+
const i = positionen.findIndex((it, k) => !vergeben.has(k) && it.kind != null && kinds.includes(it.kind)
|
|
18
|
+
&& centsDerPosition(it) === cents && !String(it.name || '').includes('····'));
|
|
19
|
+
if (i < 0)
|
|
20
|
+
return;
|
|
21
|
+
vergeben.add(i);
|
|
22
|
+
if (typeof v.code === 'string' && v.code)
|
|
23
|
+
positionen[i].name = `${positionen[i].name} ${v.code}`;
|
|
24
|
+
};
|
|
25
|
+
const bleiben = [];
|
|
26
|
+
for (const v of receipt.vouchers) {
|
|
27
|
+
if (POSITIONS_ARTEN.includes(v.type)) {
|
|
28
|
+
if (v.action === 'sell')
|
|
29
|
+
codeAnPosition(v, ['voucher']);
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (v.zeroRateBucket === true) {
|
|
33
|
+
codeAnPosition(v, ['voucher_float']);
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
bleiben.push(v);
|
|
37
|
+
}
|
|
38
|
+
return { ...receipt, items: positionen, vouchers: bleiben };
|
|
39
|
+
}
|
|
40
|
+
/*
|
|
41
|
+
* Das Backend setzt den Bon noch mit dem vendorten Paket 0.33 (functions/
|
|
42
|
+
* package.json). Es liest an einem Gutschein nur name, code, action, type und
|
|
43
|
+
* den Wert; die Kennzeichen der neuen Form (`voucherType`, `codeSuffix`,
|
|
44
|
+
* `balanceAfterCents` ...) sieht es nicht. Was nach `gutscheineFuerPaket`
|
|
45
|
+
* bleibt (Mehrzweck, Aktion), zeigt es darum wie einen Altbeleg
|
|
46
|
+
* („Wertgutschein ····-····-5KNZ - Gutschein“). Dieses Paket zeigt solche
|
|
47
|
+
* Eintraege selbst in der Form der Spec („Gutschein ····-5KNZ“ + Rest); fuer
|
|
48
|
+
* das Layout wie der Server fallen die Kennzeichen hier weg. Entfaellt, sobald
|
|
49
|
+
* der Server ein Paket mit der neuen Form vendort und nicht mehr aufbereitet.
|
|
50
|
+
*/
|
|
51
|
+
export function wieVendortesPaket(receipt) {
|
|
52
|
+
const vouchers = receipt.vouchers.map((v) => ({
|
|
53
|
+
name: v.name, code: v.code, action: v.action, type: v.type, valueCents: v.valueCents,
|
|
54
|
+
}));
|
|
55
|
+
return { ...receipt, vouchers };
|
|
56
|
+
}
|
package/dist/esm/stored/index.js
CHANGED
|
@@ -15,11 +15,12 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { belegAusHuelle, belegMitFirmaAusHuelle } from '../client/receipts.js';
|
|
17
17
|
import { fromReceiptCompanyPayload } from '../models/receipt-company.js';
|
|
18
|
-
import {
|
|
18
|
+
import { receiptSignatureIsTest } from '../receipt/layout.js';
|
|
19
19
|
import { sanitizePosSettings } from '../pos/settings.js';
|
|
20
20
|
import { fromPosArticlePayload } from '../pos/artikel.js';
|
|
21
21
|
import { KasseneckValidationError } from '../client/errors.js';
|
|
22
22
|
import { _receiptEnvelopeToWire, _storedArticleToWire, _storedReceiptInner, _storedReceiptToWire, pruefangabenDerHuelle, } from './draht.js';
|
|
23
|
+
import { layoutWieServer } from './bon-layout.js';
|
|
23
24
|
import { _storedPosSettingsToWire } from './einstellungen.js';
|
|
24
25
|
const istObjekt = (w) => w !== null && typeof w === 'object' && !Array.isArray(w);
|
|
25
26
|
// ---- Belege -----------------------------------------------------------------
|
|
@@ -93,22 +94,6 @@ function pruefangabenFuer(beleg, angabe) {
|
|
|
93
94
|
return pruefangabenDerHuelle(beleg.pruefangaben);
|
|
94
95
|
return { karteRegistriertAm: angabe?.cardRegisteredAt ?? null, kasseRegistriertAm: angabe?.cashregisterRegisteredAt ?? null };
|
|
95
96
|
}
|
|
96
|
-
/**
|
|
97
|
-
* Layout wie `beleg-layout.layoutFuerBeleg`: 80 mm, Regelwerk mindestens das
|
|
98
|
-
* aktuelle. Kann der Server es nicht bauen, liefert er `null` (dann baut
|
|
99
|
-
* [receiptLayoutFromResult] selbst); ebenso hier.
|
|
100
|
-
*/
|
|
101
|
-
function layoutWieServer(b, regelwerk) {
|
|
102
|
-
const ruleset = Math.max(Number(regelwerk) || 1, CURRENT_LAYOUT_RULESET);
|
|
103
|
-
try {
|
|
104
|
-
return buildReceiptLayout(b.receipt, b.company, {
|
|
105
|
-
paperSize: 'mm80', ruleset, testCashregister: b.testCashregister, testSignature: b.testSignature, registrationInfo: b.registrationInfo,
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
catch {
|
|
109
|
-
return null;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
97
|
// ---- Firma ------------------------------------------------------------------
|
|
113
98
|
const KOPF_FELDER = ['companyName', 'street', 'zip', 'city', 'phone', 'uid', 'taxnr', 'isSmallBusiness',
|
|
114
99
|
'footer1', 'footer2', 'footer3', 'footer4', 'thanksMessage', 'showKreiseckLogo', 'logoUrl'];
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
/** Fingerabdruck des Vertrags-Exports, aus dem diese Datei stammt (`_quelle.sha256`). */
|
|
2
|
-
export declare const VOKABULAR_QUELLE = "
|
|
2
|
+
export declare const VOKABULAR_QUELLE = "733e4385baf4b2aa50605e2ebe5903948ce77b3346aa3bb65c5fd0d450a6898f";
|
|
3
3
|
/** Schema-Notation des Vertrags: Blatt 'aussen': 'innen', Objekt { __: 'innen', ... }, Liste [ { __: 'innen', ... } ]. */
|
|
4
4
|
export type SchemaEintrag = string | SchemaObjekt | readonly [SchemaObjekt];
|
|
5
5
|
export interface SchemaObjekt {
|
|
6
6
|
readonly [aussen: string]: SchemaEintrag;
|
|
7
7
|
}
|
|
8
|
+
/** Wertverweis: Name eines Katalogs oder eine eingebettete Zuordnung innen -> aussen. */
|
|
9
|
+
export type Wertverweis = {
|
|
10
|
+
readonly $catalog: string;
|
|
11
|
+
} | Readonly<Record<string, string>>;
|
|
8
12
|
/** Schema je Endpunkt (aussen -> innen) und Wertverweise auf die Kataloge. */
|
|
9
13
|
export declare const SCHEMAS: Readonly<Record<'getReceipt' | 'getKasseSettings' | 'listMyArticles', {
|
|
10
14
|
readonly data: SchemaObjekt;
|
|
11
|
-
readonly werte: Readonly<Record<string,
|
|
12
|
-
readonly $catalog: string;
|
|
13
|
-
}>>;
|
|
15
|
+
readonly werte: Readonly<Record<string, Wertverweis>>;
|
|
14
16
|
}>>;
|
|
15
17
|
/** Die Felder eines Artikels in der Antwort (`listMyArticles`), aussen. */
|
|
16
18
|
export declare const ARTIKEL_FELDER: readonly string[];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Erzeugt von scripts/stored-vokabular.mjs aus fixtures/v3/v3-vokabular.json.
|
|
2
2
|
// Nicht von Hand aendern: test/stored.test.ts vergleicht mit dem Vertrag.
|
|
3
3
|
/** Fingerabdruck des Vertrags-Exports, aus dem diese Datei stammt (`_quelle.sha256`). */
|
|
4
|
-
export const VOKABULAR_QUELLE = "
|
|
4
|
+
export const VOKABULAR_QUELLE = "733e4385baf4b2aa50605e2ebe5903948ce77b3346aa3bb65c5fd0d450a6898f";
|
|
5
5
|
/** Schema je Endpunkt (aussen -> innen) und Wertverweise auf die Kataloge. */
|
|
6
6
|
export const SCHEMAS = {
|
|
7
7
|
"getReceipt": {
|
|
@@ -43,7 +43,22 @@ export const SCHEMAS = {
|
|
|
43
43
|
"tone": "ton"
|
|
44
44
|
}
|
|
45
45
|
]
|
|
46
|
-
}
|
|
46
|
+
},
|
|
47
|
+
"issuedVouchers": [
|
|
48
|
+
{
|
|
49
|
+
"__": "gutscheine",
|
|
50
|
+
"codeSuffix": "codeEnde",
|
|
51
|
+
"faceValueCents": "nennwertCents",
|
|
52
|
+
"quantity": "stueck",
|
|
53
|
+
"validity": {
|
|
54
|
+
"__": "gueltigkeit",
|
|
55
|
+
"pattern": "muster",
|
|
56
|
+
"redeemableUntil": "einloesbarBis",
|
|
57
|
+
"refundableUntil": "rueckzahlbarBis",
|
|
58
|
+
"validUntil": "gueltigBis"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
]
|
|
47
62
|
},
|
|
48
63
|
"werte": {
|
|
49
64
|
"receipt.cancellationReason": {
|
|
@@ -51,6 +66,12 @@ export const SCHEMAS = {
|
|
|
51
66
|
},
|
|
52
67
|
"layout.lines[].tone": {
|
|
53
68
|
"$catalog": "LAYOUT_TON"
|
|
69
|
+
},
|
|
70
|
+
"issuedVouchers[].type": {
|
|
71
|
+
"$catalog": "GUTSCHEIN_ART"
|
|
72
|
+
},
|
|
73
|
+
"issuedVouchers[].validity.pattern": {
|
|
74
|
+
"$catalog": "GUTSCHEIN_MUSTER"
|
|
54
75
|
}
|
|
55
76
|
}
|
|
56
77
|
},
|
|
@@ -157,6 +178,12 @@ export const SCHEMAS = {
|
|
|
157
178
|
"terminalVia": "terminalVia",
|
|
158
179
|
"terminalType": "terminalArt",
|
|
159
180
|
"shortcutHints": "tastenMarken"
|
|
181
|
+
},
|
|
182
|
+
"vouchers": {
|
|
183
|
+
"__": "gutscheine",
|
|
184
|
+
"sale": "verkauf",
|
|
185
|
+
"valueVoucherType": "wertArt",
|
|
186
|
+
"vatRateBp": "satzBp"
|
|
160
187
|
}
|
|
161
188
|
},
|
|
162
189
|
"werte": {
|
|
@@ -207,6 +234,10 @@ export const SCHEMAS = {
|
|
|
207
234
|
},
|
|
208
235
|
"device.terminalType": {
|
|
209
236
|
"$catalog": "KASSE_GERAET_WERTE.terminalType"
|
|
237
|
+
},
|
|
238
|
+
"vouchers.valueVoucherType": {
|
|
239
|
+
"mehrzweck": "multi_purpose",
|
|
240
|
+
"einzweck": "single_purpose"
|
|
210
241
|
}
|
|
211
242
|
}
|
|
212
243
|
},
|
|
@@ -301,6 +332,7 @@ export const KATALOGE = {
|
|
|
301
332
|
"afa_gebaeude": "building_depreciation",
|
|
302
333
|
"anlagenabgang": "asset_disposal_book_value",
|
|
303
334
|
"instandhaltung_gebaeude": "building_maintenance",
|
|
335
|
+
"bauarbeiten": "construction_work",
|
|
304
336
|
"reise": "travel_expenses",
|
|
305
337
|
"fahrkarten": "travel_tickets",
|
|
306
338
|
"naechtigung_beleg": "lodging_invoice",
|
|
@@ -335,6 +367,8 @@ export const KATALOGE = {
|
|
|
335
367
|
"geschenke_geschaeftsfreunde": "business_gifts",
|
|
336
368
|
"bewirtung": "hospitality",
|
|
337
369
|
"bewirtung_werbung": "hospitality_advertising",
|
|
370
|
+
"kundschaft_aufmerksamkeit": "customer_courtesy",
|
|
371
|
+
"lebensmittel": "groceries",
|
|
338
372
|
"bewirtung_voll": "hospitality_full",
|
|
339
373
|
"bewirtung_repraesentation": "hospitality_representation",
|
|
340
374
|
"sponsoring": "sponsorship",
|
|
@@ -365,6 +399,7 @@ export const KATALOGE = {
|
|
|
365
399
|
"arbeitslosen_optin": "voluntary_unemployment_insurance",
|
|
366
400
|
"uebrige_ausgaben": "other_expenses",
|
|
367
401
|
"telefon_internet": "phone_internet",
|
|
402
|
+
"energie": "energy_utilities",
|
|
368
403
|
"buero": "office_supplies",
|
|
369
404
|
"software": "software_subscriptions",
|
|
370
405
|
"fachliteratur": "professional_literature",
|
|
@@ -396,6 +431,17 @@ export const KATALOGE = {
|
|
|
396
431
|
"ball_kultur": "non_deductible_events",
|
|
397
432
|
"durchlaufend_ausgabe": "pass_through_payment"
|
|
398
433
|
},
|
|
434
|
+
"GUTSCHEIN_ART": {
|
|
435
|
+
"mehrzweck": "multi_purpose",
|
|
436
|
+
"einzweck": "single_purpose",
|
|
437
|
+
"leistung": "service",
|
|
438
|
+
"aktion": "promotion"
|
|
439
|
+
},
|
|
440
|
+
"GUTSCHEIN_MUSTER": {
|
|
441
|
+
"unbefristet": "unlimited",
|
|
442
|
+
"1+3": "1+3",
|
|
443
|
+
"frei": "custom"
|
|
444
|
+
},
|
|
399
445
|
"KASSE_BETRIEB_WERTE.cardProvider": {
|
|
400
446
|
"keiner": "none",
|
|
401
447
|
"extern": "external",
|
package/dist/esm/version.d.ts
CHANGED
package/dist/esm/version.js
CHANGED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
Melisse Nails e.U.
|
|
2
|
+
Melissenweg 7
|
|
3
|
+
1070 Wien
|
|
4
|
+
ATU12345675
|
|
5
|
+
+43 1 2345678
|
|
6
|
+
|
|
7
|
+
================================
|
|
8
|
+
STORNOBELEG
|
|
9
|
+
================================
|
|
10
|
+
Stornobuchung zu Beleg
|
|
11
|
+
AT0-KASSE1-70
|
|
12
|
+
vom 19.10.2026, 10:15 Uhr
|
|
13
|
+
Grund: Kunde hat storniert
|
|
14
|
+
|
|
15
|
+
Datum: 19.10.2026 10:15:30
|
|
16
|
+
Kassen-ID: KASSE1
|
|
17
|
+
Beleg-ID: AT0-KASSE1-77
|
|
18
|
+
|
|
19
|
+
1 x Maniküre -35,00 A
|
|
20
|
+
Gutschein ····-9DWT 30,50 A
|
|
21
|
+
|
|
22
|
+
MwSt% MwSt Netto Brutto
|
|
23
|
+
A 20% -0,75 -3,75 -4,50
|
|
24
|
+
--------------------------------
|
|
25
|
+
Gesamt: -4,50 €
|
|
26
|
+
Zahlungsart: Barzahlung
|
|
27
|
+
|
|
28
|
+
[QR-Code]
|
|
29
|
+
|
|
30
|
+
Danke für Ihren Besuch
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
Melisse Nails e.U.
|
|
2
|
+
Melissenweg 7
|
|
3
|
+
1070 Wien
|
|
4
|
+
ATU12345675
|
|
5
|
+
+43 1 2345678
|
|
6
|
+
|
|
7
|
+
================================================
|
|
8
|
+
STORNOBELEG
|
|
9
|
+
================================================
|
|
10
|
+
Stornobuchung zu Beleg AT0-KASSE1-70
|
|
11
|
+
vom 19.10.2026, 10:15 Uhr
|
|
12
|
+
Grund: Kunde hat storniert
|
|
13
|
+
|
|
14
|
+
Datum: 19.10.2026 10:15:30
|
|
15
|
+
Kassen-ID: KASSE1
|
|
16
|
+
Beleg-ID: AT0-KASSE1-77
|
|
17
|
+
|
|
18
|
+
1 x Maniküre -35,00 A
|
|
19
|
+
Gutschein ····-9DWT 30,50 A
|
|
20
|
+
|
|
21
|
+
MwSt% MwSt Netto Brutto
|
|
22
|
+
A 20% -0,75 -3,75 -4,50
|
|
23
|
+
------------------------------------------------
|
|
24
|
+
Gesamt: -4,50 €
|
|
25
|
+
Zahlungsart: Barzahlung
|
|
26
|
+
|
|
27
|
+
[QR-Code]
|
|
28
|
+
|
|
29
|
+
Danke für Ihren Besuch
|