@kreiseck/kasseneck-api 0.6.7
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/LICENSE +201 -0
- package/NOTICE +2 -0
- package/README.md +206 -0
- package/dist/cjs/client/api.d.ts +75 -0
- package/dist/cjs/client/api.js +40 -0
- package/dist/cjs/client/auth.d.ts +52 -0
- package/dist/cjs/client/auth.js +72 -0
- package/dist/cjs/client/cashregisters.d.ts +21 -0
- package/dist/cjs/client/cashregisters.js +36 -0
- package/dist/cjs/client/errors.d.ts +159 -0
- package/dist/cjs/client/errors.js +226 -0
- package/dist/cjs/client/index.d.ts +8 -0
- package/dist/cjs/client/index.js +44 -0
- package/dist/cjs/client/receipts.d.ts +245 -0
- package/dist/cjs/client/receipts.js +452 -0
- package/dist/cjs/client/reports.d.ts +43 -0
- package/dist/cjs/client/reports.js +73 -0
- package/dist/cjs/client/status.d.ts +43 -0
- package/dist/cjs/client/status.js +47 -0
- package/dist/cjs/client/transport.d.ts +117 -0
- package/dist/cjs/client/transport.js +312 -0
- package/dist/cjs/enums/credit-card-provider.d.ts +22 -0
- package/dist/cjs/enums/credit-card-provider.js +23 -0
- package/dist/cjs/enums/define-enum.d.ts +15 -0
- package/dist/cjs/enums/define-enum.js +16 -0
- package/dist/cjs/enums/index.d.ts +7 -0
- package/dist/cjs/enums/index.js +17 -0
- package/dist/cjs/enums/keck-payment-method.d.ts +57 -0
- package/dist/cjs/enums/keck-payment-method.js +23 -0
- package/dist/cjs/enums/receipt-type.d.ts +41 -0
- package/dist/cjs/enums/receipt-type.js +18 -0
- package/dist/cjs/enums/stripe-link-mode.d.ts +17 -0
- package/dist/cjs/enums/stripe-link-mode.js +18 -0
- package/dist/cjs/enums/vat-rate.d.ts +40 -0
- package/dist/cjs/enums/vat-rate.js +19 -0
- package/dist/cjs/enums/voucher-action.d.ts +10 -0
- package/dist/cjs/enums/voucher-action.js +11 -0
- package/dist/cjs/enums/voucher-type.d.ts +9 -0
- package/dist/cjs/enums/voucher-type.js +10 -0
- package/dist/cjs/index.d.ts +5 -0
- package/dist/cjs/index.js +97 -0
- package/dist/cjs/kasse/artikel.d.ts +83 -0
- package/dist/cjs/kasse/artikel.js +79 -0
- package/dist/cjs/kasse/client.d.ts +10 -0
- package/dist/cjs/kasse/client.js +38 -0
- package/dist/cjs/kasse/drucker.d.ts +54 -0
- package/dist/cjs/kasse/drucker.js +41 -0
- package/dist/cjs/kasse/index.d.ts +11 -0
- package/dist/cjs/kasse/index.js +38 -0
- package/dist/cjs/kasse/settings.d.ts +115 -0
- package/dist/cjs/kasse/settings.js +62 -0
- package/dist/cjs/models/cancellation.d.ts +51 -0
- package/dist/cjs/models/cancellation.js +45 -0
- package/dist/cjs/models/cashregister.d.ts +77 -0
- package/dist/cjs/models/cashregister.js +53 -0
- package/dist/cjs/models/enum-payload.d.ts +26 -0
- package/dist/cjs/models/enum-payload.js +50 -0
- package/dist/cjs/models/hobex-receipt.d.ts +63 -0
- package/dist/cjs/models/hobex-receipt.js +86 -0
- package/dist/cjs/models/index.d.ts +10 -0
- package/dist/cjs/models/index.js +46 -0
- package/dist/cjs/models/receipt-company.d.ts +71 -0
- package/dist/cjs/models/receipt-company.js +52 -0
- package/dist/cjs/models/receipt-item.d.ts +100 -0
- package/dist/cjs/models/receipt-item.js +108 -0
- package/dist/cjs/models/receipt-summary.d.ts +92 -0
- package/dist/cjs/models/receipt-summary.js +54 -0
- package/dist/cjs/models/receipt.d.ts +108 -0
- package/dist/cjs/models/receipt.js +119 -0
- package/dist/cjs/models/report-month.d.ts +32 -0
- package/dist/cjs/models/report-month.js +65 -0
- package/dist/cjs/models/stripe-url-session.d.ts +18 -0
- package/dist/cjs/models/stripe-url-session.js +20 -0
- package/dist/cjs/models/voucher.d.ts +41 -0
- package/dist/cjs/models/voucher.js +56 -0
- package/dist/cjs/money.d.ts +23 -0
- package/dist/cjs/money.js +35 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/payments/hobex.d.ts +87 -0
- package/dist/cjs/payments/hobex.js +167 -0
- package/dist/cjs/payments/index.d.ts +33 -0
- package/dist/cjs/payments/index.js +42 -0
- package/dist/cjs/payments/stripe.d.ts +61 -0
- package/dist/cjs/payments/stripe.js +157 -0
- package/dist/cjs/printing/escpos.d.ts +219 -0
- package/dist/cjs/printing/escpos.js +636 -0
- package/dist/cjs/printing/index.d.ts +3 -0
- package/dist/cjs/printing/index.js +33 -0
- package/dist/cjs/printing/printable.d.ts +27 -0
- package/dist/cjs/printing/printable.js +90 -0
- package/dist/cjs/printing/webusb.d.ts +89 -0
- package/dist/cjs/printing/webusb.js +110 -0
- package/dist/cjs/react/index.d.ts +46 -0
- package/dist/cjs/react/index.js +51 -0
- package/dist/cjs/receipt/discount.d.ts +12 -0
- package/dist/cjs/receipt/discount.js +54 -0
- package/dist/cjs/receipt/epos.d.ts +53 -0
- package/dist/cjs/receipt/epos.js +95 -0
- package/dist/cjs/receipt/grid.d.ts +47 -0
- package/dist/cjs/receipt/grid.js +122 -0
- package/dist/cjs/receipt/index.d.ts +4 -0
- package/dist/cjs/receipt/index.js +29 -0
- package/dist/cjs/receipt/layout-escpos.d.ts +35 -0
- package/dist/cjs/receipt/layout-escpos.js +67 -0
- package/dist/cjs/receipt/layout.d.ts +180 -0
- package/dist/cjs/receipt/layout.js +594 -0
- package/dist/cjs/register/index.d.ts +51 -0
- package/dist/cjs/register/index.js +61 -0
- package/dist/cjs/register/pairing.d.ts +248 -0
- package/dist/cjs/register/pairing.js +279 -0
- package/dist/cjs/register/session.d.ts +37 -0
- package/dist/cjs/register/session.js +52 -0
- package/dist/cjs/vienna-time.d.ts +23 -0
- package/dist/cjs/vienna-time.js +114 -0
- package/dist/esm/client/api.d.ts +75 -0
- package/dist/esm/client/api.js +37 -0
- package/dist/esm/client/auth.d.ts +52 -0
- package/dist/esm/client/auth.js +68 -0
- package/dist/esm/client/cashregisters.d.ts +21 -0
- package/dist/esm/client/cashregisters.js +33 -0
- package/dist/esm/client/errors.d.ts +159 -0
- package/dist/esm/client/errors.js +212 -0
- package/dist/esm/client/index.d.ts +8 -0
- package/dist/esm/client/index.js +8 -0
- package/dist/esm/client/receipts.d.ts +245 -0
- package/dist/esm/client/receipts.js +438 -0
- package/dist/esm/client/reports.d.ts +43 -0
- package/dist/esm/client/reports.js +69 -0
- package/dist/esm/client/status.d.ts +43 -0
- package/dist/esm/client/status.js +43 -0
- package/dist/esm/client/transport.d.ts +117 -0
- package/dist/esm/client/transport.js +307 -0
- package/dist/esm/enums/credit-card-provider.d.ts +22 -0
- package/dist/esm/enums/credit-card-provider.js +20 -0
- package/dist/esm/enums/define-enum.d.ts +15 -0
- package/dist/esm/enums/define-enum.js +13 -0
- package/dist/esm/enums/index.d.ts +7 -0
- package/dist/esm/enums/index.js +7 -0
- package/dist/esm/enums/keck-payment-method.d.ts +57 -0
- package/dist/esm/enums/keck-payment-method.js +20 -0
- package/dist/esm/enums/receipt-type.d.ts +41 -0
- package/dist/esm/enums/receipt-type.js +15 -0
- package/dist/esm/enums/stripe-link-mode.d.ts +17 -0
- package/dist/esm/enums/stripe-link-mode.js +15 -0
- package/dist/esm/enums/vat-rate.d.ts +40 -0
- package/dist/esm/enums/vat-rate.js +16 -0
- package/dist/esm/enums/voucher-action.d.ts +10 -0
- package/dist/esm/enums/voucher-action.js +8 -0
- package/dist/esm/enums/voucher-type.d.ts +9 -0
- package/dist/esm/enums/voucher-type.js +7 -0
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/kasse/artikel.d.ts +83 -0
- package/dist/esm/kasse/artikel.js +70 -0
- package/dist/esm/kasse/client.d.ts +10 -0
- package/dist/esm/kasse/client.js +33 -0
- package/dist/esm/kasse/drucker.d.ts +54 -0
- package/dist/esm/kasse/drucker.js +36 -0
- package/dist/esm/kasse/index.d.ts +11 -0
- package/dist/esm/kasse/index.js +13 -0
- package/dist/esm/kasse/settings.d.ts +115 -0
- package/dist/esm/kasse/settings.js +58 -0
- package/dist/esm/models/cancellation.d.ts +51 -0
- package/dist/esm/models/cancellation.js +40 -0
- package/dist/esm/models/cashregister.d.ts +77 -0
- package/dist/esm/models/cashregister.js +50 -0
- package/dist/esm/models/enum-payload.d.ts +26 -0
- package/dist/esm/models/enum-payload.js +44 -0
- package/dist/esm/models/hobex-receipt.d.ts +63 -0
- package/dist/esm/models/hobex-receipt.js +80 -0
- package/dist/esm/models/index.d.ts +10 -0
- package/dist/esm/models/index.js +10 -0
- package/dist/esm/models/receipt-company.d.ts +71 -0
- package/dist/esm/models/receipt-company.js +48 -0
- package/dist/esm/models/receipt-item.d.ts +100 -0
- package/dist/esm/models/receipt-item.js +101 -0
- package/dist/esm/models/receipt-summary.d.ts +92 -0
- package/dist/esm/models/receipt-summary.js +49 -0
- package/dist/esm/models/receipt.d.ts +108 -0
- package/dist/esm/models/receipt.js +113 -0
- package/dist/esm/models/report-month.d.ts +32 -0
- package/dist/esm/models/report-month.js +58 -0
- package/dist/esm/models/stripe-url-session.d.ts +18 -0
- package/dist/esm/models/stripe-url-session.js +16 -0
- package/dist/esm/models/voucher.d.ts +41 -0
- package/dist/esm/models/voucher.js +51 -0
- package/dist/esm/money.d.ts +23 -0
- package/dist/esm/money.js +31 -0
- package/dist/esm/payments/hobex.d.ts +87 -0
- package/dist/esm/payments/hobex.js +162 -0
- package/dist/esm/payments/index.d.ts +33 -0
- package/dist/esm/payments/index.js +33 -0
- package/dist/esm/payments/stripe.d.ts +61 -0
- package/dist/esm/payments/stripe.js +153 -0
- package/dist/esm/printing/escpos.d.ts +219 -0
- package/dist/esm/printing/escpos.js +616 -0
- package/dist/esm/printing/index.d.ts +3 -0
- package/dist/esm/printing/index.js +3 -0
- package/dist/esm/printing/printable.d.ts +27 -0
- package/dist/esm/printing/printable.js +87 -0
- package/dist/esm/printing/webusb.d.ts +89 -0
- package/dist/esm/printing/webusb.js +101 -0
- package/dist/esm/react/index.d.ts +46 -0
- package/dist/esm/react/index.js +47 -0
- package/dist/esm/receipt/discount.d.ts +12 -0
- package/dist/esm/receipt/discount.js +51 -0
- package/dist/esm/receipt/epos.d.ts +53 -0
- package/dist/esm/receipt/epos.js +86 -0
- package/dist/esm/receipt/grid.d.ts +47 -0
- package/dist/esm/receipt/grid.js +116 -0
- package/dist/esm/receipt/index.d.ts +4 -0
- package/dist/esm/receipt/index.js +4 -0
- package/dist/esm/receipt/layout-escpos.d.ts +35 -0
- package/dist/esm/receipt/layout-escpos.js +64 -0
- package/dist/esm/receipt/layout.d.ts +180 -0
- package/dist/esm/receipt/layout.js +583 -0
- package/dist/esm/register/index.d.ts +51 -0
- package/dist/esm/register/index.js +51 -0
- package/dist/esm/register/pairing.d.ts +248 -0
- package/dist/esm/register/pairing.js +270 -0
- package/dist/esm/register/session.d.ts +37 -0
- package/dist/esm/register/session.js +48 -0
- package/dist/esm/vienna-time.d.ts +23 -0
- package/dist/esm/vienna-time.js +110 -0
- package/fixtures/belege/langer-artikelname.json +43 -0
- package/fixtures/belege/null-ausfall.json +41 -0
- package/fixtures/belege/null-jahr.json +41 -0
- package/fixtures/belege/null-monat.json +41 -0
- package/fixtures/belege/null-pruef.json +41 -0
- package/fixtures/belege/null-schluss.json +41 -0
- package/fixtures/belege/null-start.json +40 -0
- package/fixtures/belege/rabattzeilen.json +61 -0
- package/fixtures/belege/signaturausfall-verkauf.json +49 -0
- package/fixtures/belege/storno-teil.json +48 -0
- package/fixtures/belege/storno-voll.json +54 -0
- package/fixtures/belege/testkasse-verkauf.json +50 -0
- package/fixtures/belege/testsignatur-verkauf.json +50 -0
- package/fixtures/belege/training.json +49 -0
- package/fixtures/belege/verkauf-bar.json +49 -0
- package/fixtures/belege/verkauf-karte.json +49 -0
- package/fixtures/belege/verkauf-kleinunternehmer.json +42 -0
- package/fixtures/erwartet/langer-artikelname.grid32.txt +25 -0
- package/fixtures/erwartet/langer-artikelname.grid48.txt +24 -0
- package/fixtures/erwartet/langer-artikelname.lines.json +216 -0
- package/fixtures/erwartet/null-ausfall.grid32.txt +28 -0
- package/fixtures/erwartet/null-ausfall.grid48.txt +25 -0
- package/fixtures/erwartet/null-ausfall.lines.json +220 -0
- package/fixtures/erwartet/null-jahr.grid32.txt +29 -0
- package/fixtures/erwartet/null-jahr.grid48.txt +25 -0
- package/fixtures/erwartet/null-jahr.lines.json +220 -0
- package/fixtures/erwartet/null-monat.grid32.txt +28 -0
- package/fixtures/erwartet/null-monat.grid48.txt +25 -0
- package/fixtures/erwartet/null-monat.lines.json +220 -0
- package/fixtures/erwartet/null-pruef.grid32.txt +28 -0
- package/fixtures/erwartet/null-pruef.grid48.txt +25 -0
- package/fixtures/erwartet/null-pruef.lines.json +220 -0
- package/fixtures/erwartet/null-schluss.grid32.txt +28 -0
- package/fixtures/erwartet/null-schluss.grid48.txt +25 -0
- package/fixtures/erwartet/null-schluss.lines.json +220 -0
- package/fixtures/erwartet/null-start.grid32.txt +28 -0
- package/fixtures/erwartet/null-start.grid48.txt +25 -0
- package/fixtures/erwartet/null-start.lines.json +220 -0
- package/fixtures/erwartet/rabattzeilen.grid32.txt +27 -0
- package/fixtures/erwartet/rabattzeilen.grid48.txt +26 -0
- package/fixtures/erwartet/rabattzeilen.lines.json +286 -0
- package/fixtures/erwartet/signaturausfall-verkauf.grid32.txt +28 -0
- package/fixtures/erwartet/signaturausfall-verkauf.grid48.txt +26 -0
- package/fixtures/erwartet/signaturausfall-verkauf.lines.json +266 -0
- package/fixtures/erwartet/storno-teil.grid32.txt +27 -0
- package/fixtures/erwartet/storno-teil.grid48.txt +26 -0
- package/fixtures/erwartet/storno-teil.lines.json +237 -0
- package/fixtures/erwartet/storno-voll.grid32.txt +29 -0
- package/fixtures/erwartet/storno-voll.grid48.txt +28 -0
- package/fixtures/erwartet/storno-voll.lines.json +277 -0
- package/fixtures/erwartet/testkasse-verkauf.grid32.txt +28 -0
- package/fixtures/erwartet/testkasse-verkauf.grid48.txt +27 -0
- package/fixtures/erwartet/testkasse-verkauf.lines.json +270 -0
- package/fixtures/erwartet/testsignatur-verkauf.grid32.txt +30 -0
- package/fixtures/erwartet/testsignatur-verkauf.grid48.txt +27 -0
- package/fixtures/erwartet/testsignatur-verkauf.lines.json +270 -0
- package/fixtures/erwartet/training.grid32.txt +33 -0
- package/fixtures/erwartet/training.grid48.txt +30 -0
- package/fixtures/erwartet/training.lines.json +277 -0
- package/fixtures/erwartet/verkauf-bar.grid32.txt +25 -0
- package/fixtures/erwartet/verkauf-bar.grid48.txt +24 -0
- package/fixtures/erwartet/verkauf-bar.lines.json +256 -0
- package/fixtures/erwartet/verkauf-karte.grid32.txt +25 -0
- package/fixtures/erwartet/verkauf-karte.grid48.txt +24 -0
- package/fixtures/erwartet/verkauf-karte.lines.json +256 -0
- package/fixtures/erwartet/verkauf-kleinunternehmer.grid32.txt +26 -0
- package/fixtures/erwartet/verkauf-kleinunternehmer.grid48.txt +25 -0
- package/fixtures/erwartet/verkauf-kleinunternehmer.lines.json +226 -0
- package/fixtures/manifest.json +107 -0
- package/package.json +135 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stripe-Zahlungslink-Sitzung — Zwilling von `StripeUrlSession` in
|
|
3
|
+
* kasseneck_api/lib/models/stripe_url_seesion.dart.
|
|
4
|
+
*/
|
|
5
|
+
export interface StripeUrlSession {
|
|
6
|
+
id: string;
|
|
7
|
+
url: string;
|
|
8
|
+
shortenUrl: string;
|
|
9
|
+
expiresAt: Date;
|
|
10
|
+
}
|
|
11
|
+
export interface StripeUrlSessionPayload {
|
|
12
|
+
id: string;
|
|
13
|
+
url: string;
|
|
14
|
+
shorten_payment_url: string;
|
|
15
|
+
expires_at: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function toStripeUrlSessionPayload(session: StripeUrlSession): StripeUrlSessionPayload;
|
|
18
|
+
export declare function fromStripeUrlSessionPayload(payload: StripeUrlSessionPayload): StripeUrlSession;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function toStripeUrlSessionPayload(session) {
|
|
2
|
+
return {
|
|
3
|
+
id: session.id,
|
|
4
|
+
url: session.url,
|
|
5
|
+
shorten_payment_url: session.shortenUrl,
|
|
6
|
+
expires_at: session.expiresAt.toISOString(),
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
export function fromStripeUrlSessionPayload(payload) {
|
|
10
|
+
return {
|
|
11
|
+
id: payload.id,
|
|
12
|
+
url: payload.url,
|
|
13
|
+
shortenUrl: payload.shorten_payment_url,
|
|
14
|
+
expiresAt: new Date(payload.expires_at),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { VoucherAction, VoucherType } from '../enums/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Gutschein — Zwilling von `KeckVoucher` in
|
|
4
|
+
* kasseneck_api/lib/models/keck_voucher.dart.
|
|
5
|
+
*
|
|
6
|
+
* `valueCents` ist der Gutscheinwert in **Cent** (exakte Integer-Arithmetik).
|
|
7
|
+
*
|
|
8
|
+
* `action`/`type` sind schon im Dart-Vorbild reine Strings (keine
|
|
9
|
+
* Zusatzfelder) — beim Lesen bleibt ein unbekannter Wert deshalb ebenfalls
|
|
10
|
+
* einfach der rohe Nutzlast-String (siehe [readEnumKey]); ob er zu den
|
|
11
|
+
* bekannten Werten gehoert, entscheidet sich erst beim Schreiben.
|
|
12
|
+
*/
|
|
13
|
+
export interface Voucher {
|
|
14
|
+
name?: string;
|
|
15
|
+
code?: string;
|
|
16
|
+
action: VoucherAction | string;
|
|
17
|
+
type: VoucherType | string;
|
|
18
|
+
valueCents?: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Nutzlast: traegt **beide** Felder, `value` (Euro) und `valueCents` (Cent).
|
|
22
|
+
* Das Backend erwartet das Euro-Feld weiterhin (Altkompatibilitaet) — die
|
|
23
|
+
* Umwandlung passiert nur hier, an dieser einen Stelle.
|
|
24
|
+
*/
|
|
25
|
+
export interface VoucherPayload {
|
|
26
|
+
name: string | null;
|
|
27
|
+
code: string | null;
|
|
28
|
+
action: string;
|
|
29
|
+
type: string;
|
|
30
|
+
value: number | null;
|
|
31
|
+
valueCents: number | null;
|
|
32
|
+
}
|
|
33
|
+
export declare function toVoucherPayload(voucher: Voucher): VoucherPayload;
|
|
34
|
+
/**
|
|
35
|
+
* Ist der Gutschein an das Backend sendbar? Zwilling von `KeckVoucher.isValid`
|
|
36
|
+
* im Flutter-Vorbild: Wert- und Promotionsgutscheine brauchen einen Wert,
|
|
37
|
+
* Promotionsgutscheine duerfen nur eingeloest (nicht verkauft) werden, und ein
|
|
38
|
+
* gesetzter Wert muss positiv sein.
|
|
39
|
+
*/
|
|
40
|
+
export declare function voucherIsValid(voucher: Voucher): boolean;
|
|
41
|
+
export declare function fromVoucherPayload(payload: VoucherPayload): Voucher;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { VoucherAction, VoucherType } from '../enums/index.js';
|
|
2
|
+
import { readEnumKey, requireEnumKey } from './enum-payload.js';
|
|
3
|
+
export function toVoucherPayload(voucher) {
|
|
4
|
+
return {
|
|
5
|
+
name: voucher.name ?? null,
|
|
6
|
+
code: voucher.code ?? null,
|
|
7
|
+
// Schreibpfad bleibt streng: action/type sehen fuer bekannte und
|
|
8
|
+
// unbekannte Werte gleich aus (reine Strings) — erst der Lookup hier
|
|
9
|
+
// entscheidet, ob geschrieben werden darf.
|
|
10
|
+
action: requireEnumKey(VoucherAction, voucher.action, 'Gutschein-Aktion'),
|
|
11
|
+
type: requireEnumKey(VoucherType, voucher.type, 'Gutscheinart'),
|
|
12
|
+
// Euro-Feld nur fuer Altbestand-Konsumenten des Backends — siehe Kommentar oben.
|
|
13
|
+
value: voucher.valueCents == null ? null : voucher.valueCents / 100,
|
|
14
|
+
valueCents: voucher.valueCents ?? null,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Ist der Gutschein an das Backend sendbar? Zwilling von `KeckVoucher.isValid`
|
|
19
|
+
* im Flutter-Vorbild: Wert- und Promotionsgutscheine brauchen einen Wert,
|
|
20
|
+
* Promotionsgutscheine duerfen nur eingeloest (nicht verkauft) werden, und ein
|
|
21
|
+
* gesetzter Wert muss positiv sein.
|
|
22
|
+
*/
|
|
23
|
+
export function voucherIsValid(voucher) {
|
|
24
|
+
if (voucher.type === VoucherType.value && voucher.valueCents == null) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
if (voucher.type === VoucherType.promo && voucher.action !== VoucherAction.redeem) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
if (voucher.type === VoucherType.promo && voucher.valueCents == null) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
if (voucher.valueCents != null && voucher.valueCents <= 0) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
export function fromVoucherPayload(payload) {
|
|
39
|
+
const valueCents = payload.valueCents != null
|
|
40
|
+
? payload.valueCents
|
|
41
|
+
: payload.value != null
|
|
42
|
+
? Math.round(payload.value * 100)
|
|
43
|
+
: undefined;
|
|
44
|
+
return {
|
|
45
|
+
name: payload.name ?? undefined,
|
|
46
|
+
code: payload.code ?? undefined,
|
|
47
|
+
action: readEnumKey(VoucherAction, payload.action),
|
|
48
|
+
type: readEnumKey(VoucherType, payload.type),
|
|
49
|
+
valueCents,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Die Grenze zwischen Euro und Cent — an genau einer Stelle.
|
|
3
|
+
*
|
|
4
|
+
* Dieses Paket rechnet ausnahmslos in ganzen Cent (siehe README). Euro treten
|
|
5
|
+
* nur dort auf, wo eine fremde Schnittstelle sie verlangt oder liefert: die
|
|
6
|
+
* Belegliste des Backends sendet `total`/`umsatz` in Euro, das Hobex-Terminal
|
|
7
|
+
* nimmt `amount`/`tip` in Euro entgegen. Beide Richtungen stehen hier, damit
|
|
8
|
+
* die Umrechnung nicht in jeder Datei erneut auftaucht — und damit die
|
|
9
|
+
* Rundungsregel nur einmal entschieden ist.
|
|
10
|
+
*/
|
|
11
|
+
/** Cent -> Euro, fuer die Schnittstellen, die Euro verlangen. */
|
|
12
|
+
export declare function centsToEuro(cents: number): number;
|
|
13
|
+
/**
|
|
14
|
+
* Euro -> ganze Cent, fuer Betraege, die aus einer fremden Antwort kommen.
|
|
15
|
+
*
|
|
16
|
+
* Unbrauchbare Werte (fehlend, `null`, keine Zahl, NaN, Unendlich) ergeben 0:
|
|
17
|
+
* eine Belegliste darf nicht daran scheitern, dass ein einzelner Betrag fehlt.
|
|
18
|
+
*
|
|
19
|
+
* Gerundet wird **von der Null weg**, nicht mit `Math.round` — das schoebe
|
|
20
|
+
* `.5` immer Richtung +unendlich, und dann heben sich ein Beleg und sein
|
|
21
|
+
* Storno im Cent nicht mehr auf (dieselbe Regel wie in receipt/layout.ts).
|
|
22
|
+
*/
|
|
23
|
+
export declare function euroToCents(euro: unknown): number;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Die Grenze zwischen Euro und Cent — an genau einer Stelle.
|
|
3
|
+
*
|
|
4
|
+
* Dieses Paket rechnet ausnahmslos in ganzen Cent (siehe README). Euro treten
|
|
5
|
+
* nur dort auf, wo eine fremde Schnittstelle sie verlangt oder liefert: die
|
|
6
|
+
* Belegliste des Backends sendet `total`/`umsatz` in Euro, das Hobex-Terminal
|
|
7
|
+
* nimmt `amount`/`tip` in Euro entgegen. Beide Richtungen stehen hier, damit
|
|
8
|
+
* die Umrechnung nicht in jeder Datei erneut auftaucht — und damit die
|
|
9
|
+
* Rundungsregel nur einmal entschieden ist.
|
|
10
|
+
*/
|
|
11
|
+
/** Cent -> Euro, fuer die Schnittstellen, die Euro verlangen. */
|
|
12
|
+
export function centsToEuro(cents) {
|
|
13
|
+
return cents / 100;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Euro -> ganze Cent, fuer Betraege, die aus einer fremden Antwort kommen.
|
|
17
|
+
*
|
|
18
|
+
* Unbrauchbare Werte (fehlend, `null`, keine Zahl, NaN, Unendlich) ergeben 0:
|
|
19
|
+
* eine Belegliste darf nicht daran scheitern, dass ein einzelner Betrag fehlt.
|
|
20
|
+
*
|
|
21
|
+
* Gerundet wird **von der Null weg**, nicht mit `Math.round` — das schoebe
|
|
22
|
+
* `.5` immer Richtung +unendlich, und dann heben sich ein Beleg und sein
|
|
23
|
+
* Storno im Cent nicht mehr auf (dieselbe Regel wie in receipt/layout.ts).
|
|
24
|
+
*/
|
|
25
|
+
export function euroToCents(euro) {
|
|
26
|
+
if (typeof euro !== 'number' || !Number.isFinite(euro)) {
|
|
27
|
+
return 0;
|
|
28
|
+
}
|
|
29
|
+
const cents = Math.round(Math.abs(euro) * 100);
|
|
30
|
+
return euro < 0 ? -cents : cents;
|
|
31
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { type HobexReceipt } from '../models/index.js';
|
|
2
|
+
import type { KasseneckTransport } from '../client/transport.js';
|
|
3
|
+
/**
|
|
4
|
+
* Cent -> Euro. **Die einzige Umrechnungsstelle dieses Moduls.** Betraege
|
|
5
|
+
* werden im ganzen Paket in Cent gefuehrt (exakte Ganzzahl-Arithmetik); die
|
|
6
|
+
* Hobex-Schnittstelle erwartet dagegen Euro als Gleitkommazahl (`amount`,
|
|
7
|
+
* `tip`), und das Backend reicht sie unveraendert an Hobex weiter. Das
|
|
8
|
+
* Gegenstueck fuer die Antwortrichtung steht in models/hobex-receipt.ts.
|
|
9
|
+
*
|
|
10
|
+
* **Geerbte Ungenauigkeit, hier nicht behebbar:** das Backend addiert die
|
|
11
|
+
* beiden Euro-Werte serverseitig (`check.params.amount + check.params.tip`,
|
|
12
|
+
* functions/payment-endpoints.js) — aus 10,10 EUR und 0,20 EUR wird dort
|
|
13
|
+
* `10.299999999999999`. Jede Rundung auf dieser Seite wuerde daran nichts
|
|
14
|
+
* aendern, weil die Addition erst danach passiert; die saubere Loesung waere
|
|
15
|
+
* ein Cent-Feld am Backend.
|
|
16
|
+
*/
|
|
17
|
+
export interface HobexPayOptions {
|
|
18
|
+
/** Kennung der Zahlung — siehe [newHobexTransactionId]. */
|
|
19
|
+
transactionId: string;
|
|
20
|
+
/** Zu belastender Betrag in **Cent** (ohne Trinkgeld). */
|
|
21
|
+
amountCents: number;
|
|
22
|
+
/** Trinkgeld in **Cent**; Hobex belastet Betrag + Trinkgeld in einem. */
|
|
23
|
+
tipCents?: number;
|
|
24
|
+
/** Freier Verwendungszweck, den Hobex mitfuehrt (z. B. Tischnummer). */
|
|
25
|
+
reference?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface HobexRefundOptions {
|
|
28
|
+
/** Kennung der zu erstattenden Zahlung. */
|
|
29
|
+
transactionId: string;
|
|
30
|
+
/** Zu erstattender Betrag in **Cent** (ohne Trinkgeld). */
|
|
31
|
+
amountCents: number;
|
|
32
|
+
/** Zu erstattendes Trinkgeld in **Cent**. */
|
|
33
|
+
tipCents?: number;
|
|
34
|
+
}
|
|
35
|
+
/** Zeit- und Zufallsquelle von [newHobexTransactionId] — fuer Tests einspeisbar. */
|
|
36
|
+
export interface HobexTransactionIdOptions {
|
|
37
|
+
/** Zeitpunkt der Kennung; ohne Angabe jetzt. */
|
|
38
|
+
now?: Date;
|
|
39
|
+
/** Zufallsquelle in `[0, 1)` wie `Math.random`; ohne Angabe `Math.random`. */
|
|
40
|
+
random?: () => number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Belastet eine Karte ueber die **Hobex-Cloud-API** und liefert den
|
|
44
|
+
* entstandenen [HobexReceipt].
|
|
45
|
+
*
|
|
46
|
+
* **Der Endpunkt heisst `hobexPayApi`** — mit Suffix; ohne ihn gibt es ihn
|
|
47
|
+
* nicht.
|
|
48
|
+
*/
|
|
49
|
+
export declare function hobexPay(rufen: KasseneckTransport, options: HobexPayOptions): Promise<HobexReceipt>;
|
|
50
|
+
/**
|
|
51
|
+
* Erstattet eine zuvor ueber die Hobex-Cloud getaetigte Zahlung. Das Backend
|
|
52
|
+
* storniert zuerst (Void, solange der Tagesabschluss aussteht) und erstattet
|
|
53
|
+
* erst danach.
|
|
54
|
+
*
|
|
55
|
+
* **Ohne Rueckgabewert, mit Absicht.** Das Vorbild liefert
|
|
56
|
+
* `resJson['status'] == 'success'`; in diesem Paket wirft die Fehlerhuelle
|
|
57
|
+
* schon im Transport, sobald der Status nicht ausdruecklich Erfolg ist. Ein
|
|
58
|
+
* Wahrheitswert waere hier also immer `true` — eine Luege ueber den
|
|
59
|
+
* Informationsgehalt, an der ein Aufrufer ein `if` aufhaengt, das nie greift.
|
|
60
|
+
* Misserfolg kommt als geworfener Fehler.
|
|
61
|
+
*
|
|
62
|
+
* **Der Endpunkt heisst `hobexRefundApi`** — mit Suffix.
|
|
63
|
+
*/
|
|
64
|
+
export declare function hobexRefund(rufen: KasseneckTransport, options: HobexRefundOptions): Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
* Erzeugt eine neue Hobex-Transaktionskennung: 19 Ziffern aus Zeitanteil und
|
|
67
|
+
* Zufall (Zwilling von `newHobexTransactionId` im Vorbild, Zeile 522).
|
|
68
|
+
*
|
|
69
|
+
* Zwei bewusste Abweichungen:
|
|
70
|
+
*
|
|
71
|
+
* 1. **Wiener Wanduhrzeit statt Geraetezeit.** Das Vorbild nimmt
|
|
72
|
+
* `DateTime.now()` in der Zeitzone des Geraets; damit haetten zwei Kassen
|
|
73
|
+
* desselben Betriebs in verschiedenen Zeitzonen Kennungen, die sich um
|
|
74
|
+
* Stunden unterscheiden, und der Tageswechsel in der Kennung faende nicht
|
|
75
|
+
* zum Geschaeftstag statt. Fachlich ist Wien die Zeitzone (siehe
|
|
76
|
+
* vienna-time.ts) — und eine Browser-Kasse laeuft in der Zeitzone des Gasts,
|
|
77
|
+
* nicht des Betriebs.
|
|
78
|
+
* 2. **Millisekunden statt Mikrosekunden.** JavaScript hat keine
|
|
79
|
+
* Mikrosekunden-Uhr. Das Vorbild fuellt mit sechs Bruchteilsstellen auf und
|
|
80
|
+
* haengt zwei Zufallsziffern an, von denen die Laengenbegrenzung eine wieder
|
|
81
|
+
* abschneidet; hier stehen drei Bruchteilsstellen und vier Zufallsziffern.
|
|
82
|
+
* Laenge und Form (nur Ziffern, 19 Stellen, `JJMMTThhmmss` voran) bleiben
|
|
83
|
+
* gleich.
|
|
84
|
+
*
|
|
85
|
+
* Zeit- und Zufallsquelle sind einspeisbar, damit die Kennung pruefbar ist.
|
|
86
|
+
*/
|
|
87
|
+
export declare function newHobexTransactionId(options?: HobexTransactionIdOptions): string;
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { fromHobexReceiptPayload } from '../models/index.js';
|
|
2
|
+
import { KasseneckValidationError } from '../client/errors.js';
|
|
3
|
+
import { toViennaWallClock } from '../vienna-time.js';
|
|
4
|
+
import { centsToEuro } from '../money.js';
|
|
5
|
+
/**
|
|
6
|
+
* Hobex-Kartenzahlung ueber die **Cloud-API** — Zwilling der Hobex-Aufrufe in
|
|
7
|
+
* kasseneck_api/lib/kasseneck_api.dart (Zeilen 491-526).
|
|
8
|
+
*
|
|
9
|
+
* Der Ablauf hat zwei Schritte: eine Kennung erzeugen ([newHobexTransactionId])
|
|
10
|
+
* und damit belasten ([hobexPay]). Die Kennung ist der Faden, an dem das
|
|
11
|
+
* Backend eine haengende Zahlung wiederfindet (`getHobexStatusWithTimeout`,
|
|
12
|
+
* functions/payment-endpoints.js) — sie ist deshalb kein Schmuck, sondern die
|
|
13
|
+
* Absicherung gegen eine doppelte Belastung.
|
|
14
|
+
*
|
|
15
|
+
* **Nur der Cloud-Weg ist hier drin, und das bleibt so.** Hobex **HPS** ist ein
|
|
16
|
+
* physisches Terminal, mit dem die Kasse **lokal ueber TCP** spricht; **myPOS**
|
|
17
|
+
* und **SumUp** sind **Android-SDKs**. Ein Browser hat weder rohe TCP-Sockets
|
|
18
|
+
* noch eine Android-Laufzeit — das ist keine fehlende Umsetzung und kein
|
|
19
|
+
* Buendler-Problem, sondern eine Grenze der Umgebung. Wer diese drei Wege
|
|
20
|
+
* braucht, braucht die Flutter-App, nicht dieses Paket.
|
|
21
|
+
*
|
|
22
|
+
* **Kassen-Benutzer-Weg (`registerUserAuth`, Browser-Kasse):** Keiner der
|
|
23
|
+
* beiden Endpunkte dieser Datei setzt `allowRegisterUser`; beide laufen nur
|
|
24
|
+
* mit `apiKeyAuth`. Ausgefuehrt steht das in payments/index.ts — an einer
|
|
25
|
+
* Stelle statt an dreien.
|
|
26
|
+
*/
|
|
27
|
+
/** Endpunktnamen aus dem Vorbild — beide mit Suffix `Api`. */
|
|
28
|
+
const ENDPUNKT_PAY = 'hobexPayApi';
|
|
29
|
+
const ENDPUNKT_REFUND = 'hobexRefundApi';
|
|
30
|
+
/**
|
|
31
|
+
* Belastet eine Karte ueber die **Hobex-Cloud-API** und liefert den
|
|
32
|
+
* entstandenen [HobexReceipt].
|
|
33
|
+
*
|
|
34
|
+
* **Der Endpunkt heisst `hobexPayApi`** — mit Suffix; ohne ihn gibt es ihn
|
|
35
|
+
* nicht.
|
|
36
|
+
*/
|
|
37
|
+
export async function hobexPay(rufen, options) {
|
|
38
|
+
const params = zahlungsNutzlast(ENDPUNKT_PAY, options);
|
|
39
|
+
// `reference` steht im Vorbild **unbedingt** in der Nutzlast: ohne Angabe
|
|
40
|
+
// geht sie als null raus, nicht gar nicht. Der Transport wirft nur
|
|
41
|
+
// `undefined` weg, `null` bleibt erhalten — genau diese Unterscheidung.
|
|
42
|
+
params['reference'] = options.reference ?? null;
|
|
43
|
+
return belegAusNutzlast(await rufen(ENDPUNKT_PAY, params));
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Erstattet eine zuvor ueber die Hobex-Cloud getaetigte Zahlung. Das Backend
|
|
47
|
+
* storniert zuerst (Void, solange der Tagesabschluss aussteht) und erstattet
|
|
48
|
+
* erst danach.
|
|
49
|
+
*
|
|
50
|
+
* **Ohne Rueckgabewert, mit Absicht.** Das Vorbild liefert
|
|
51
|
+
* `resJson['status'] == 'success'`; in diesem Paket wirft die Fehlerhuelle
|
|
52
|
+
* schon im Transport, sobald der Status nicht ausdruecklich Erfolg ist. Ein
|
|
53
|
+
* Wahrheitswert waere hier also immer `true` — eine Luege ueber den
|
|
54
|
+
* Informationsgehalt, an der ein Aufrufer ein `if` aufhaengt, das nie greift.
|
|
55
|
+
* Misserfolg kommt als geworfener Fehler.
|
|
56
|
+
*
|
|
57
|
+
* **Der Endpunkt heisst `hobexRefundApi`** — mit Suffix.
|
|
58
|
+
*/
|
|
59
|
+
export async function hobexRefund(rufen, options) {
|
|
60
|
+
// Anders als die Zahlung sendet der Refund im Vorbild **keine** reference.
|
|
61
|
+
await rufen(ENDPUNKT_REFUND, zahlungsNutzlast(ENDPUNKT_REFUND, options));
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Erzeugt eine neue Hobex-Transaktionskennung: 19 Ziffern aus Zeitanteil und
|
|
65
|
+
* Zufall (Zwilling von `newHobexTransactionId` im Vorbild, Zeile 522).
|
|
66
|
+
*
|
|
67
|
+
* Zwei bewusste Abweichungen:
|
|
68
|
+
*
|
|
69
|
+
* 1. **Wiener Wanduhrzeit statt Geraetezeit.** Das Vorbild nimmt
|
|
70
|
+
* `DateTime.now()` in der Zeitzone des Geraets; damit haetten zwei Kassen
|
|
71
|
+
* desselben Betriebs in verschiedenen Zeitzonen Kennungen, die sich um
|
|
72
|
+
* Stunden unterscheiden, und der Tageswechsel in der Kennung faende nicht
|
|
73
|
+
* zum Geschaeftstag statt. Fachlich ist Wien die Zeitzone (siehe
|
|
74
|
+
* vienna-time.ts) — und eine Browser-Kasse laeuft in der Zeitzone des Gasts,
|
|
75
|
+
* nicht des Betriebs.
|
|
76
|
+
* 2. **Millisekunden statt Mikrosekunden.** JavaScript hat keine
|
|
77
|
+
* Mikrosekunden-Uhr. Das Vorbild fuellt mit sechs Bruchteilsstellen auf und
|
|
78
|
+
* haengt zwei Zufallsziffern an, von denen die Laengenbegrenzung eine wieder
|
|
79
|
+
* abschneidet; hier stehen drei Bruchteilsstellen und vier Zufallsziffern.
|
|
80
|
+
* Laenge und Form (nur Ziffern, 19 Stellen, `JJMMTThhmmss` voran) bleiben
|
|
81
|
+
* gleich.
|
|
82
|
+
*
|
|
83
|
+
* Zeit- und Zufallsquelle sind einspeisbar, damit die Kennung pruefbar ist.
|
|
84
|
+
*/
|
|
85
|
+
export function newHobexTransactionId(options = {}) {
|
|
86
|
+
const wand = toViennaWallClock(options.now ?? new Date());
|
|
87
|
+
const zufall = options.random ?? Math.random;
|
|
88
|
+
const zeitanteil = zweistellig(wand.year % 100) +
|
|
89
|
+
zweistellig(wand.month) +
|
|
90
|
+
zweistellig(wand.day) +
|
|
91
|
+
zweistellig(wand.hour) +
|
|
92
|
+
zweistellig(wand.minute) +
|
|
93
|
+
zweistellig(wand.second) +
|
|
94
|
+
String(wand.millisecond).padStart(3, '0');
|
|
95
|
+
// Vier Ziffern, immer vierstellig: eine kuerzere Zahl wuerde die Kennung
|
|
96
|
+
// verkuerzen und damit ihre Form verlassen. Der Wert wird auf [0, 1)
|
|
97
|
+
// begrenzt — eine fremde Zufallsquelle koennte 1 liefern.
|
|
98
|
+
const zufallsanteil = String(Math.floor(begrenzt(zufall()) * 10_000)).padStart(4, '0');
|
|
99
|
+
return zeitanteil + zufallsanteil;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Gemeinsame Nutzlast beider Hobex-Aufrufe: Kennung und die beiden Betraege in
|
|
103
|
+
* Euro. Prueft, bevor irgendetwas rausgeht — hier bewegt sich Geld auf einer
|
|
104
|
+
* fremden Karte, und ein NaN-Betrag oder eine leere Kennung ist an einem
|
|
105
|
+
* Zahlungsterminal nichts, was man dem Backend zum Ausprobieren schickt.
|
|
106
|
+
*/
|
|
107
|
+
function zahlungsNutzlast(functionName, options) {
|
|
108
|
+
if (typeof options.transactionId !== 'string' || !options.transactionId.trim()) {
|
|
109
|
+
throw eingabefehler(functionName, 'transactionId fehlt');
|
|
110
|
+
}
|
|
111
|
+
const amountCents = gepruefterBetrag(functionName, options.amountCents, 'amountCents', 1);
|
|
112
|
+
const tipCents = gepruefterBetrag(functionName, options.tipCents ?? 0, 'tipCents', 0);
|
|
113
|
+
return {
|
|
114
|
+
transactionId: options.transactionId,
|
|
115
|
+
// Euro-Umrechnung genau hier, an der Hobex-Grenze.
|
|
116
|
+
amount: centsToEuro(amountCents),
|
|
117
|
+
tip: centsToEuro(tipCents),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Ganzzahliger Cent-Betrag ab [mindestens]. `Number.isInteger` faengt NaN,
|
|
122
|
+
* Unendlich und Bruchteils-Cent in einem — ein halber Cent ergibt bei der
|
|
123
|
+
* Euro-Umrechnung eine dritte Nachkommastelle, die Hobex nicht kennt.
|
|
124
|
+
*/
|
|
125
|
+
function gepruefterBetrag(functionName, cents, feld, mindestens) {
|
|
126
|
+
if (!Number.isInteger(cents)) {
|
|
127
|
+
throw eingabefehler(functionName, `${feld} muss eine ganze Zahl in Cent sein.`);
|
|
128
|
+
}
|
|
129
|
+
if (cents < mindestens) {
|
|
130
|
+
throw eingabefehler(functionName, `${feld} muss mindestens ${mindestens} Cent betragen.`);
|
|
131
|
+
}
|
|
132
|
+
return cents;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Hobex-Beleg aus der Antwort lesen. Geprueft werden die beiden Felder, ohne
|
|
136
|
+
* die der Beleg nichts wert ist: die Kennung der Zahlung und der Zeitstempel
|
|
137
|
+
* (an ihm scheitert die Lesart des Modells sonst mit einem nackten TypeError,
|
|
138
|
+
* weil sie ihn zerlegt). Die uebrigen Felder bleiben so tolerant wie im
|
|
139
|
+
* Vorbild — ein Beleg, dem Hobex den Kartenaussteller schuldig bleibt, ist
|
|
140
|
+
* trotzdem eine erfolgte Zahlung.
|
|
141
|
+
*/
|
|
142
|
+
function belegAusNutzlast(daten) {
|
|
143
|
+
const roh = daten;
|
|
144
|
+
if (roh == null ||
|
|
145
|
+
typeof roh !== 'object' ||
|
|
146
|
+
typeof roh.transactionId !== 'string' ||
|
|
147
|
+
typeof roh.transactionDate !== 'string') {
|
|
148
|
+
throw antwortfehler(ENDPUNKT_PAY, 'Antwort enthaelt keinen Hobex-Beleg');
|
|
149
|
+
}
|
|
150
|
+
return fromHobexReceiptPayload(roh);
|
|
151
|
+
}
|
|
152
|
+
const zweistellig = (wert) => String(wert).padStart(2, '0');
|
|
153
|
+
/** Auf `[0, 1)` begrenzen — eine fremde Zufallsquelle haelt sich nicht daran. */
|
|
154
|
+
const begrenzt = (wert) => (Number.isFinite(wert) ? Math.min(Math.max(wert, 0), 0.999_999_9) : 0);
|
|
155
|
+
/** Fehler in der Eingabe des Aufrufers — es geht keine Anfrage raus. */
|
|
156
|
+
function eingabefehler(functionName, grund) {
|
|
157
|
+
return new KasseneckValidationError(functionName, grund, 'request');
|
|
158
|
+
}
|
|
159
|
+
/** Die Antwort meldete Erfolg, trug aber nicht, was der Aufruf zusagt. */
|
|
160
|
+
function antwortfehler(functionName, grund) {
|
|
161
|
+
return new KasseneckValidationError(functionName, grund, 'response');
|
|
162
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unterpfad `@kreiseck/kasseneck-api/payments` — die Zahlungswege, die ein
|
|
3
|
+
* Browser oder ein Node-Prozess wirklich gehen kann: **Stripe-Zahlungslinks**
|
|
4
|
+
* (Fernzahlung per Link/QR-Code) und die **Hobex-Cloud-API** (Kartenzahlung
|
|
5
|
+
* ueber ein bei Hobex registriertes Terminal, gesteuert ueber das Netz).
|
|
6
|
+
*
|
|
7
|
+
* **Was hier bewusst fehlt — und warum es auch nicht nachgeruestet wird:**
|
|
8
|
+
*
|
|
9
|
+
* - **Hobex HPS** spricht **lokal ueber TCP** mit einem angeschlossenen
|
|
10
|
+
* Terminal (roher Socket auf eine Geraete-IP im selben Netz).
|
|
11
|
+
* - **myPOS** und **SumUp** sind **Android-SDKs**; sie laufen als
|
|
12
|
+
* Bibliothek in einer Android-App und reden ueber Bluetooth bzw. das
|
|
13
|
+
* Hersteller-Geraet mit dem Terminal.
|
|
14
|
+
*
|
|
15
|
+
* Ein Browser hat weder rohe TCP-Sockets noch eine Android-Laufzeit. Das ist
|
|
16
|
+
* keine Luecke in diesem Paket und auch nichts, was ein anderer Buendler,
|
|
17
|
+
* ein Polyfill oder eine WebAssembly-Schicht aufloest — es ist eine Grenze der
|
|
18
|
+
* Umgebung. Diese drei Wege gibt es im Flutter-Paket `kasseneck_api`, und dort
|
|
19
|
+
* bleiben sie.
|
|
20
|
+
*
|
|
21
|
+
* **Kassen-Benutzer-Weg (`registerUserAuth`, Browser-Kasse):** **Keiner** der
|
|
22
|
+
* vier Zahlungs-Endpunkte setzt `allowRegisterUser`; sie laufen alle ueber
|
|
23
|
+
* `checkRequest(req, 'user', …)` und damit nur mit `apiKeyAuth`. Dieses Paket
|
|
24
|
+
* bildet das **nicht** nach — wer darf, entscheidet allein das Backend. Der
|
|
25
|
+
* Hinweis steht **hier** und gilt fuer beide Dateien dieses Unterpfads.
|
|
26
|
+
*
|
|
27
|
+
* Welche **anderen** Endpunkte den Weg offen haben, steht bewusst nirgends in
|
|
28
|
+
* diesem Paket: eine abgeschriebene Liste veraltet still, und sie hat hier
|
|
29
|
+
* nichts zu entscheiden.
|
|
30
|
+
*/
|
|
31
|
+
export { StripeLinkMode, type StripeLinkModeKey } from '../enums/index.js';
|
|
32
|
+
export { type CreateStripeLinkOptions, type StripeCaptureResult, createStripeLink, stripeCaptureIntent, } from './stripe.js';
|
|
33
|
+
export { type HobexPayOptions, type HobexRefundOptions, type HobexTransactionIdOptions, hobexPay, hobexRefund, newHobexTransactionId, } from './hobex.js';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unterpfad `@kreiseck/kasseneck-api/payments` — die Zahlungswege, die ein
|
|
3
|
+
* Browser oder ein Node-Prozess wirklich gehen kann: **Stripe-Zahlungslinks**
|
|
4
|
+
* (Fernzahlung per Link/QR-Code) und die **Hobex-Cloud-API** (Kartenzahlung
|
|
5
|
+
* ueber ein bei Hobex registriertes Terminal, gesteuert ueber das Netz).
|
|
6
|
+
*
|
|
7
|
+
* **Was hier bewusst fehlt — und warum es auch nicht nachgeruestet wird:**
|
|
8
|
+
*
|
|
9
|
+
* - **Hobex HPS** spricht **lokal ueber TCP** mit einem angeschlossenen
|
|
10
|
+
* Terminal (roher Socket auf eine Geraete-IP im selben Netz).
|
|
11
|
+
* - **myPOS** und **SumUp** sind **Android-SDKs**; sie laufen als
|
|
12
|
+
* Bibliothek in einer Android-App und reden ueber Bluetooth bzw. das
|
|
13
|
+
* Hersteller-Geraet mit dem Terminal.
|
|
14
|
+
*
|
|
15
|
+
* Ein Browser hat weder rohe TCP-Sockets noch eine Android-Laufzeit. Das ist
|
|
16
|
+
* keine Luecke in diesem Paket und auch nichts, was ein anderer Buendler,
|
|
17
|
+
* ein Polyfill oder eine WebAssembly-Schicht aufloest — es ist eine Grenze der
|
|
18
|
+
* Umgebung. Diese drei Wege gibt es im Flutter-Paket `kasseneck_api`, und dort
|
|
19
|
+
* bleiben sie.
|
|
20
|
+
*
|
|
21
|
+
* **Kassen-Benutzer-Weg (`registerUserAuth`, Browser-Kasse):** **Keiner** der
|
|
22
|
+
* vier Zahlungs-Endpunkte setzt `allowRegisterUser`; sie laufen alle ueber
|
|
23
|
+
* `checkRequest(req, 'user', …)` und damit nur mit `apiKeyAuth`. Dieses Paket
|
|
24
|
+
* bildet das **nicht** nach — wer darf, entscheidet allein das Backend. Der
|
|
25
|
+
* Hinweis steht **hier** und gilt fuer beide Dateien dieses Unterpfads.
|
|
26
|
+
*
|
|
27
|
+
* Welche **anderen** Endpunkte den Weg offen haben, steht bewusst nirgends in
|
|
28
|
+
* diesem Paket: eine abgeschriebene Liste veraltet still, und sie hat hier
|
|
29
|
+
* nichts zu entscheiden.
|
|
30
|
+
*/
|
|
31
|
+
export { StripeLinkMode } from '../enums/index.js';
|
|
32
|
+
export { createStripeLink, stripeCaptureIntent, } from './stripe.js';
|
|
33
|
+
export { hobexPay, hobexRefund, newHobexTransactionId, } from './hobex.js';
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { StripeLinkMode, type StripeLinkModeKey } from '../enums/index.js';
|
|
2
|
+
import { type ReceiptItem, type StripeUrlSession } from '../models/index.js';
|
|
3
|
+
import type { KasseneckTransport } from '../client/transport.js';
|
|
4
|
+
export interface CreateStripeLinkOptions {
|
|
5
|
+
/** Positionen des Zahlungslinks; mindestens eine, alle gueltig. */
|
|
6
|
+
items: ReceiptItem[];
|
|
7
|
+
/** Soll das Backend nach bezahltem Link selbsttaetig einen Beleg erzeugen? */
|
|
8
|
+
createReceiptAfterPayment: boolean;
|
|
9
|
+
/** Sofort einziehen (`payment`) oder nur reservieren (`authorization`). */
|
|
10
|
+
mode: StripeLinkMode | StripeLinkModeKey;
|
|
11
|
+
/** Eigener Bezeichner fuer den Zahlungs-Webhook des Aufrufers. */
|
|
12
|
+
webhookId?: string;
|
|
13
|
+
/** Telefonnummer des Gasts (landet in den Stripe-Metadaten). */
|
|
14
|
+
customerPhone?: string;
|
|
15
|
+
/** E-Mail des Gasts (Stripe schickt die Zahlungsbestaetigung dorthin). */
|
|
16
|
+
customerEmail?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Ergebnis von [stripeCaptureIntent] — das eingezogene Zahlungsversprechen
|
|
20
|
+
* (Stripe PaymentIntent), **nicht** noch einmal die Zahlungslink-Sitzung.
|
|
21
|
+
*
|
|
22
|
+
* Das ist eine bewusste Abweichung vom Dart-Vorbild: dort steht
|
|
23
|
+
* `StripeUrlSession.fromJson(resJson['data'])`, das Backend antwortet an dieser
|
|
24
|
+
* Stelle aber mit `{id, status, amount_received, currency}` (successResponse in
|
|
25
|
+
* functions/payment-endpoints.js). Weder `url` noch `shorten_payment_url` noch
|
|
26
|
+
* `expires_at` sind darin — die Sitzungs-Lesart kann hier gar nicht gelingen.
|
|
27
|
+
*/
|
|
28
|
+
export interface StripeCaptureResult {
|
|
29
|
+
/** Bezeichner des PaymentIntent (`pi_…`), nicht der der Sitzung (`cs_…`). */
|
|
30
|
+
id: string;
|
|
31
|
+
/** Stripe-Status des Einzugs, z. B. `succeeded`. */
|
|
32
|
+
status: string;
|
|
33
|
+
/**
|
|
34
|
+
* Tatsaechlich eingezogener Betrag in Cent. Stripe fuehrt Betraege in der
|
|
35
|
+
* kleinsten Waehrungseinheit; der Name unterstellt damit eine
|
|
36
|
+
* zweistellige Waehrung. Fuer diese Anlage stimmt das — das Backend legt
|
|
37
|
+
* `currency: 'eur'` fest (functions/payment-endpoints.js). Bei einer
|
|
38
|
+
* nullstelligen Waehrung (JPY) waere „Cent" der falsche Name; dann gehoert
|
|
39
|
+
* die Einheit aus `currency` abgeleitet und nicht in den Feldnamen.
|
|
40
|
+
*/
|
|
41
|
+
amountReceivedCents: number;
|
|
42
|
+
/** Waehrungscode, wie Stripe ihn fuehrt (klein geschrieben, z. B. `eur`). */
|
|
43
|
+
currency: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Erzeugt einen Stripe-Zahlungslink fuer [items] (Fernzahlung: Link per
|
|
47
|
+
* Nachricht, QR-Code oder Kurzlink).
|
|
48
|
+
*
|
|
49
|
+
* **Der Endpunkt heisst `createPaymentLinkStripe`**, nicht wie diese Funktion —
|
|
50
|
+
* Methodenname und Endpunktname fallen wie schon beim Monatsbericht
|
|
51
|
+
* auseinander (siehe client/reports.ts).
|
|
52
|
+
*/
|
|
53
|
+
export declare function createStripeLink(rufen: KasseneckTransport, options: CreateStripeLinkOptions): Promise<StripeUrlSession>;
|
|
54
|
+
/**
|
|
55
|
+
* Zieht die zuvor nur reservierte Zahlung einer `authorization`-Sitzung ein.
|
|
56
|
+
*
|
|
57
|
+
* **Der Parameter heisst `stripe_sessions_id`** — mit "sessions" im Plural, so
|
|
58
|
+
* das Vorbild und so das Backend. Der naheliegende Singular waere ein fehlender
|
|
59
|
+
* Pflichtparameter.
|
|
60
|
+
*/
|
|
61
|
+
export declare function stripeCaptureIntent(rufen: KasseneckTransport, stripeSessionId: string): Promise<StripeCaptureResult>;
|