@kreiseck/kasseneck-api 1.16.0 → 1.17.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.
- package/CHANGELOG.md +21 -0
- package/dist/cjs/client/receipts.js +8 -0
- package/dist/cjs/client/reports.d.ts +10 -9
- package/dist/cjs/client/reports.js +10 -9
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/models/voucher.d.ts +46 -4
- package/dist/cjs/models/voucher.js +58 -11
- package/dist/cjs/pos/artikel.d.ts +9 -0
- package/dist/cjs/pos/artikel.js +1 -0
- package/dist/cjs/pos/gutschein.d.ts +107 -2
- package/dist/cjs/pos/gutschein.js +124 -4
- package/dist/cjs/pos/index.d.ts +1 -1
- package/dist/cjs/pos/index.js +7 -3
- package/dist/cjs/pos/texte.d.ts +39 -0
- package/dist/cjs/pos/texte.js +22 -0
- package/dist/cjs/receipt/due.d.ts +20 -9
- package/dist/cjs/receipt/due.js +1 -0
- package/dist/cjs/receipt/gutschein-plan.d.ts +23 -7
- package/dist/cjs/receipt/gutschein-plan.js +67 -2
- package/dist/cjs/receipt/index.d.ts +1 -1
- package/dist/cjs/stored/draht.js +10 -2
- package/dist/cjs/stored/vokabular.d.ts +1 -1
- package/dist/cjs/stored/vokabular.js +84 -3
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/client/receipts.js +8 -0
- package/dist/esm/client/reports.d.ts +10 -9
- package/dist/esm/client/reports.js +10 -9
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/models/voucher.d.ts +46 -4
- package/dist/esm/models/voucher.js +56 -11
- package/dist/esm/pos/artikel.d.ts +9 -0
- package/dist/esm/pos/artikel.js +1 -0
- package/dist/esm/pos/gutschein.d.ts +107 -2
- package/dist/esm/pos/gutschein.js +123 -3
- package/dist/esm/pos/index.d.ts +1 -1
- package/dist/esm/pos/index.js +2 -2
- package/dist/esm/pos/texte.d.ts +39 -0
- package/dist/esm/pos/texte.js +22 -0
- package/dist/esm/receipt/due.d.ts +20 -9
- package/dist/esm/receipt/due.js +1 -0
- package/dist/esm/receipt/gutschein-plan.d.ts +23 -7
- package/dist/esm/receipt/gutschein-plan.js +68 -3
- package/dist/esm/receipt/index.d.ts +1 -1
- package/dist/esm/stored/draht.js +10 -2
- package/dist/esm/stored/vokabular.d.ts +1 -1
- package/dist/esm/stored/vokabular.js +84 -3
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/fixtures/hobex-hps-codes.json +1 -1
- package/fixtures/invoice-api.schema.json +1 -1
- package/fixtures/invoice-texts.json +1 -1
- package/fixtures/pos-texts.json +43 -2
- package/fixtures/receipt-due-voucher-generated.json +485 -483
- package/fixtures/surface.json +17 -1
- package/fixtures/v3/README.md +8 -1
- package/fixtures/v3/antworten/belege.json +27 -12
- package/fixtures/v3/antworten/belegmail.json +4 -1
- package/fixtures/v3/antworten/berichte.json +151 -0
- package/fixtures/v3/antworten/kasse-belege.json +27 -12
- package/fixtures/v3/antworten/kasse.json +366 -9
- package/fixtures/v3/antworten/lager.json +1 -1
- package/fixtures/v3/antworten/rechnungen.json +4 -1
- package/fixtures/v3/antworten/storno.json +4 -1
- package/fixtures/v3/stored/belege.json +4 -1
- package/fixtures/v3/stored/kasse.json +2 -2
- package/fixtures/v3/stored/rechnungen.json +4 -1
- package/fixtures/v3/v3-vokabular.json +417 -10
- package/fixtures/v3/zahlbetrag-faelle.json +29 -10
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.VOUCHER_SETTINGS_DEFAULTS = exports.VOUCHER_STATUSES = exports.VOUCHER_KINDS = void 0;
|
|
3
|
+
exports.VOUCHER_SETTINGS_DEFAULTS = exports.VOUCHER_TYPE_VALIDITY_PATTERNS = exports.VOUCHER_AMOUNT_MODES = exports.VOUCHER_TYPE_KINDS = exports.VOUCHER_PAYOUTS = exports.VOUCHER_STATUSES = exports.VOUCHER_KINDS = void 0;
|
|
4
4
|
exports.posVoucherSettingsFromWire = posVoucherSettingsFromWire;
|
|
5
5
|
exports.checkVoucher = checkVoucher;
|
|
6
6
|
exports.reprintVoucherLabel = reprintVoucherLabel;
|
|
@@ -8,10 +8,21 @@ const validator_1 = require("@kreiseck/validator");
|
|
|
8
8
|
const errors_js_1 = require("../client/errors.js");
|
|
9
9
|
exports.VOUCHER_KINDS = Object.freeze(['multi_purpose', 'single_purpose', 'service', 'promotion']);
|
|
10
10
|
exports.VOUCHER_STATUSES = Object.freeze(['active', 'used_up', 'expired', 'paid_out', 'cancelled', 'blocked']);
|
|
11
|
+
// Nur die Muster, die der Server an Gutscheinen nach aussen gibt: eine Sorte mit
|
|
12
|
+
// „N Jahre“ geht fuer jedes N als `1+3` mit den Daten und `redeemableYears` = N hinaus
|
|
13
|
+
// (Nachtrag E1), damit Kassen bis 1.16 beim Einloesen nicht an einem neuen Muster
|
|
14
|
+
// scheitern und „einloesbar bis <Datum>“ drucken.
|
|
11
15
|
const VOUCHER_VALIDITY_PATTERNS = ['unlimited', '1+3', 'custom'];
|
|
16
|
+
exports.VOUCHER_PAYOUTS = Object.freeze(['allowed', 'never']);
|
|
17
|
+
exports.VOUCHER_TYPE_KINDS = Object.freeze(['multi_purpose', 'single_purpose']);
|
|
18
|
+
/** Betrag einer Sorte: frei an der Kasse eingegeben oder fest. */
|
|
19
|
+
exports.VOUCHER_AMOUNT_MODES = Object.freeze(['free', 'fixed']);
|
|
20
|
+
/** Gueltigkeit einer Sorte: unbefristet oder N Jahre (das Muster der Sorte, nicht das eines Gutscheins). */
|
|
21
|
+
exports.VOUCHER_TYPE_VALIDITY_PATTERNS = Object.freeze(['unlimited', 'years']);
|
|
12
22
|
/** Ohne Block `vouchers` (alter Server, Konto ohne Schalter): Verkaufen ist aus. */
|
|
13
23
|
exports.VOUCHER_SETTINGS_DEFAULTS = Object.freeze({
|
|
14
24
|
sale: false, valueVoucherType: null, vatRateBp: null,
|
|
25
|
+
typeSale: false, types: Object.freeze([]), serviceArticles: false, labelDefault: null,
|
|
15
26
|
});
|
|
16
27
|
/**
|
|
17
28
|
* Block `vouchers` einer Einstellungs-Antwort, geschlossen im Zweifel: ist
|
|
@@ -21,10 +32,18 @@ exports.VOUCHER_SETTINGS_DEFAULTS = Object.freeze({
|
|
|
21
32
|
* `multi_purpose`/`single_purpose`/`null`, der Satz eine ganze Zahl >= 0 oder
|
|
22
33
|
* `null`; Mehrzweck traegt keinen Satz, Einzweck braucht einen, und ein
|
|
23
34
|
* eingeschalteter Verkauf braucht eine Art. Ein ausgeschalteter Verkauf darf
|
|
24
|
-
* eine Art behalten.
|
|
35
|
+
* eine Art behalten. `typeSale` und `serviceArticles` sind Wahrheitswerte,
|
|
36
|
+
* `types` eine Liste (fehlen sie, antwortet ein aelterer Server: aus, leer).
|
|
37
|
+
*
|
|
38
|
+
* Sorten (Gutscheine Stufe 4b) liest der Leser einzeln: eine unstimmige Sorte
|
|
39
|
+
* faellt weg ([sorteVomDraht]), die anderen bleiben; ist danach weder eine
|
|
40
|
+
* Sorte noch ein Leistungsartikel da, ist `typeSale` aus (kein leerer Reiter).
|
|
41
|
+
* Eine unbrauchbare Etikett-Vorlage schliesst nichts: sie wird `null`, die
|
|
42
|
+
* Kasse druckt dann ihren Standard (ein Verkauf scheitert nie an der Vorlage).
|
|
43
|
+
* Das alte Feld `label` (Kassen vor 1.17, Ruling R3) liest das Paket nicht.
|
|
25
44
|
*/
|
|
26
45
|
function posVoucherSettingsFromWire(block) {
|
|
27
|
-
const zu = () => ({ ...exports.VOUCHER_SETTINGS_DEFAULTS });
|
|
46
|
+
const zu = () => ({ ...exports.VOUCHER_SETTINGS_DEFAULTS, types: [] });
|
|
28
47
|
if (block === null || typeof block !== 'object' || Array.isArray(block))
|
|
29
48
|
return zu();
|
|
30
49
|
const b = block;
|
|
@@ -43,7 +62,92 @@ function posVoucherSettingsFromWire(block) {
|
|
|
43
62
|
return zu();
|
|
44
63
|
if (art === 'multi_purpose' && satz !== null)
|
|
45
64
|
return zu();
|
|
46
|
-
|
|
65
|
+
const sortenVerkauf = b['typeSale'] ?? false;
|
|
66
|
+
const rohSorten = b['types'] ?? [];
|
|
67
|
+
const leistung = b['serviceArticles'] ?? false;
|
|
68
|
+
if (typeof sortenVerkauf !== 'boolean' || typeof leistung !== 'boolean' || !Array.isArray(rohSorten))
|
|
69
|
+
return zu();
|
|
70
|
+
const types = [];
|
|
71
|
+
const gesehen = new Set();
|
|
72
|
+
for (const roh of rohSorten) {
|
|
73
|
+
const t = sorteVomDraht(roh);
|
|
74
|
+
if (t === null || gesehen.has(t.id))
|
|
75
|
+
continue;
|
|
76
|
+
gesehen.add(t.id);
|
|
77
|
+
types.push(t);
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
sale, valueVoucherType: art, vatRateBp: satz,
|
|
81
|
+
typeSale: sortenVerkauf && (types.length > 0 || leistung),
|
|
82
|
+
types,
|
|
83
|
+
serviceArticles: leistung,
|
|
84
|
+
labelDefault: vorlageVomDraht(b['labelDefault']),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/** Kennung wie am Server (gutschein-core.ID_MUSTER): reservierte `__…__` gibt es nie als Sorte. */
|
|
88
|
+
const SORTE_ID = /^(?!__.*__$)[A-Za-z0-9_-]{1,128}$/;
|
|
89
|
+
/** Grenzen des Servers (gutschein-core.pruefeSorte): Fixbetrag 1,00 bis 10.000,00 €, Gueltigkeit 1 bis 30 Jahre. */
|
|
90
|
+
const MIN_FIX_CENTS = 100;
|
|
91
|
+
const MAX_BETRAG_CENTS = 1_000_000;
|
|
92
|
+
const MAX_JAHRE = 30;
|
|
93
|
+
const istObjekt = (w) => w !== null && typeof w === 'object' && !Array.isArray(w);
|
|
94
|
+
const ganzeZahl = (w, min, max = Number.MAX_SAFE_INTEGER) => typeof w === 'number' && Number.isSafeInteger(w) && w >= min && w <= max;
|
|
95
|
+
/** Etikett-Vorlage als Kopie, wenn sie Groesse und Layout als Text traegt; sonst `null`. */
|
|
96
|
+
function vorlageVomDraht(w) {
|
|
97
|
+
if (!istObjekt(w) || typeof w['size'] !== 'string' || typeof w['layout'] !== 'string')
|
|
98
|
+
return null;
|
|
99
|
+
return JSON.parse(JSON.stringify(w));
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Eine Sorte aus `vouchers.types[]`, oder `null`, wenn sie nicht so ist, wie
|
|
103
|
+
* der Server eine verkaufbare Sorte liefert (dann bietet die Kasse sie nicht
|
|
104
|
+
* an): Kennung, Name, Art mit passendem Satz, Betrag, Gueltigkeit, Auszahlung
|
|
105
|
+
* (`never` nur unbefristet) und aktiv. Fehlende Reihenfolge oder Verkaufszahl
|
|
106
|
+
* gelten als 0; eine unbrauchbare Vorlage wird `null`.
|
|
107
|
+
*/
|
|
108
|
+
function sorteVomDraht(w) {
|
|
109
|
+
if (!istObjekt(w))
|
|
110
|
+
return null;
|
|
111
|
+
const { id, name, kind, amount, validity, payout } = w;
|
|
112
|
+
const satz = w['vatRateBp'] ?? null;
|
|
113
|
+
const reihenfolge = w['order'] ?? 0;
|
|
114
|
+
const verkauft = w['soldCount'] ?? 0;
|
|
115
|
+
if (typeof id !== 'string' || !SORTE_ID.test(id))
|
|
116
|
+
return null;
|
|
117
|
+
if (typeof name !== 'string' || name.trim() === '')
|
|
118
|
+
return null;
|
|
119
|
+
if (kind !== 'multi_purpose' && kind !== 'single_purpose')
|
|
120
|
+
return null;
|
|
121
|
+
if (kind === 'single_purpose' ? !ganzeZahl(satz, 1) : satz !== null)
|
|
122
|
+
return null;
|
|
123
|
+
if (!istObjekt(amount) || !istObjekt(validity))
|
|
124
|
+
return null;
|
|
125
|
+
let betrag;
|
|
126
|
+
if (amount['mode'] === 'free')
|
|
127
|
+
betrag = { mode: 'free' };
|
|
128
|
+
else if (amount['mode'] === 'fixed' && ganzeZahl(amount['cents'], MIN_FIX_CENTS, MAX_BETRAG_CENTS))
|
|
129
|
+
betrag = { mode: 'fixed', cents: amount['cents'] };
|
|
130
|
+
else
|
|
131
|
+
return null;
|
|
132
|
+
let gueltig;
|
|
133
|
+
if (validity['pattern'] === 'unlimited')
|
|
134
|
+
gueltig = { pattern: 'unlimited' };
|
|
135
|
+
else if (validity['pattern'] === 'years' && ganzeZahl(validity['years'], 1, MAX_JAHRE))
|
|
136
|
+
gueltig = { pattern: 'years', years: validity['years'] };
|
|
137
|
+
else
|
|
138
|
+
return null;
|
|
139
|
+
if (payout !== 'allowed' && payout !== 'never')
|
|
140
|
+
return null;
|
|
141
|
+
if (payout === 'never' && gueltig.pattern !== 'unlimited')
|
|
142
|
+
return null;
|
|
143
|
+
if (!ganzeZahl(reihenfolge, Number.MIN_SAFE_INTEGER) || !ganzeZahl(verkauft, 0))
|
|
144
|
+
return null;
|
|
145
|
+
if (w['active'] !== true)
|
|
146
|
+
return null;
|
|
147
|
+
return {
|
|
148
|
+
id, name, kind, vatRateBp: satz, amount: betrag, validity: gueltig, payout,
|
|
149
|
+
label: vorlageVomDraht(w['label']), order: reihenfolge, active: true, soldCount: verkauft,
|
|
150
|
+
};
|
|
47
151
|
}
|
|
48
152
|
function fehler(name, grund) {
|
|
49
153
|
return new errors_js_1.KasseneckValidationError(name, `Antwort: ${grund}`, 'response');
|
|
@@ -77,6 +181,12 @@ function wahl(name, pfad, o, feld, erlaubt) {
|
|
|
77
181
|
function gueltigkeit(name, w) {
|
|
78
182
|
const o = objekt(name, 'validity', w);
|
|
79
183
|
const raus = { pattern: wahl(name, 'validity', o, 'pattern', VOUCHER_VALIDITY_PATTERNS) };
|
|
184
|
+
if (!fehlt(o.redeemableYears)) {
|
|
185
|
+
const jahre = o.redeemableYears;
|
|
186
|
+
if (typeof jahre !== 'number' || !Number.isSafeInteger(jahre) || jahre < 1)
|
|
187
|
+
throw fehler(name, 'validity.redeemableYears ist keine Zahl von Jahren');
|
|
188
|
+
raus.redeemableYears = jahre;
|
|
189
|
+
}
|
|
80
190
|
for (const feld of ['redeemableUntil', 'refundableUntil', 'validUntil']) {
|
|
81
191
|
const t = o[feld];
|
|
82
192
|
if (fehlt(t))
|
|
@@ -117,6 +227,16 @@ function leseCheck(name, w) {
|
|
|
117
227
|
throw fehler(name, 'data.exempt ist kein Wahrheitswert');
|
|
118
228
|
raus.exempt = o.exempt;
|
|
119
229
|
}
|
|
230
|
+
if (!fehlt(o.typeName)) {
|
|
231
|
+
if (typeof o.typeName !== 'string' || o.typeName === '')
|
|
232
|
+
throw fehler(name, 'data.typeName ist kein Text');
|
|
233
|
+
raus.typeName = o.typeName;
|
|
234
|
+
}
|
|
235
|
+
// Geschlossen im Zweifel, ohne Wurf: ein unbekannter Wert (neuerer Server)
|
|
236
|
+
// gilt als `never`. Einloesen haengt nicht daran und darf nicht an einem
|
|
237
|
+
// neuen Wert scheitern (die Lehre aus dem Gueltigkeitsmuster, Nachtrag E1).
|
|
238
|
+
if (!fehlt(o.payout))
|
|
239
|
+
raus.payout = o.payout === 'allowed' ? 'allowed' : 'never';
|
|
120
240
|
return raus;
|
|
121
241
|
}
|
|
122
242
|
/**
|
package/dist/cjs/pos/index.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ export { STOCK_LOCATION_TYPES, type StockLocationType, type StockLocation, type
|
|
|
18
18
|
export { type ListMyStocktakesOptions, type ListMyStocktakeItemsOptions, type ListMyStocktakeCountsOptions, type RecordMyStocktakeCountOptions, type VoidMyStocktakeCountOptions, listMyStocktakes, listMyStocktakeItems, listMyStocktakeCounts, recordMyStocktakeCount, voidMyStocktakeCount, parseQuantityMilli, } from './inventur.js';
|
|
19
19
|
export type { Stocktake, StocktakeItem, StocktakeCount, StocktakeCountResult, StocktakeItemPage, StocktakeCountPage, StocktakeActor, StocktakeProgress, StocktakeReview, StocktakeRecount, StocktakeScope, } from '../inventory/typen.js';
|
|
20
20
|
export type { StocktakeStatus } from '../inventory/vertrag.js';
|
|
21
|
-
export { VOUCHER_KINDS, VOUCHER_STATUSES, checkVoucher, reprintVoucherLabel, VOUCHER_SETTINGS_DEFAULTS, posVoucherSettingsFromWire, type VoucherKind, type VoucherStatus, type VoucherValidity, type VoucherArticle, type VoucherCheck, type PosVoucherSettings, } from './gutschein.js';
|
|
21
|
+
export { VOUCHER_KINDS, VOUCHER_STATUSES, checkVoucher, reprintVoucherLabel, VOUCHER_SETTINGS_DEFAULTS, posVoucherSettingsFromWire, VOUCHER_PAYOUTS, VOUCHER_TYPE_KINDS, VOUCHER_AMOUNT_MODES, VOUCHER_TYPE_VALIDITY_PATTERNS, type VoucherKind, type VoucherStatus, type VoucherValidity, type VoucherArticle, type VoucherCheck, type PosVoucherSettings, type VoucherPayout, type VoucherTypeKind, type PosVoucherType, type VoucherLabelTemplate, } from './gutschein.js';
|
|
22
22
|
export { type GetMyDrawerStateOptions, type OpenMyShiftOptions, type RecordMyCashMovementOptions, type DrawerOpeningEntry, type LogMyDrawerOpeningsOptions, type GetMyShiftReportOptions, type TipPayout, type CloseMyShiftOptions, type AfterCountOption, getMyDrawerState, openMyShift, recordMyCashMovement, logMyDrawerOpenings, getMyShiftReport, closeMyShift, sumDenominations, parseCentsAllowZero, newIdempotencyKey, shiftTipLines, durationText, type ShiftTipLine, type ShiftTipLineKey, } from './schicht.js';
|
|
23
23
|
export { EUR_DENOMINATIONS, MOVEMENT_TYPES, MANUAL_MOVEMENT_TYPES, CASH_LOCATIONS, OPENING_REASONS, MANUAL_OPENING_REASONS, SHIFT_RECEIPT_KINDS, AFTER_COUNT_TYPES, type AfterCountType, type AfterCount, type EurDenomination, type MovementType, type ManualMovementType, type CashLocation, type OpeningReason, type ManualOpeningReason, type ShiftReceiptKind, type ShiftStatus, type ShiftActorRole, type Denominations, type ShiftActor, type DrawerInfo, type DrawerRights, type NonCashAmount, type ShiftTipTotals, type ShiftTip, type ShiftRunningTotals, type ShiftReconciliation, type Shift, type TipClaim, type DrawerOpening, type DrawerState, type CashMovement, type ShiftReceiptHeader, type ShiftReceiptMovement, type ShiftReceiptTip, type ShiftSummaryReceipt, type CashMovementReceipt, type ShiftReceipt, type OpenShiftResult, type CashMovementResult, type DrawerOpeningsResult, type ShiftReport, type CloseShiftResult, } from './schicht-typen.js';
|
|
24
24
|
export { type ShiftReceiptLayoutOptions, shiftReceiptLayout, cashMovementLayout } from '../receipt/shift-sheet.js';
|
package/dist/cjs/pos/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.quantityRuleForUnit = exports.QUANTITY_RULES = exports.listMyArticles = exports.listMyArticleGroups = exports.fromPosArticlePayload = exports.fromArticleGroupPayload = exports.DONE_SCREEN_SECONDS = exports.WATERMARK_SCALE = exports.LOGO_SCALE = exports.WATERMARK_STRENGTH = exports.WATERMARK_SIDE = exports.DISCOUNT = exports.AUTO_LOGOUT_MINUTES = exports.TILE_STYLE = exports.SETTINGS_FONT_SIZE = exports.LOGO_SIZE = exports.QR_MODE = exports.DRAWER_AUTO_OPEN = exports.CUT = exports.CODE_PAGE = exports.PAPER_SIZE = exports.TERMINAL_TYPE = exports.TERMINAL_VIA = exports.PRINTER_TYPE = exports.TILE_HEIGHT = exports.CATEGORY_POSITION = exports.LAYOUT = exports.RECEIPT_OUTPUT = exports.CARD_PROVIDER = exports.CHECKOUT_MODE = exports.TIP_MODE = exports.QUANTITY = exports.WATERMARK = exports.FONT_SIZE = exports.THEME = exports.posShortcutConflict = exports.POS_SHORTCUT_SHARED_PAIRS = exports.posSettingsChanges = exports.unknownPosSettingValues = exports.sanitizePosSettings = exports.mergePosSettings = exports.POS_DEVICE_VALUES = exports.POS_BUSINESS_VALUES = exports.posTipKeptByDefault = exports.POS_BUSINESS_OPTIONAL_FIELDS = exports.POS_DEVICE_OPTIONAL_FIELDS = exports.POS_DEVICE_DEFAULTS = exports.POS_BUSINESS_DEFAULTS = exports.POS_SHORTCUT_DEFAULTS = exports.POS_SHORTCUT_ACTIONS = void 0;
|
|
4
|
-
exports.
|
|
5
|
-
exports.receiptOutputLabel = exports.RETURN_DISPOSITION_LABELS = exports.labelText = exports.LABELS = exports.voucherErrorMessage = exports.VOUCHER_ERROR_MESSAGES = exports.cancellationPaymentErrorMessage = exports.CANCELLATION_PAYMENT_ERROR_MESSAGES = exports.receiptEmailErrorMessage = exports.RECEIPT_EMAIL_ERROR_MESSAGES = exports.messageAppliesTo = exports.messageText = exports.messageOutcome = exports.findErrorRule = exports.CALLS_WITH_EFFECT = exports.ERROR_OUTCOME_RULES = exports.ERROR_CODE_RULES = exports.ERROR_RULES = exports.MESSAGES = exports.isReturnDisposition = exports.RETURN_DISPOSITIONS = exports.RECEIPT_OUTPUT_RESULTS = exports.RECEIPT_OUTPUT_KINDS = exports.cashMovementLayout = exports.shiftReceiptLayout = exports.AFTER_COUNT_TYPES = exports.SHIFT_RECEIPT_KINDS = exports.MANUAL_OPENING_REASONS = exports.OPENING_REASONS = exports.CASH_LOCATIONS = exports.MANUAL_MOVEMENT_TYPES = exports.MOVEMENT_TYPES = exports.EUR_DENOMINATIONS = exports.durationText = void 0;
|
|
4
|
+
exports.closeMyShift = exports.getMyShiftReport = exports.logMyDrawerOpenings = exports.recordMyCashMovement = exports.openMyShift = exports.getMyDrawerState = exports.VOUCHER_TYPE_VALIDITY_PATTERNS = exports.VOUCHER_AMOUNT_MODES = exports.VOUCHER_TYPE_KINDS = exports.VOUCHER_PAYOUTS = exports.posVoucherSettingsFromWire = exports.VOUCHER_SETTINGS_DEFAULTS = exports.reprintVoucherLabel = exports.checkVoucher = exports.VOUCHER_STATUSES = exports.VOUCHER_KINDS = exports.parseQuantityMilli = exports.voidMyStocktakeCount = exports.recordMyStocktakeCount = exports.listMyStocktakeCounts = exports.listMyStocktakeItems = exports.listMyStocktakes = exports.setMyCashregisterStockLocation = exports.listMyStock = exports.listMyStockLocations = exports.STOCK_LOCATION_TYPES = exports.listMyTipRecipients = exports.getPrintJob = exports.createPrintJob = exports.listMyPrinters = exports.isPrintJobFinished = exports.PRINT_JOB_SOURCES = exports.PRINT_JOB_STATUSES = exports.voucherPermsOf = exports.stockViewOf = exports.receiptsScopeOf = exports.cancelScopeOf = exports.distributeDiscount = exports.posFieldErrors = exports.isPosError = exports.posErrorCode = exports.isPosErrorCode = exports.POS_ERROR_CODES = exports.posSettingsFromWire = exports.setMyPosLogo = exports.setMyRegisterDeviceSettings = exports.setMyPosSettings = exports.getPosSettings = exports.allowedQuantity = exports.quantityDefaults = void 0;
|
|
5
|
+
exports.receiptOutputLabel = exports.RETURN_DISPOSITION_LABELS = exports.labelText = exports.LABELS = exports.voucherErrorMessage = exports.VOUCHER_ERROR_MESSAGES = exports.cancellationPaymentErrorMessage = exports.CANCELLATION_PAYMENT_ERROR_MESSAGES = exports.receiptEmailErrorMessage = exports.RECEIPT_EMAIL_ERROR_MESSAGES = exports.messageAppliesTo = exports.messageText = exports.messageOutcome = exports.findErrorRule = exports.CALLS_WITH_EFFECT = exports.ERROR_OUTCOME_RULES = exports.ERROR_CODE_RULES = exports.ERROR_RULES = exports.MESSAGES = exports.isReturnDisposition = exports.RETURN_DISPOSITIONS = exports.RECEIPT_OUTPUT_RESULTS = exports.RECEIPT_OUTPUT_KINDS = exports.cashMovementLayout = exports.shiftReceiptLayout = exports.AFTER_COUNT_TYPES = exports.SHIFT_RECEIPT_KINDS = exports.MANUAL_OPENING_REASONS = exports.OPENING_REASONS = exports.CASH_LOCATIONS = exports.MANUAL_MOVEMENT_TYPES = exports.MOVEMENT_TYPES = exports.EUR_DENOMINATIONS = exports.durationText = exports.shiftTipLines = exports.newIdempotencyKey = exports.parseCentsAllowZero = exports.sumDenominations = void 0;
|
|
6
6
|
/**
|
|
7
7
|
* Kachel-Kasse: Einstellungen, Artikelgruppen/Artikel fuer Kacheln,
|
|
8
8
|
* Rabattverteilung, Drucker, Trinkgeld-Empfaenger, Lager (Standorte, Bestand,
|
|
@@ -108,7 +108,7 @@ Object.defineProperty(exports, "listMyStocktakeCounts", { enumerable: true, get:
|
|
|
108
108
|
Object.defineProperty(exports, "recordMyStocktakeCount", { enumerable: true, get: function () { return inventur_js_1.recordMyStocktakeCount; } });
|
|
109
109
|
Object.defineProperty(exports, "voidMyStocktakeCount", { enumerable: true, get: function () { return inventur_js_1.voidMyStocktakeCount; } });
|
|
110
110
|
Object.defineProperty(exports, "parseQuantityMilli", { enumerable: true, get: function () { return inventur_js_1.parseQuantityMilli; } });
|
|
111
|
-
// Gutschein pruefen und Etikett nachdrucken an der Kasse.
|
|
111
|
+
// Gutschein pruefen und Etikett nachdrucken an der Kasse; Gutschein-Sorten (Stufe 4b, 1.17.0).
|
|
112
112
|
var gutschein_js_1 = require("./gutschein.js");
|
|
113
113
|
Object.defineProperty(exports, "VOUCHER_KINDS", { enumerable: true, get: function () { return gutschein_js_1.VOUCHER_KINDS; } });
|
|
114
114
|
Object.defineProperty(exports, "VOUCHER_STATUSES", { enumerable: true, get: function () { return gutschein_js_1.VOUCHER_STATUSES; } });
|
|
@@ -116,6 +116,10 @@ Object.defineProperty(exports, "checkVoucher", { enumerable: true, get: function
|
|
|
116
116
|
Object.defineProperty(exports, "reprintVoucherLabel", { enumerable: true, get: function () { return gutschein_js_1.reprintVoucherLabel; } });
|
|
117
117
|
Object.defineProperty(exports, "VOUCHER_SETTINGS_DEFAULTS", { enumerable: true, get: function () { return gutschein_js_1.VOUCHER_SETTINGS_DEFAULTS; } });
|
|
118
118
|
Object.defineProperty(exports, "posVoucherSettingsFromWire", { enumerable: true, get: function () { return gutschein_js_1.posVoucherSettingsFromWire; } });
|
|
119
|
+
Object.defineProperty(exports, "VOUCHER_PAYOUTS", { enumerable: true, get: function () { return gutschein_js_1.VOUCHER_PAYOUTS; } });
|
|
120
|
+
Object.defineProperty(exports, "VOUCHER_TYPE_KINDS", { enumerable: true, get: function () { return gutschein_js_1.VOUCHER_TYPE_KINDS; } });
|
|
121
|
+
Object.defineProperty(exports, "VOUCHER_AMOUNT_MODES", { enumerable: true, get: function () { return gutschein_js_1.VOUCHER_AMOUNT_MODES; } });
|
|
122
|
+
Object.defineProperty(exports, "VOUCHER_TYPE_VALIDITY_PATTERNS", { enumerable: true, get: function () { return gutschein_js_1.VOUCHER_TYPE_VALIDITY_PATTERNS; } });
|
|
119
123
|
// Schicht, Kassenstand und Lade-Protokoll (1.9.0): Aufrufe, Kataloge, Helfer, Bons.
|
|
120
124
|
var schicht_js_1 = require("./schicht.js");
|
|
121
125
|
Object.defineProperty(exports, "getMyDrawerState", { enumerable: true, get: function () { return schicht_js_1.getMyDrawerState; } });
|
package/dist/cjs/pos/texte.d.ts
CHANGED
|
@@ -371,6 +371,24 @@ declare const MELDUNGEN_ROH: {
|
|
|
371
371
|
readonly 'voucher_error.sale_off': {
|
|
372
372
|
readonly text: "Gutscheine verkaufen geht hier noch nicht.";
|
|
373
373
|
};
|
|
374
|
+
readonly 'voucher_error.type_required': {
|
|
375
|
+
readonly text: "Bitte eine Gutschein-Sorte wählen.";
|
|
376
|
+
};
|
|
377
|
+
readonly 'voucher_error.type_not_found': {
|
|
378
|
+
readonly text: "Diese Gutschein-Sorte gibt es nicht mehr. Die Kasse lädt die Sorten neu.";
|
|
379
|
+
};
|
|
380
|
+
readonly 'voucher_error.amount_mismatch': {
|
|
381
|
+
readonly text: "Die Gutschein-Sorte hat sich geändert. Die Kasse lädt die Sorten neu.";
|
|
382
|
+
};
|
|
383
|
+
readonly 'voucher_error.service_not_allowed': {
|
|
384
|
+
readonly text: "Dieser Artikel ist nicht als Leistungsgutschein freigegeben.";
|
|
385
|
+
};
|
|
386
|
+
readonly 'voucher_error.payout_not_allowed': {
|
|
387
|
+
readonly text: "Dieser Gutschein kann nicht ausgezahlt werden.";
|
|
388
|
+
};
|
|
389
|
+
readonly 'voucher.type_changed': {
|
|
390
|
+
readonly text: "Diese Gutschein-Sorte hat sich geändert. Bitte die Zeile entfernen und die Kachel neu antippen.";
|
|
391
|
+
};
|
|
374
392
|
readonly 'voucher.reentry_needed': {
|
|
375
393
|
readonly text: "Die Karte ist belastet, der Beleg fehlt noch: zu jedem Gutschein den Code erneut eingeben, dann den Beleg abschließen.";
|
|
376
394
|
};
|
|
@@ -1048,6 +1066,11 @@ export declare const VOUCHER_ERROR_MESSAGES: {
|
|
|
1048
1066
|
readonly voucher_partial_cancel: "voucher_error.partial_cancel";
|
|
1049
1067
|
readonly voucher_settings_missing: "voucher_error.settings_missing";
|
|
1050
1068
|
readonly too_many_voucher_checks: "voucher_error.too_many_checks";
|
|
1069
|
+
readonly voucher_type_required: "voucher_error.type_required";
|
|
1070
|
+
readonly voucher_type_not_found: "voucher_error.type_not_found";
|
|
1071
|
+
readonly voucher_amount_mismatch: "voucher_error.amount_mismatch";
|
|
1072
|
+
readonly voucher_service_not_allowed: "voucher_error.service_not_allowed";
|
|
1073
|
+
readonly voucher_payout_not_allowed: "voucher_error.payout_not_allowed";
|
|
1051
1074
|
};
|
|
1052
1075
|
export type VoucherMessageCode = keyof typeof VOUCHER_ERROR_MESSAGES;
|
|
1053
1076
|
/** Der Satz zu einem Gutschein-`code`; `undefined` für jeden anderen Code. */
|
|
@@ -1896,6 +1919,22 @@ declare const BESCHRIFTUNGEN_ROH: {
|
|
|
1896
1919
|
readonly 'voucher.add': {
|
|
1897
1920
|
readonly text: "Hinzufügen";
|
|
1898
1921
|
};
|
|
1922
|
+
readonly 'voucher.tab': {
|
|
1923
|
+
readonly text: "Gutscheine";
|
|
1924
|
+
};
|
|
1925
|
+
readonly 'voucher.enter_amount': {
|
|
1926
|
+
readonly text: "Betrag eingeben";
|
|
1927
|
+
};
|
|
1928
|
+
readonly 'voucher.service_tile': {
|
|
1929
|
+
readonly text: "Leistungsgutschein";
|
|
1930
|
+
};
|
|
1931
|
+
readonly 'voucher.kind_multi_short': {
|
|
1932
|
+
readonly text: "Mehrzweck";
|
|
1933
|
+
};
|
|
1934
|
+
readonly 'voucher.kind_single_short': {
|
|
1935
|
+
readonly text: "Einzweck {rate} %";
|
|
1936
|
+
readonly placeholders: readonly ["rate"];
|
|
1937
|
+
};
|
|
1899
1938
|
readonly 'shift.all_payments': {
|
|
1900
1939
|
readonly text: "Alle Zahlungen dieser Schicht (bar + unbar)";
|
|
1901
1940
|
};
|
package/dist/cjs/pos/texte.js
CHANGED
|
@@ -207,6 +207,16 @@ const MELDUNGEN_ROH = {
|
|
|
207
207
|
'voucher_error.settings_missing': { text: 'Die Gutschein-Einstellungen fehlen. Bitte die Kasse neu laden.' },
|
|
208
208
|
'voucher_error.too_many_checks': { text: 'Zu viele Versuche. Bitte in einer Stunde wieder.' },
|
|
209
209
|
'voucher_error.sale_off': { text: 'Gutscheine verkaufen geht hier noch nicht.' },
|
|
210
|
+
// Gutschein-Sorten (Stufe 4b, 1.17.0): Verkauf nur ueber eine Sorte; bei den beiden Satzpaaren laedt die Kasse die Sorten neu.
|
|
211
|
+
'voucher_error.type_required': { text: 'Bitte eine Gutschein-Sorte wählen.' },
|
|
212
|
+
'voucher_error.type_not_found': { text: 'Diese Gutschein-Sorte gibt es nicht mehr. Die Kasse lädt die Sorten neu.' },
|
|
213
|
+
'voucher_error.amount_mismatch': { text: 'Die Gutschein-Sorte hat sich geändert. Die Kasse lädt die Sorten neu.' },
|
|
214
|
+
'voucher_error.service_not_allowed': { text: 'Dieser Artikel ist nicht als Leistungsgutschein freigegeben.' },
|
|
215
|
+
'voucher_error.payout_not_allowed': { text: 'Dieser Gutschein kann nicht ausgezahlt werden.' },
|
|
216
|
+
// Satz der Kasse selbst (1.17.0): eine Verkaufszeile im Korb passt nach dem Neuladen der Sorten nicht mehr (Sorte
|
|
217
|
+
// geaendert, deaktiviert oder geloescht). Die Zeile sperrt das Kassieren, bis sie entfernt und neu gewaehlt ist;
|
|
218
|
+
// der Satz nach einer Absage des Servers bleibt voucher_error.type_not_found bzw. voucher_error.amount_mismatch.
|
|
219
|
+
'voucher.type_changed': { text: 'Diese Gutschein-Sorte hat sich geändert. Bitte die Zeile entfernen und die Kachel neu antippen.' },
|
|
210
220
|
// Gutscheine an der Kasse, Stufe 3 (1.13.0): Sätze der Kasse selbst (nicht des Servers).
|
|
211
221
|
'voucher.reentry_needed': { text: 'Die Karte ist belastet, der Beleg fehlt noch: zu jedem Gutschein den Code erneut eingeben, dann den Beleg abschließen.' },
|
|
212
222
|
'voucher.reentry_mismatch': { text: 'Mit diesen Gutscheinen ergibt der Beleg nicht mehr den belasteten Betrag – die Karte zurückbuchen.' },
|
|
@@ -611,6 +621,11 @@ exports.VOUCHER_ERROR_MESSAGES = {
|
|
|
611
621
|
voucher_partial_cancel: 'voucher_error.partial_cancel',
|
|
612
622
|
voucher_settings_missing: 'voucher_error.settings_missing',
|
|
613
623
|
too_many_voucher_checks: 'voucher_error.too_many_checks',
|
|
624
|
+
voucher_type_required: 'voucher_error.type_required',
|
|
625
|
+
voucher_type_not_found: 'voucher_error.type_not_found',
|
|
626
|
+
voucher_amount_mismatch: 'voucher_error.amount_mismatch',
|
|
627
|
+
voucher_service_not_allowed: 'voucher_error.service_not_allowed',
|
|
628
|
+
voucher_payout_not_allowed: 'voucher_error.payout_not_allowed',
|
|
614
629
|
};
|
|
615
630
|
/** Der Satz zu einem Gutschein-`code`; `undefined` für jeden anderen Code. */
|
|
616
631
|
function voucherErrorMessage(code) {
|
|
@@ -952,6 +967,13 @@ const BESCHRIFTUNGEN_ROH = {
|
|
|
952
967
|
'voucher.code_done': { text: 'Fertig' },
|
|
953
968
|
'voucher.article': { text: 'Artikel' },
|
|
954
969
|
'voucher.add': { text: 'Hinzufügen' },
|
|
970
|
+
// Gutschein-Sorten als Kacheln im Reiter „Gutscheine“ (Stufe 4b, 1.17.0): Kachel je Sorte mit Betrag
|
|
971
|
+
// oder „Betrag eingeben“, darunter klein die Art; dazu die feste Kachel „Leistungsgutschein“.
|
|
972
|
+
'voucher.tab': { text: 'Gutscheine' },
|
|
973
|
+
'voucher.enter_amount': { text: 'Betrag eingeben' },
|
|
974
|
+
'voucher.service_tile': { text: 'Leistungsgutschein' },
|
|
975
|
+
'voucher.kind_multi_short': { text: 'Mehrzweck' },
|
|
976
|
+
'voucher.kind_single_short': { text: 'Einzweck {rate} %', placeholders: ['rate'] },
|
|
955
977
|
'shift.all_payments': { text: 'Alle Zahlungen dieser Schicht (bar + unbar)' },
|
|
956
978
|
'shift.receipt_count_one': { text: '1 Beleg' },
|
|
957
979
|
'shift.receipt_count_other': { text: '{count} Belege', placeholders: ['count'] },
|
|
@@ -2,8 +2,8 @@ import { ReceiptType, type ReceiptTypeKey, KeckPaymentMethod } from '../enums/in
|
|
|
2
2
|
import type { ReceiptItem } from '../models/receipt-item.js';
|
|
3
3
|
import type { Voucher } from '../models/voucher.js';
|
|
4
4
|
import type { PosVoucherSettings, VoucherCheck } from '../pos/gutschein.js';
|
|
5
|
-
import { type VoucherDueArticle, type VoucherDueInfo } from './gutschein-plan.js';
|
|
6
|
-
export { VOUCHER_ZERO_RATE_BUCKET_FROM, type VoucherDueArticle, type VoucherDueInfo } from './gutschein-plan.js';
|
|
5
|
+
import { type VoucherDueArticle, type VoucherDueInfo, type VoucherDueType } from './gutschein-plan.js';
|
|
6
|
+
export { VOUCHER_ZERO_RATE_BUCKET_FROM, type VoucherDueArticle, type VoucherDueInfo, type VoucherDueType } from './gutschein-plan.js';
|
|
7
7
|
/**
|
|
8
8
|
* Zahlbetrag eines Belegs in ganzen Cent: Zwilling von `createReceipt` im
|
|
9
9
|
* Backend (Nachtrag §8), also `beleg-toepfe.belegToepfe(...).zaehlerDeltaCents`
|
|
@@ -42,8 +42,8 @@ export { VOUCHER_ZERO_RATE_BUCKET_FROM, type VoucherDueArticle, type VoucherDueI
|
|
|
42
42
|
* (`gutschein-beleg.plane`, Zwilling in `gutschein-plan.ts`). Was er dafuer
|
|
43
43
|
* aus seinen Daten liest, gibt die Kasse mit: je Einloesung/Auszahlung die
|
|
44
44
|
* Pruefung aus `checkVoucher` (`voucherInfo`, ueber den Code zugeordnet), fuer
|
|
45
|
-
* einen
|
|
46
|
-
*
|
|
45
|
+
* einen Wertgutschein-Verkauf die Gutschein-Sorten (`voucherTypes`, Art, Satz,
|
|
46
|
+
* Betrag; seit 1.17.0), fuer einen Leistungsgutschein-Verkauf den Artikel
|
|
47
47
|
* (`voucherArticles`, Preis und Satz) und `smallBusiness` fuer ein
|
|
48
48
|
* Kleinunternehmer-Konto. Was fehlt oder was der Server abwiese, wirft
|
|
49
49
|
* `invalid_voucher` mit dem erwarteten Server-Code in `voucherErrorCode`.
|
|
@@ -86,11 +86,22 @@ export interface ReceiptDueOptions {
|
|
|
86
86
|
*/
|
|
87
87
|
voucherInfo?: readonly VoucherDueInfo[];
|
|
88
88
|
/**
|
|
89
|
-
* Gutschein-
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
89
|
+
* Gutschein-Sorten der Kasse (`getKasseSettings`, `vouchers.types`, oder
|
|
90
|
+
* je Verkauf die gewaehlte): ein Wertgutschein wird nur ueber eine Sorte
|
|
91
|
+
* verkauft (`typeId` am Wunsch), Art und Satz kommen aus ihr. Fehlt die
|
|
92
|
+
* Sorte des Wunschs hier: `voucher_type_not_found` (wie beim Server fuer
|
|
93
|
+
* eine unbekannte oder inaktive); ein anderer Fixbetrag oder eine andere
|
|
94
|
+
* Art am Wunsch (die Sorte wurde umgestellt): `voucher_amount_mismatch`.
|
|
95
|
+
*/
|
|
96
|
+
voucherTypes?: readonly VoucherDueType[];
|
|
97
|
+
/**
|
|
98
|
+
* Alte Gutschein-Einstellung der Kasse (bis 1.16, Block `vouchers` ohne
|
|
99
|
+
* Sorten). Nur noch fuer einen Wert-Verkauf ohne `typeId`: nennt sie eine
|
|
100
|
+
* Art (`valueVoucherType`), rechnet der Zahlbetrag wie bisher (eine andere
|
|
101
|
+
* Art: `voucher_invalid`); ohne sie oder ohne Art – so liest sich der Block
|
|
102
|
+
* jedes Servers ab Gutscheine Stufe 4b – `voucher_type_required`. Der
|
|
103
|
+
* Server verkauft seitdem nur ueber eine Sorte, und `createReceipt` sendet
|
|
104
|
+
* einen Wert-Verkauf ohne `typeId` nicht mehr.
|
|
94
105
|
*/
|
|
95
106
|
voucherSettings?: PosVoucherSettings;
|
|
96
107
|
/**
|
package/dist/cjs/receipt/due.js
CHANGED
|
@@ -92,6 +92,7 @@ function rechne(items, vouchers, receiptType, options) {
|
|
|
92
92
|
const plan = (0, gutschein_plan_js_1.planeGutscheine)(positionen, vouchers, art, {
|
|
93
93
|
voucherInfo: options.voucherInfo,
|
|
94
94
|
voucherSettings: options.voucherSettings,
|
|
95
|
+
voucherTypes: options.voucherTypes,
|
|
95
96
|
voucherArticles: options.voucherArticles,
|
|
96
97
|
smallBusiness: options.smallBusiness,
|
|
97
98
|
zeroRateBucketFrom: options.zeroRateBucketFrom,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Voucher } from '../models/voucher.js';
|
|
2
|
-
import type { PosVoucherSettings, VoucherArticle, VoucherCheck } from '../pos/gutschein.js';
|
|
2
|
+
import type { PosVoucherSettings, PosVoucherType, VoucherArticle, VoucherCheck } from '../pos/gutschein.js';
|
|
3
3
|
/**
|
|
4
4
|
* Gutscheine der neuen Form im Zahlbetrag: Zwilling von
|
|
5
5
|
* `gutschein-beleg.plane` im Backend, soweit er den Zahlbetrag bestimmt.
|
|
@@ -14,10 +14,16 @@ import type { PosVoucherSettings, VoucherArticle, VoucherCheck } from '../pos/gu
|
|
|
14
14
|
* - Mehrzweck einloesen: Eintrag `value`, mindert den Zahlbetrag als Fluss.
|
|
15
15
|
* - Mehrzweck verkaufen: Eintrag `value` (+Fluss); ab dem Stichtag des
|
|
16
16
|
* 0-%-Topfs stattdessen Position im 0-%-Satz ohne Fluss.
|
|
17
|
-
* - Mehrzweck auszahlen: immer Position im 0-%-Satz (minus), kein Fluss
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
17
|
+
* - Mehrzweck auszahlen: immer Position im 0-%-Satz (minus), kein Fluss;
|
|
18
|
+
* nie bei einem Gutschein mit Auszahlung `never`.
|
|
19
|
+
* - Einzweck: Position im Satz (Verkauf aus der Sorte, Einloesung und
|
|
20
|
+
* Auszahlung aus der Pruefung des Gutscheins); als Kleinunternehmer
|
|
21
|
+
* eingeloest anteilig auf alle Saetze des Korbs.
|
|
22
|
+
* - Wertgutschein verkaufen (Stufe 4b): nur ueber eine Sorte (`typeId`); Art
|
|
23
|
+
* und Satz kommen aus der Sorte, ein Fixbetrag muss stimmen. Ohne Sorte
|
|
24
|
+
* rechnet nur noch ein Aufrufer mit einer alten Gutschein-Einstellung mit
|
|
25
|
+
* Art (`voucherSettings.valueVoucherType`) wie bisher; sonst und beim
|
|
26
|
+
* Server immer `voucher_type_required`.
|
|
21
27
|
* - Leistung verkaufen: Stueck mal Artikelpreis im Artikelsatz; einloesen: je
|
|
22
28
|
* Satz eine Minuszeile ueber die gewaehlten Positionen.
|
|
23
29
|
* - Aktion: Rabatt wie `promo`, Betrag aus der Pruefung, hoechstens die Summe.
|
|
@@ -50,8 +56,17 @@ export interface VoucherDueInfo {
|
|
|
50
56
|
code: string;
|
|
51
57
|
check: VoucherCheck;
|
|
52
58
|
}
|
|
53
|
-
/**
|
|
54
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Artikel fuer den Verkauf eines Dienstleistungsgutscheins: Preis und Satz wie
|
|
61
|
+
* im Artikelstamm. `serviceVoucher` (`PosArticle.serviceVoucher`): bei `false`
|
|
62
|
+
* verkauft der Server ihn nicht (`voucher_service_not_allowed`); ohne Angabe
|
|
63
|
+
* rechnet der Zahlbetrag wie bisher.
|
|
64
|
+
*/
|
|
65
|
+
export type VoucherDueArticle = Pick<VoucherArticle, 'id' | 'priceCents' | 'vatRateBp'> & {
|
|
66
|
+
serviceVoucher?: boolean;
|
|
67
|
+
};
|
|
68
|
+
/** Gutschein-Sorte fuer den Verkauf: Kennung, Art, Satz und Betrag wie in `getKasseSettings` (`vouchers.types[]`). */
|
|
69
|
+
export type VoucherDueType = Pick<PosVoucherType, 'id' | 'kind' | 'vatRateBp' | 'amount'>;
|
|
55
70
|
/**
|
|
56
71
|
* Stichtag des 0-%-Topfs fuer Mehrzweck-Verkaeufe (Backend
|
|
57
72
|
* `gutschein-core.NULLTOPF_AB`). Solange er in der Zukunft liegt, zaehlt ein
|
|
@@ -62,6 +77,7 @@ export declare const VOUCHER_ZERO_RATE_BUCKET_FROM = "2099-12-31";
|
|
|
62
77
|
export interface PlanOptionen {
|
|
63
78
|
voucherInfo?: readonly VoucherDueInfo[];
|
|
64
79
|
voucherSettings?: PosVoucherSettings;
|
|
80
|
+
voucherTypes?: readonly VoucherDueType[];
|
|
65
81
|
voucherArticles?: readonly VoucherDueArticle[];
|
|
66
82
|
smallBusiness?: boolean;
|
|
67
83
|
zeroRateBucketFrom?: string;
|
|
@@ -53,6 +53,23 @@ function satzBp(vat) {
|
|
|
53
53
|
function position(satzBpWert, cents, kind) {
|
|
54
54
|
return { amount: 1, priceOne: cents / 100, vat: satzBpWert / 100, tip: null, kind };
|
|
55
55
|
}
|
|
56
|
+
/** Reservierte Kennung (`__…__`): gibt es am Server nie als Sorte (gutschein-core.RESERVIERTE_ID). */
|
|
57
|
+
const RESERVIERTE_ID = /^__.*__$/;
|
|
58
|
+
/**
|
|
59
|
+
* Die Sorte zum Wunsch, wie der Server sie verkaufen wuerde, oder null
|
|
60
|
+
* (unbekannt): Mehrzweck ohne Satz, Einzweck mit Satz > 0, Betrag frei oder
|
|
61
|
+
* fest von 1,00 bis 10.000,00 €. Eine unstimmige Sorte verkauft der Server
|
|
62
|
+
* nicht (`gutschein-beleg.sorteFuerVerkauf` ueber `gutschein-core.pruefeSorte`).
|
|
63
|
+
*/
|
|
64
|
+
function sorteZumWunsch(typen, typeId) {
|
|
65
|
+
const t = (typen ?? []).find((x) => x.id === typeId);
|
|
66
|
+
if (t == null)
|
|
67
|
+
return null;
|
|
68
|
+
const satzOk = t.kind === 'multi_purpose' ? t.vatRateBp == null : t.kind === 'single_purpose' && Number.isInteger(t.vatRateBp) && t.vatRateBp > 0;
|
|
69
|
+
const betragOk = t.amount?.mode === 'free'
|
|
70
|
+
|| (t.amount?.mode === 'fixed' && Number.isInteger(t.amount.cents) && t.amount.cents >= 100 && t.amount.cents <= 1_000_000);
|
|
71
|
+
return satzOk && betragOk ? t : null;
|
|
72
|
+
}
|
|
56
73
|
/** Code in Normalform (tolerant eingelesen, Pruefzeichen stimmt) oder null. */
|
|
57
74
|
function normalerCode(code) {
|
|
58
75
|
if (typeof code !== 'string')
|
|
@@ -161,7 +178,23 @@ function planeGutscheine(kunde, vouchers, art, o) {
|
|
|
161
178
|
for (const [i, v] of vouchers.entries()) {
|
|
162
179
|
if (istGelesen(v))
|
|
163
180
|
return nein('voucher_invalid', `Gutschein ${i + 1}: Serverfelder an einem Wunsch.`);
|
|
164
|
-
if ((0, voucher_js_1.isNewFormVoucher)(v)
|
|
181
|
+
if (!(0, voucher_js_1.isNewFormVoucher)(v))
|
|
182
|
+
continue;
|
|
183
|
+
if ((0, voucher_js_1.istWertVerkauf)(v) && v.typeId == null) {
|
|
184
|
+
// Wie gutschein-beleg.pruefeWuensche: ein Wert-Verkauf ohne Sorte ist voucher_type_required.
|
|
185
|
+
// Nur eine alte Gutschein-Einstellung MIT Art (Aufrufer bis 1.16) rechnet wie bisher; ein Server ab
|
|
186
|
+
// Stufe 4b schickt `valueVoucherType` immer null, dort hilft kein Neuladen – die Sorte fehlt.
|
|
187
|
+
if (o.voucherSettings?.valueVoucherType == null)
|
|
188
|
+
return nein('voucher_type_required', `Gutschein ${i + 1}: die Gutschein-Sorte fehlt (typeId).`);
|
|
189
|
+
if (!(0, voucher_js_1.wunschFormGueltig)(v, false))
|
|
190
|
+
return nein('voucher_invalid', `Gutschein ${i + 1} ist unvollstaendig.`);
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
// Eine reservierte Kennung weist der Server vor jeder anderen Pruefung als unbekannt ab.
|
|
194
|
+
if ((0, voucher_js_1.istWertVerkauf)(v) && typeof v.typeId === 'string' && RESERVIERTE_ID.test(v.typeId)) {
|
|
195
|
+
return nein('voucher_type_not_found', `Gutschein ${i + 1}: diese Gutschein-Sorte gibt es nicht.`);
|
|
196
|
+
}
|
|
197
|
+
if (!(0, voucher_js_1.voucherIsValid)(v))
|
|
165
198
|
return nein('voucher_invalid', `Gutschein ${i + 1} ist unvollstaendig.`);
|
|
166
199
|
}
|
|
167
200
|
// Kein Gutschein mit Gutschein bezahlen, sobald einer der beiden die neue Form hat.
|
|
@@ -219,6 +252,34 @@ function planeGutscheine(kunde, vouchers, art, o) {
|
|
|
219
252
|
gutscheine.push(g);
|
|
220
253
|
continue;
|
|
221
254
|
}
|
|
255
|
+
if ((0, voucher_js_1.istWertVerkauf)(v) && v.typeId != null) {
|
|
256
|
+
// Verkauf ueber eine Sorte (gutschein-beleg.plane): unbekannt, andere Art, falscher Fixbetrag. Eine andere Art
|
|
257
|
+
// heisst: die Kasse hat eine alte Sicht (Sorte umgestellt) – wie ein anderer Fixbetrag voucher_amount_mismatch,
|
|
258
|
+
// die Kasse laedt die Sorten neu.
|
|
259
|
+
const sorte = sorteZumWunsch(o.voucherTypes, v.typeId);
|
|
260
|
+
if (sorte == null)
|
|
261
|
+
return nein('voucher_type_not_found', `Gutschein ${i + 1}: die Gutschein-Sorte fehlt (voucherTypes).`);
|
|
262
|
+
if (v.type != null && v.type !== sorte.kind)
|
|
263
|
+
return nein('voucher_amount_mismatch', `Gutschein ${i + 1}: die Art passt nicht (mehr) zur Gutschein-Sorte.`);
|
|
264
|
+
if (sorte.amount.mode === 'fixed' && v.amountCents !== sorte.amount.cents) {
|
|
265
|
+
return nein('voucher_amount_mismatch', `Gutschein ${i + 1}: der Betrag passt nicht zum Fixbetrag der Gutschein-Sorte.`);
|
|
266
|
+
}
|
|
267
|
+
const c = v.amountCents;
|
|
268
|
+
if (sorte.kind === 'multi_purpose') {
|
|
269
|
+
if (nulltopf) {
|
|
270
|
+
zusatz.push(position(0, c, 'voucher_float'));
|
|
271
|
+
gutscheine.push({ action: 'sell', type: 'value', value: c / 100, imNullTopf: true });
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
gutscheine.push({ action: 'sell', type: 'value', value: c / 100 });
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
// Kleinunternehmer: befreit verkauft, der Satz der Sorte legt nur fest, wofuer der Gutschein gilt.
|
|
279
|
+
zusatz.push(position(ku ? 0 : sorte.vatRateBp, c, 'voucher'));
|
|
280
|
+
}
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
222
283
|
if (!ARTEN.includes(String(v.type)))
|
|
223
284
|
return nein('voucher_invalid', `Gutschein ${i + 1}: unbekannte Art.`);
|
|
224
285
|
if (v.action === 'sell') {
|
|
@@ -248,6 +309,8 @@ function planeGutscheine(kunde, vouchers, art, o) {
|
|
|
248
309
|
const a = (o.voucherArticles ?? []).find((x) => x.id === v.articleId);
|
|
249
310
|
if (a == null)
|
|
250
311
|
return nein('voucher_item_mismatch', `Gutschein ${i + 1}: der Artikel fehlt (voucherArticles).`);
|
|
312
|
+
if (a.serviceVoucher === false)
|
|
313
|
+
return nein('voucher_service_not_allowed', `Gutschein ${i + 1}: der Artikel ist nicht als Leistungsgutschein freigegeben.`);
|
|
251
314
|
if (!Number.isInteger(a.priceCents) || a.priceCents <= 0 || !Number.isInteger(a.vatRateBp) || a.vatRateBp < 0) {
|
|
252
315
|
return nein('voucher_invalid', `Gutschein ${i + 1}: Artikel ohne Preis oder Satz.`);
|
|
253
316
|
}
|
|
@@ -262,7 +325,9 @@ function planeGutscheine(kunde, vouchers, art, o) {
|
|
|
262
325
|
if ('fehler' in check)
|
|
263
326
|
return check;
|
|
264
327
|
if (v.action === 'payout') {
|
|
265
|
-
// `gutschein-core.darfAuszahlen`:
|
|
328
|
+
// `gutschein-core.darfAuszahlen`: Auszahlung nicht gesperrt, aktiv oder abgelaufen bis zum Ende der Rueckzahlbarkeit.
|
|
329
|
+
if (check.payout === 'never')
|
|
330
|
+
return nein('voucher_payout_not_allowed', `Gutschein ${i + 1}: dieser Gutschein wird nie ausgezahlt.`);
|
|
266
331
|
if (!((check.balanceCents ?? 0) > 0))
|
|
267
332
|
return nein('voucher_used_up', `Gutschein ${i + 1}: kein Saldo.`);
|
|
268
333
|
if (check.status === 'expired') {
|
|
@@ -8,4 +8,4 @@ export { rasterizeLogo } from './bild.js';
|
|
|
8
8
|
export { type BrandMarkRaster, BRAND_MARK_RASTERS, BRAND_MARK_PATHS } from './marke-daten.js';
|
|
9
9
|
export { brandMarkImage } from './marke.js';
|
|
10
10
|
export { type CodeTableTestSheetInput, type CodeTableTestSheetRow, type CodeTableTestSheet, CODE_TABLE_TEST_SHEET_CHARS, codeTableTestSheet, codeTableTestSheetBytes, codeTableReferenceImage, } from './code-table-test-sheet.js';
|
|
11
|
-
export { type ReceiptDueTip, type ReceiptDueTipRecipient, type ReceiptDueOptions, type ReceiptDueBuckets, type ReceiptDueBreakdown, type ReceiptDueErrorReason, receiptDueCents, receiptDueBreakdown, ReceiptDueError, RECEIPT_DUE_ERROR_REASONS, isReceiptDueError, type VoucherDueInfo, type VoucherDueArticle, type VoucherRedeemContext, voucherRedeemMaxCents, VOUCHER_ZERO_RATE_BUCKET_FROM, } from './due.js';
|
|
11
|
+
export { type ReceiptDueTip, type ReceiptDueTipRecipient, type ReceiptDueOptions, type ReceiptDueBuckets, type ReceiptDueBreakdown, type ReceiptDueErrorReason, receiptDueCents, receiptDueBreakdown, ReceiptDueError, RECEIPT_DUE_ERROR_REASONS, isReceiptDueError, type VoucherDueInfo, type VoucherDueArticle, type VoucherDueType, type VoucherRedeemContext, voucherRedeemMaxCents, VOUCHER_ZERO_RATE_BUCKET_FROM, } from './due.js';
|
package/dist/cjs/stored/draht.js
CHANGED
|
@@ -150,12 +150,17 @@ function belegRueckgabeNachAussen(beleg) {
|
|
|
150
150
|
return raus;
|
|
151
151
|
}
|
|
152
152
|
// ---- Gutschein-Eintraege am Beleg ---------------------------------------------
|
|
153
|
-
/**
|
|
153
|
+
/**
|
|
154
|
+
* Zwilling von `BELEG_GUTSCHEIN` (api-vokabular-v3): aussen -> innen. Sorte,
|
|
155
|
+
* Sortenname und Auszahlung friert der Server beim Verkauf ueber eine Sorte
|
|
156
|
+
* ein (Gutscheine Stufe 4b); die Auszahlung traegt dazu einen Wert aus dem
|
|
157
|
+
* Katalog `GUTSCHEIN_AUSZAHLUNG` (erlaubt/nie).
|
|
158
|
+
*/
|
|
154
159
|
const BELEG_GUTSCHEIN = {
|
|
155
160
|
voucherType: 'art', voucherId: 'gutscheinId', codeSuffix: 'codeEnde', amountCents: 'betragCents', vatRateBp: 'satzBp',
|
|
156
161
|
article: 'artikel', articleId: 'artikelId', quantity: 'stueck', positions: 'positionen',
|
|
157
162
|
balanceAfterCents: 'saldoNachCents', remainingQuantityAfter: 'stueckOffenNach', taxedWith: 'versteuertMit', exempt: 'befreit',
|
|
158
|
-
reason: 'grund', zeroRateBucket: 'imNullTopf',
|
|
163
|
+
reason: 'grund', zeroRateBucket: 'imNullTopf', typeId: 'sorteId', typeName: 'sorteName', payout: 'auszahlung',
|
|
159
164
|
};
|
|
160
165
|
const BELEG_GUTSCHEIN_AUSSEN = Object.fromEntries(Object.entries(BELEG_GUTSCHEIN).map(([aussen, innen]) => [innen, aussen]));
|
|
161
166
|
const GUTSCHEIN_ARTIKEL_AUSSEN = { satzBp: 'vatRateBp', preisCents: 'priceCents' };
|
|
@@ -167,6 +172,7 @@ function gutscheinEintragNachAussen(v) {
|
|
|
167
172
|
if (!(0, exports.istObjekt)(v))
|
|
168
173
|
return v;
|
|
169
174
|
const art = vokabular_js_1.KATALOGE.GUTSCHEIN_ART ?? {};
|
|
175
|
+
const auszahlung = vokabular_js_1.KATALOGE.GUTSCHEIN_AUSZAHLUNG ?? {};
|
|
170
176
|
const typNeu = typeof v.type === 'string' && (0, exports.hat)(art, v.type);
|
|
171
177
|
if (!typNeu && !Object.keys(v).some((k) => (0, exports.hat)(BELEG_GUTSCHEIN_AUSSEN, k)))
|
|
172
178
|
return v;
|
|
@@ -178,6 +184,8 @@ function gutscheinEintragNachAussen(v) {
|
|
|
178
184
|
raus.voucherType = typeof w === 'string' && (0, exports.hat)(art, w) ? art[w] : w;
|
|
179
185
|
else if (k === 'artikel')
|
|
180
186
|
raus.article = (0, exports.istObjekt)(w) ? umbenannt(w, GUTSCHEIN_ARTIKEL_AUSSEN) : w;
|
|
187
|
+
else if (k === 'auszahlung')
|
|
188
|
+
raus.payout = typeof w === 'string' && (0, exports.hat)(auszahlung, w) ? auszahlung[w] : w;
|
|
181
189
|
else
|
|
182
190
|
raus[(0, exports.hat)(BELEG_GUTSCHEIN_AUSSEN, k) ? BELEG_GUTSCHEIN_AUSSEN[k] : k] = w;
|
|
183
191
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
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 = "3088cb472f3fef3ed4ff969bf0d37d051363714096616a9263270c58266bde14";
|
|
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 {
|