@kreiseck/kasseneck-api 0.31.0 → 1.0.0-rc.2
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 +317 -0
- package/README.de.md +11 -7
- package/README.md +509 -126
- package/dist/cjs/client/api.d.ts +7 -6
- package/dist/cjs/client/api.js +2 -2
- package/dist/cjs/client/aufrufe.d.ts +29 -5
- package/dist/cjs/client/aufrufe.js +114 -2
- package/dist/cjs/client/auth.d.ts +2 -0
- package/dist/cjs/client/auth.js +17 -1
- package/dist/cjs/client/cashregisters.d.ts +1 -1
- package/dist/cjs/client/cashregisters.js +2 -2
- package/dist/cjs/client/errors.d.ts +94 -19
- package/dist/cjs/client/errors.js +132 -28
- package/dist/cjs/client/fehlercodes.d.ts +9 -0
- package/dist/cjs/client/fehlercodes.js +36 -0
- package/dist/cjs/client/index.d.ts +5 -5
- package/dist/cjs/client/index.js +11 -3
- package/dist/cjs/client/receipts.d.ts +131 -124
- package/dist/cjs/client/receipts.js +196 -137
- package/dist/cjs/client/reports.d.ts +26 -4
- package/dist/cjs/client/reports.js +37 -4
- package/dist/cjs/client/status.d.ts +3 -3
- package/dist/cjs/client/status.js +7 -7
- package/dist/cjs/client/transport.d.ts +56 -4
- package/dist/cjs/client/transport.js +234 -25
- package/dist/cjs/enums/vat-rate.d.ts +2 -2
- package/dist/cjs/enums/vat-rate.js +1 -1
- package/dist/cjs/index.d.ts +4 -3
- package/dist/cjs/index.js +42 -13
- package/dist/{esm/rechnung → cjs/invoice}/api.d.ts +18 -17
- package/dist/cjs/{rechnung → invoice}/api.js +6 -6
- package/dist/{esm/rechnung → cjs/invoice}/auth.d.ts +2 -2
- package/dist/cjs/{rechnung → invoice}/auth.js +5 -5
- package/dist/{esm/rechnung/rechnen.d.ts → cjs/invoice/calc.d.ts} +27 -27
- package/dist/cjs/{rechnung/rechnen.js → invoice/calc.js} +54 -54
- package/dist/{esm/rechnung → cjs/invoice}/endpunkte.d.ts +23 -21
- package/dist/cjs/{rechnung → invoice}/endpunkte.js +52 -42
- package/dist/cjs/invoice/fehler.d.ts +31 -0
- package/dist/cjs/invoice/fehler.js +39 -0
- package/dist/cjs/invoice/index.d.ts +21 -0
- package/dist/cjs/invoice/index.js +86 -0
- package/dist/cjs/{rechnung → invoice}/summen.d.ts +12 -12
- package/dist/cjs/{rechnung → invoice}/summen.js +14 -14
- package/dist/cjs/invoice/texte.d.ts +224 -0
- package/dist/cjs/invoice/texte.js +425 -0
- package/dist/{esm/rechnung → cjs/invoice}/typen.d.ts +32 -11
- package/dist/cjs/{rechnung → invoice}/vertrag.d.ts +97 -71
- package/dist/cjs/{rechnung → invoice}/vertrag.js +144 -82
- package/dist/cjs/models/cancellation.d.ts +43 -24
- package/dist/cjs/models/cancellation.js +94 -46
- package/dist/cjs/models/hobex-receipt.d.ts +3 -3
- package/dist/cjs/models/hobex-receipt.js +35 -35
- package/dist/cjs/models/index.d.ts +6 -5
- package/dist/cjs/models/index.js +22 -2
- package/dist/cjs/models/payment-errors.d.ts +32 -15
- package/dist/cjs/models/payment-errors.js +80 -32
- package/dist/cjs/models/receipt-company.d.ts +6 -5
- package/dist/cjs/models/receipt-company.js +4 -4
- package/dist/cjs/models/receipt-email.d.ts +32 -18
- package/dist/cjs/models/receipt-email.js +69 -24
- package/dist/cjs/models/receipt-errors.d.ts +39 -0
- package/dist/cjs/models/receipt-errors.js +94 -0
- package/dist/cjs/models/receipt-item.d.ts +9 -1
- package/dist/cjs/models/receipt-item.js +3 -0
- package/dist/cjs/models/receipt-summary.d.ts +10 -4
- package/dist/cjs/models/receipt-summary.js +10 -4
- package/dist/cjs/models/receipt.d.ts +31 -2
- package/dist/cjs/models/receipt.js +12 -1
- package/dist/cjs/models/voucher.d.ts +7 -6
- package/dist/cjs/models/voucher.js +2 -7
- package/dist/cjs/partner/ablauf.d.ts +10 -10
- package/dist/cjs/partner/ablauf.js +29 -29
- package/dist/cjs/partner/api.d.ts +26 -23
- package/dist/cjs/partner/api.js +11 -13
- package/dist/cjs/partner/auth.d.ts +1 -1
- package/dist/cjs/partner/auth.js +2 -2
- package/dist/cjs/partner/betrieb.d.ts +7 -7
- package/dist/cjs/partner/betrieb.js +10 -10
- package/dist/cjs/partner/endpunkte.d.ts +27 -14
- package/dist/cjs/partner/endpunkte.js +80 -39
- package/dist/cjs/partner/fehler.d.ts +60 -30
- package/dist/cjs/partner/fehler.js +99 -43
- package/dist/cjs/partner/index.d.ts +13 -12
- package/dist/cjs/partner/index.js +35 -22
- package/dist/cjs/partner/secret.d.ts +3 -3
- package/dist/cjs/partner/secret.js +6 -6
- package/dist/cjs/partner/typen.d.ts +129 -71
- package/dist/cjs/partner/typen.js +76 -3
- package/dist/cjs/partner/webhook-signatur.d.ts +2 -2
- package/dist/cjs/partner/webhook-signatur.js +12 -12
- package/dist/cjs/partner/webhooks.d.ts +60 -32
- package/dist/cjs/partner/webhooks.js +40 -34
- package/dist/cjs/payments/hobex.d.ts +11 -3
- package/dist/cjs/payments/hobex.js +17 -5
- package/dist/cjs/payments/stripe.d.ts +5 -2
- package/dist/cjs/payments/stripe.js +10 -5
- package/dist/cjs/pos/artikel.d.ts +90 -0
- package/dist/cjs/pos/artikel.js +89 -0
- package/dist/cjs/pos/client.d.ts +27 -0
- package/dist/cjs/pos/client.js +144 -0
- package/dist/cjs/pos/drucker.d.ts +86 -0
- package/dist/cjs/pos/drucker.js +78 -0
- package/dist/cjs/pos/errors.d.ts +36 -0
- package/dist/cjs/pos/errors.js +95 -0
- package/dist/cjs/pos/index.d.ts +15 -0
- package/dist/cjs/pos/index.js +102 -0
- package/dist/cjs/pos/settings.d.ts +313 -0
- package/dist/cjs/pos/settings.js +376 -0
- package/dist/cjs/pos/texte.d.ts +883 -0
- package/dist/cjs/pos/texte.js +489 -0
- package/dist/cjs/{kasse → pos}/trinkgeld.d.ts +1 -1
- package/dist/cjs/{kasse → pos}/trinkgeld.js +2 -2
- package/dist/cjs/printing/escpos.d.ts +29 -29
- package/dist/cjs/printing/escpos.js +61 -61
- package/dist/cjs/printing/index.d.ts +2 -2
- package/dist/cjs/printing/index.js +17 -17
- package/dist/cjs/printing/qr-groesse.d.ts +38 -38
- package/dist/cjs/printing/qr-groesse.js +47 -47
- package/dist/cjs/printing/webusb.d.ts +2 -2
- package/dist/cjs/printing/webusb.js +4 -4
- package/dist/cjs/react/index.d.ts +21 -21
- package/dist/cjs/react/index.js +40 -30
- package/dist/cjs/receipt/bild.d.ts +4 -4
- package/dist/cjs/receipt/bild.js +11 -11
- package/dist/cjs/receipt/blatt.d.ts +46 -46
- package/dist/cjs/receipt/blatt.js +59 -59
- package/dist/cjs/receipt/discount.d.ts +1 -1
- package/dist/cjs/receipt/discount.js +8 -8
- package/dist/cjs/receipt/due.d.ts +86 -0
- package/dist/cjs/receipt/due.js +261 -0
- package/dist/cjs/receipt/epos.d.ts +22 -22
- package/dist/cjs/receipt/epos.js +45 -45
- package/dist/cjs/receipt/grid.d.ts +10 -10
- package/dist/cjs/receipt/grid.js +20 -20
- package/dist/cjs/receipt/index.d.ts +9 -8
- package/dist/cjs/receipt/index.js +26 -23
- package/dist/cjs/receipt/layout-escpos.d.ts +24 -24
- package/dist/cjs/receipt/layout-escpos.js +49 -49
- package/dist/cjs/receipt/layout.d.ts +28 -23
- package/dist/cjs/receipt/layout.js +45 -21
- package/dist/cjs/receipt/marke-daten.d.ts +8 -8
- package/dist/cjs/receipt/marke-daten.js +8 -8
- package/dist/cjs/receipt/marke.d.ts +7 -7
- package/dist/cjs/receipt/marke.js +10 -10
- package/dist/cjs/register/errors.d.ts +61 -0
- package/dist/cjs/register/errors.js +112 -0
- package/dist/cjs/register/index.d.ts +14 -1
- package/dist/cjs/register/index.js +20 -1
- package/dist/cjs/register/pairing.d.ts +55 -36
- package/dist/cjs/register/pairing.js +33 -29
- package/dist/cjs/register/session.d.ts +5 -5
- package/dist/cjs/register/session.js +7 -7
- package/dist/cjs/stored/draht.d.ts +45 -0
- package/dist/cjs/stored/draht.js +220 -0
- package/dist/cjs/stored/einstellungen.d.ts +23 -0
- package/dist/cjs/stored/einstellungen.js +200 -0
- package/dist/cjs/stored/index.d.ts +109 -0
- package/dist/cjs/stored/index.js +225 -0
- package/dist/cjs/stored/vokabular.d.ts +18 -0
- package/dist/cjs/stored/vokabular.js +389 -0
- package/dist/cjs/version.d.ts +7 -0
- package/dist/cjs/version.js +10 -0
- package/dist/cjs/vienna-time.d.ts +1 -1
- package/dist/cjs/vienna-time.js +2 -2
- package/dist/esm/client/api.d.ts +7 -6
- package/dist/esm/client/api.js +4 -4
- package/dist/esm/client/aufrufe.d.ts +29 -5
- package/dist/esm/client/aufrufe.js +111 -1
- package/dist/esm/client/auth.d.ts +2 -0
- package/dist/esm/client/auth.js +16 -1
- package/dist/esm/client/cashregisters.d.ts +1 -1
- package/dist/esm/client/cashregisters.js +2 -2
- package/dist/esm/client/errors.d.ts +94 -19
- package/dist/esm/client/errors.js +129 -27
- package/dist/esm/client/fehlercodes.d.ts +9 -0
- package/dist/esm/client/fehlercodes.js +32 -0
- package/dist/esm/client/index.d.ts +5 -5
- package/dist/esm/client/index.js +5 -5
- package/dist/esm/client/receipts.d.ts +131 -124
- package/dist/esm/client/receipts.js +195 -140
- package/dist/esm/client/reports.d.ts +26 -4
- package/dist/esm/client/reports.js +36 -4
- package/dist/esm/client/status.d.ts +3 -3
- package/dist/esm/client/status.js +7 -7
- package/dist/esm/client/transport.d.ts +56 -4
- package/dist/esm/client/transport.js +233 -24
- package/dist/esm/enums/vat-rate.d.ts +2 -2
- package/dist/esm/enums/vat-rate.js +1 -1
- package/dist/esm/index.d.ts +4 -3
- package/dist/esm/index.js +4 -3
- package/dist/{cjs/rechnung → esm/invoice}/api.d.ts +18 -17
- package/dist/esm/{rechnung → invoice}/api.js +6 -6
- package/dist/{cjs/rechnung → esm/invoice}/auth.d.ts +2 -2
- package/dist/esm/{rechnung → invoice}/auth.js +4 -4
- package/dist/{cjs/rechnung/rechnen.d.ts → esm/invoice/calc.d.ts} +27 -27
- package/dist/esm/{rechnung/rechnen.js → invoice/calc.js} +45 -45
- package/dist/{cjs/rechnung → esm/invoice}/endpunkte.d.ts +23 -21
- package/dist/esm/{rechnung → invoice}/endpunkte.js +52 -42
- package/dist/esm/invoice/fehler.d.ts +31 -0
- package/dist/esm/invoice/fehler.js +33 -0
- package/dist/esm/invoice/index.d.ts +21 -0
- package/dist/esm/invoice/index.js +20 -0
- package/dist/esm/{rechnung → invoice}/summen.d.ts +12 -12
- package/dist/esm/{rechnung → invoice}/summen.js +12 -12
- package/dist/esm/invoice/texte.d.ts +224 -0
- package/dist/esm/invoice/texte.js +421 -0
- package/dist/{cjs/rechnung → esm/invoice}/typen.d.ts +32 -11
- package/dist/esm/{rechnung → invoice}/vertrag.d.ts +97 -71
- package/dist/esm/{rechnung → invoice}/vertrag.js +143 -81
- package/dist/esm/models/cancellation.d.ts +43 -24
- package/dist/esm/models/cancellation.js +90 -45
- package/dist/esm/models/hobex-receipt.d.ts +3 -3
- package/dist/esm/models/hobex-receipt.js +35 -35
- package/dist/esm/models/index.d.ts +6 -5
- package/dist/esm/models/index.js +6 -5
- package/dist/esm/models/payment-errors.d.ts +32 -15
- package/dist/esm/models/payment-errors.js +77 -32
- package/dist/esm/models/receipt-company.d.ts +6 -5
- package/dist/esm/models/receipt-company.js +4 -4
- package/dist/esm/models/receipt-email.d.ts +32 -18
- package/dist/esm/models/receipt-email.js +65 -23
- package/dist/esm/models/receipt-errors.d.ts +39 -0
- package/dist/esm/models/receipt-errors.js +87 -0
- package/dist/esm/models/receipt-item.d.ts +9 -1
- package/dist/esm/models/receipt-item.js +3 -0
- package/dist/esm/models/receipt-summary.d.ts +10 -4
- package/dist/esm/models/receipt-summary.js +9 -3
- package/dist/esm/models/receipt.d.ts +31 -2
- package/dist/esm/models/receipt.js +12 -2
- package/dist/esm/models/voucher.d.ts +7 -6
- package/dist/esm/models/voucher.js +2 -7
- package/dist/esm/partner/ablauf.d.ts +10 -10
- package/dist/esm/partner/ablauf.js +27 -27
- package/dist/esm/partner/api.d.ts +26 -23
- package/dist/esm/partner/api.js +13 -15
- package/dist/esm/partner/auth.d.ts +1 -1
- package/dist/esm/partner/auth.js +2 -2
- package/dist/esm/partner/betrieb.d.ts +7 -7
- package/dist/esm/partner/betrieb.js +8 -8
- package/dist/esm/partner/endpunkte.d.ts +27 -14
- package/dist/esm/partner/endpunkte.js +79 -39
- package/dist/esm/partner/fehler.d.ts +60 -30
- package/dist/esm/partner/fehler.js +91 -35
- package/dist/esm/partner/index.d.ts +13 -12
- package/dist/esm/partner/index.js +12 -11
- package/dist/esm/partner/secret.d.ts +3 -3
- package/dist/esm/partner/secret.js +5 -5
- package/dist/esm/partner/typen.d.ts +129 -71
- package/dist/esm/partner/typen.js +75 -2
- package/dist/esm/partner/webhook-signatur.d.ts +2 -2
- package/dist/esm/partner/webhook-signatur.js +12 -12
- package/dist/esm/partner/webhooks.d.ts +60 -32
- package/dist/esm/partner/webhooks.js +38 -32
- package/dist/esm/payments/hobex.d.ts +11 -3
- package/dist/esm/payments/hobex.js +18 -6
- package/dist/esm/payments/stripe.d.ts +5 -2
- package/dist/esm/payments/stripe.js +11 -6
- package/dist/esm/pos/artikel.d.ts +90 -0
- package/dist/esm/pos/artikel.js +79 -0
- package/dist/esm/pos/client.d.ts +27 -0
- package/dist/esm/pos/client.js +137 -0
- package/dist/esm/pos/drucker.d.ts +86 -0
- package/dist/esm/pos/drucker.js +71 -0
- package/dist/esm/pos/errors.d.ts +36 -0
- package/dist/esm/pos/errors.js +88 -0
- package/dist/esm/pos/index.d.ts +15 -0
- package/dist/esm/pos/index.js +20 -0
- package/dist/esm/pos/settings.d.ts +313 -0
- package/dist/esm/pos/settings.js +367 -0
- package/dist/esm/pos/texte.d.ts +883 -0
- package/dist/esm/pos/texte.js +481 -0
- package/dist/esm/{kasse → pos}/trinkgeld.d.ts +1 -1
- package/dist/esm/{kasse → pos}/trinkgeld.js +2 -2
- package/dist/esm/printing/escpos.d.ts +29 -29
- package/dist/esm/printing/escpos.js +56 -56
- package/dist/esm/printing/index.d.ts +2 -2
- package/dist/esm/printing/index.js +2 -2
- package/dist/esm/printing/qr-groesse.d.ts +38 -38
- package/dist/esm/printing/qr-groesse.js +42 -42
- package/dist/esm/printing/webusb.d.ts +2 -2
- package/dist/esm/printing/webusb.js +4 -4
- package/dist/esm/react/index.d.ts +21 -21
- package/dist/esm/react/index.js +39 -29
- package/dist/esm/receipt/bild.d.ts +4 -4
- package/dist/esm/receipt/bild.js +11 -11
- package/dist/esm/receipt/blatt.d.ts +46 -46
- package/dist/esm/receipt/blatt.js +55 -55
- package/dist/esm/receipt/discount.d.ts +1 -1
- package/dist/esm/receipt/discount.js +7 -7
- package/dist/esm/receipt/due.d.ts +86 -0
- package/dist/esm/receipt/due.js +257 -0
- package/dist/esm/receipt/epos.d.ts +22 -22
- package/dist/esm/receipt/epos.js +47 -47
- package/dist/esm/receipt/grid.d.ts +10 -10
- package/dist/esm/receipt/grid.js +18 -18
- package/dist/esm/receipt/index.d.ts +9 -8
- package/dist/esm/receipt/index.js +9 -8
- package/dist/esm/receipt/layout-escpos.d.ts +24 -24
- package/dist/esm/receipt/layout-escpos.js +51 -51
- package/dist/esm/receipt/layout.d.ts +28 -23
- package/dist/esm/receipt/layout.js +44 -20
- package/dist/esm/receipt/marke-daten.d.ts +8 -8
- package/dist/esm/receipt/marke-daten.js +7 -7
- package/dist/esm/receipt/marke.d.ts +7 -7
- package/dist/esm/receipt/marke.js +10 -10
- package/dist/esm/register/errors.d.ts +61 -0
- package/dist/esm/register/errors.js +104 -0
- package/dist/esm/register/index.d.ts +14 -1
- package/dist/esm/register/index.js +13 -0
- package/dist/esm/register/pairing.d.ts +55 -36
- package/dist/esm/register/pairing.js +33 -29
- package/dist/esm/register/session.d.ts +5 -5
- package/dist/esm/register/session.js +7 -7
- package/dist/esm/stored/draht.d.ts +45 -0
- package/dist/esm/stored/draht.js +208 -0
- package/dist/esm/stored/einstellungen.d.ts +23 -0
- package/dist/esm/stored/einstellungen.js +196 -0
- package/dist/esm/stored/index.d.ts +109 -0
- package/dist/esm/stored/index.js +217 -0
- package/dist/esm/stored/vokabular.d.ts +18 -0
- package/dist/esm/stored/vokabular.js +386 -0
- package/dist/esm/version.d.ts +7 -0
- package/dist/esm/version.js +7 -0
- package/dist/esm/vienna-time.d.ts +1 -1
- package/dist/esm/vienna-time.js +2 -2
- package/fixtures/{erwartet/storno-rabatt.lines.json → expected/cancellation-discount.lines.json} +2 -2
- package/fixtures/expected/cancellation-discount.sheet32.json +248 -0
- package/fixtures/{erwartet/storno-rabatt.blatt48.json → expected/cancellation-discount.sheet48.json} +119 -119
- package/fixtures/{erwartet/storno-voll.lines.json → expected/cancellation-full.lines.json} +2 -2
- package/fixtures/expected/cancellation-full.sheet32.json +218 -0
- package/fixtures/{erwartet/storno-voll.blatt48.json → expected/cancellation-full.sheet48.json} +107 -107
- package/fixtures/{erwartet/storno-teil.lines.json → expected/cancellation-partial.lines.json} +2 -2
- package/fixtures/expected/cancellation-partial.sheet32.json +206 -0
- package/fixtures/{erwartet/storno-teil.blatt48.json → expected/cancellation-partial.sheet48.json} +101 -101
- package/fixtures/{erwartet/storno-split-voll.lines.json → expected/cancellation-split-full.lines.json} +2 -2
- package/fixtures/expected/cancellation-split-full.sheet32.json +320 -0
- package/fixtures/{erwartet/storno-split-voll.blatt48.json → expected/cancellation-split-full.sheet48.json} +158 -158
- package/fixtures/{erwartet/storno-split-teil.lines.json → expected/cancellation-split-partial.lines.json} +2 -2
- package/fixtures/expected/cancellation-split-partial.sheet32.json +230 -0
- package/fixtures/{erwartet/storno-split-teil.blatt48.json → expected/cancellation-split-partial.sheet48.json} +113 -113
- package/fixtures/{erwartet/karte-eigener.lines.json → expected/card-custom.lines.json} +1 -1
- package/fixtures/expected/card-custom.sheet32.json +158 -0
- package/fixtures/{erwartet/karte-eigener.blatt48.json → expected/card-custom.sheet48.json} +80 -80
- package/fixtures/{erwartet/karte-gptom-ios.lines.json → expected/card-gptom-ios.lines.json} +1 -1
- package/fixtures/expected/card-gptom-ios.sheet32.json +230 -0
- package/fixtures/{erwartet/karte-gptom-ios.blatt48.json → expected/card-gptom-ios.sheet48.json} +116 -116
- package/fixtures/{erwartet/karte-gptom.lines.json → expected/card-gptom.lines.json} +1 -1
- package/fixtures/expected/card-gptom.sheet32.json +230 -0
- package/fixtures/{erwartet/karte-gptom.blatt48.json → expected/card-gptom.sheet48.json} +116 -116
- package/fixtures/{erwartet/karte-hobex-cloud.lines.json → expected/card-hobex-cloud.lines.json} +1 -1
- package/fixtures/expected/card-hobex-cloud.sheet32.json +200 -0
- package/fixtures/{erwartet/karte-hobex-cloud.blatt48.json → expected/card-hobex-cloud.sheet48.json} +101 -101
- package/fixtures/{erwartet/karte-hobex-hps.lines.json → expected/card-hobex-hps.lines.json} +1 -1
- package/fixtures/expected/card-hobex-hps.sheet32.json +224 -0
- package/fixtures/{erwartet/karte-hobex-hps.blatt48.json → expected/card-hobex-hps.sheet48.json} +113 -113
- package/fixtures/{erwartet/karte-mypos.lines.json → expected/card-mypos.lines.json} +1 -1
- package/fixtures/expected/card-mypos.sheet32.json +254 -0
- package/fixtures/{erwartet/karte-mypos.blatt48.json → expected/card-mypos.sheet48.json} +122 -122
- package/fixtures/{erwartet/karte-stripe-eps.lines.json → expected/card-stripe-eps.lines.json} +1 -1
- package/fixtures/expected/card-stripe-eps.sheet32.json +194 -0
- package/fixtures/{erwartet/karte-stripe-eps.blatt48.json → expected/card-stripe-eps.sheet48.json} +98 -98
- package/fixtures/{erwartet/karte-stripe.lines.json → expected/card-stripe.lines.json} +1 -1
- package/fixtures/expected/card-stripe.sheet32.json +212 -0
- package/fixtures/{erwartet/karte-stripe.blatt48.json → expected/card-stripe.sheet48.json} +107 -107
- package/fixtures/{erwartet/karte-sumup.lines.json → expected/card-sumup.lines.json} +1 -1
- package/fixtures/expected/card-sumup.sheet32.json +218 -0
- package/fixtures/{erwartet/karte-sumup.blatt48.json → expected/card-sumup.sheet48.json} +104 -104
- package/fixtures/{erwartet/rabattzeilen.lines.json → expected/discount-lines.lines.json} +1 -1
- package/fixtures/expected/discount-lines.sheet32.json +200 -0
- package/fixtures/{erwartet/rabattzeilen.blatt48.json → expected/discount-lines.sheet48.json} +98 -98
- package/fixtures/{erwartet/rabatt-chef-trinkgeld.lines.json → expected/discount-owner-tip.lines.json} +1 -1
- package/fixtures/expected/discount-owner-tip.sheet32.json +212 -0
- package/fixtures/{erwartet/rabatt-chef-trinkgeld.blatt48.json → expected/discount-owner-tip.sheet48.json} +104 -104
- package/fixtures/{erwartet/rabatt-einfach.lines.json → expected/discount-simple.lines.json} +1 -1
- package/fixtures/expected/discount-simple.sheet32.json +182 -0
- package/fixtures/{erwartet/rabatt-einfach.blatt48.json → expected/discount-simple.sheet48.json} +89 -89
- package/fixtures/{erwartet/rabatt-trinkgeld.lines.json → expected/discount-tip.lines.json} +1 -1
- package/fixtures/expected/discount-tip.sheet32.json +212 -0
- package/fixtures/{erwartet/rabatt-trinkgeld.blatt48.json → expected/discount-tip.sheet48.json} +104 -104
- package/fixtures/{erwartet/rabatt-wertgutschein.lines.json → expected/discount-value-voucher.lines.json} +1 -1
- package/fixtures/expected/discount-value-voucher.sheet32.json +218 -0
- package/fixtures/{erwartet/rabatt-wertgutschein.blatt48.json → expected/discount-value-voucher.sheet48.json} +107 -107
- package/fixtures/{erwartet/langer-artikelname.lines.json → expected/long-item-name.lines.json} +1 -1
- package/fixtures/expected/long-item-name.sheet32.json +176 -0
- package/fixtures/{erwartet/langer-artikelname.blatt48.json → expected/long-item-name.sheet48.json} +86 -86
- package/fixtures/{erwartet/verkauf-karte.lines.json → expected/sale-card.lines.json} +1 -1
- package/fixtures/expected/sale-card.sheet32.json +176 -0
- package/fixtures/{erwartet/verkauf-karte.blatt48.json → expected/sale-card.sheet48.json} +86 -86
- package/fixtures/{erwartet/verkauf-bar.lines.json → expected/sale-cash.lines.json} +1 -1
- package/fixtures/expected/sale-cash.sheet32.json +176 -0
- package/fixtures/{erwartet/verkauf-bar.blatt48.json → expected/sale-cash.sheet48.json} +86 -86
- package/fixtures/{erwartet/verkauf-kleinunternehmer.lines.json → expected/sale-small-business.lines.json} +1 -1
- package/fixtures/expected/sale-small-business.sheet32.json +182 -0
- package/fixtures/{erwartet/verkauf-kleinunternehmer.blatt48.json → expected/sale-small-business.sheet48.json} +89 -89
- package/fixtures/{erwartet/signaturausfall-verkauf.lines.json → expected/signature-outage-sale.lines.json} +1 -1
- package/fixtures/expected/signature-outage-sale.sheet32.json +194 -0
- package/fixtures/{erwartet/signaturausfall-verkauf.blatt48.json → expected/signature-outage-sale.sheet48.json} +92 -92
- package/fixtures/{erwartet/split-karte-karte-bar.lines.json → expected/split-card-card-cash.lines.json} +1 -1
- package/fixtures/expected/split-card-card-cash.sheet32.json +356 -0
- package/fixtures/{erwartet/split-karte-karte-bar.blatt48.json → expected/split-card-card-cash.sheet48.json} +170 -170
- package/fixtures/{erwartet/split-bar-rueckgeld.lines.json → expected/split-cash-change.lines.json} +1 -1
- package/fixtures/expected/split-cash-change.sheet32.json +194 -0
- package/fixtures/{erwartet/split-bar-rueckgeld.blatt48.json → expected/split-cash-change.sheet48.json} +92 -92
- package/fixtures/{erwartet/split-langer-betrag.lines.json → expected/split-long-amount.lines.json} +1 -1
- package/fixtures/expected/split-long-amount.sheet32.json +266 -0
- package/fixtures/{erwartet/split-langer-betrag.blatt48.json → expected/split-long-amount.sheet48.json} +131 -131
- package/fixtures/{erwartet/split-eine-karte-trinkgeld.lines.json → expected/split-one-card-tip.lines.json} +1 -1
- package/fixtures/expected/split-one-card-tip.sheet32.json +242 -0
- package/fixtures/{erwartet/split-eine-karte-trinkgeld.blatt48.json → expected/split-one-card-tip.sheet48.json} +113 -113
- package/fixtures/{erwartet/split-tischrunde-trinkgeld.lines.json → expected/split-table-round-tip.lines.json} +1 -1
- package/fixtures/expected/split-table-round-tip.sheet32.json +470 -0
- package/fixtures/{erwartet/split-tischrunde-trinkgeld.blatt48.json → expected/split-table-round-tip.sheet48.json} +218 -218
- package/fixtures/{erwartet/split-trinkgeld-karte.lines.json → expected/split-tip-card.lines.json} +1 -1
- package/fixtures/expected/split-tip-card.sheet32.json +272 -0
- package/fixtures/{erwartet/split-trinkgeld-karte.blatt48.json → expected/split-tip-card.sheet48.json} +128 -128
- package/fixtures/{erwartet/split-zwei-karten-gleicher-anbieter.lines.json → expected/split-two-cards-same-provider.lines.json} +1 -1
- package/fixtures/expected/split-two-cards-same-provider.sheet32.json +326 -0
- package/fixtures/{erwartet/split-zwei-karten-gleicher-anbieter.blatt48.json → expected/split-two-cards-same-provider.sheet48.json} +149 -149
- package/fixtures/{erwartet/testkasse-verkauf.lines.json → expected/test-cashregister-sale.lines.json} +3 -3
- package/fixtures/expected/test-cashregister-sale.sheet32.json +224 -0
- package/fixtures/{erwartet/testkasse-verkauf.blatt48.json → expected/test-cashregister-sale.sheet48.json} +110 -110
- package/fixtures/{erwartet/testsignatur-verkauf.lines.json → expected/test-signature-sale.lines.json} +3 -3
- package/fixtures/expected/test-signature-sale.sheet32.json +236 -0
- package/fixtures/{erwartet/testsignatur-verkauf.blatt48.json → expected/test-signature-sale.sheet48.json} +110 -110
- package/fixtures/{erwartet → expected}/training.lines.json +2 -2
- package/fixtures/expected/training.sheet32.json +236 -0
- package/fixtures/{erwartet/training.blatt48.json → expected/training.sheet48.json} +110 -110
- package/fixtures/{erwartet/null-jahr.lines.json → expected/zero-annual.lines.json} +2 -2
- package/fixtures/expected/zero-annual.sheet32.json +212 -0
- package/fixtures/{erwartet/null-jahr.blatt48.json → expected/zero-annual.sheet48.json} +95 -95
- package/fixtures/{erwartet/null-schluss.lines.json → expected/zero-final.lines.json} +2 -2
- package/fixtures/expected/zero-final.sheet32.json +206 -0
- package/fixtures/{erwartet/null-schluss.blatt48.json → expected/zero-final.sheet48.json} +95 -95
- package/fixtures/{erwartet/null-pruef.lines.json → expected/zero-manual.lines.json} +2 -2
- package/fixtures/expected/zero-manual.sheet32.json +206 -0
- package/fixtures/{erwartet/null-pruef.blatt48.json → expected/zero-manual.sheet48.json} +95 -95
- package/fixtures/{erwartet/null-monat.lines.json → expected/zero-monthly.lines.json} +2 -2
- package/fixtures/expected/zero-monthly.sheet32.json +206 -0
- package/fixtures/{erwartet/null-monat.blatt48.json → expected/zero-monthly.sheet48.json} +95 -95
- package/fixtures/{erwartet/null-ausfall.lines.json → expected/zero-outage-end.lines.json} +2 -2
- package/fixtures/expected/zero-outage-end.sheet32.json +206 -0
- package/fixtures/{erwartet/null-ausfall.blatt48.json → expected/zero-outage-end.sheet48.json} +95 -95
- package/fixtures/{erwartet/null-start.lines.json → expected/zero-start.lines.json} +2 -2
- package/fixtures/expected/zero-start.sheet32.json +206 -0
- package/fixtures/{erwartet/null-start.blatt48.json → expected/zero-start.sheet48.json} +95 -95
- package/fixtures/hobex-hps-codes.json +12 -12
- package/fixtures/invoice-api-examples/brands-ok.json +8 -0
- package/fixtures/{rechnung-api-beispiele/credit-fehler-grund.json → invoice-api-examples/credit-error-reason.json} +6 -6
- package/fixtures/{rechnung-api-beispiele → invoice-api-examples}/credit-ok.json +6 -6
- package/fixtures/{rechnung-api-beispiele/customer-fehler-uid.json → invoice-api-examples/customer-error-vat-id.json} +4 -4
- package/fixtures/invoice-api-examples/customer-get-error-both.json +15 -0
- package/fixtures/{rechnung-api-beispiele → invoice-api-examples}/customer-ok.json +4 -4
- package/fixtures/{rechnung-api-beispiele/customer-search-fehler-leer.json → invoice-api-examples/customer-search-error-empty.json} +4 -4
- package/fixtures/{rechnung-api-beispiele/issue-rabatt.json → invoice-api-examples/issue-discount.json} +6 -6
- package/fixtures/{rechnung-api-beispiele/issue-englisch.json → invoice-api-examples/issue-english.json} +7 -7
- package/fixtures/{rechnung-api-beispiele/issue-fehler-cent.json → invoice-api-examples/issue-error-cent.json} +6 -6
- package/fixtures/{rechnung-api-beispiele/issue-fehler-sprache.json → invoice-api-examples/issue-error-language.json} +5 -5
- package/fixtures/{rechnung-api-beispiele/issue-fehler-negativ.json → invoice-api-examples/issue-error-negative.json} +6 -6
- package/fixtures/{rechnung-api-beispiele/issue-fehler-zahlungsart.json → invoice-api-examples/issue-error-payment-method.json} +8 -6
- package/fixtures/{rechnung-api-beispiele/issue-fehler-preis-beide.json → invoice-api-examples/issue-error-price-both.json} +6 -6
- package/fixtures/{rechnung-api-beispiele/issue-fehler-preis-fehlt.json → invoice-api-examples/issue-error-price-missing.json} +6 -6
- package/fixtures/{rechnung-api-beispiele/issue-fehler-menge.json → invoice-api-examples/issue-error-quantity.json} +6 -6
- package/fixtures/{rechnung-api-beispiele/issue-fehler-satz.json → invoice-api-examples/issue-error-rate.json} +6 -6
- package/fixtures/{rechnung-api-beispiele/issue-fehler-einheit.json → invoice-api-examples/issue-error-unit.json} +5 -5
- package/fixtures/{rechnung-api-beispiele/issue-fehler-unbekannt.json → invoice-api-examples/issue-error-unknown.json} +6 -6
- package/fixtures/{rechnung-api-beispiele/issue-brutto-20.json → invoice-api-examples/issue-gross-20.json} +6 -6
- package/fixtures/{rechnung-api-beispiele/issue-mikropreis.json → invoice-api-examples/issue-micro-price.json} +6 -6
- package/fixtures/{rechnung-api-beispiele/issue-gemischt.json → invoice-api-examples/issue-mixed.json} +6 -6
- package/fixtures/{rechnung-api-beispiele/issue-netto-20.json → invoice-api-examples/issue-net-20.json} +6 -6
- package/fixtures/{rechnung-api-beispiele/issue-bezahlt.json → invoice-api-examples/issue-paid.json} +7 -7
- package/fixtures/{rechnung-api-beispiele/issue-kleinunternehmer.json → invoice-api-examples/issue-small-business.json} +6 -6
- package/fixtures/invoice-api-examples/payment-error-on-site.json +17 -0
- package/fixtures/invoice-api-examples/payment-error-without-key.json +16 -0
- package/fixtures/invoice-api-examples/payment-recorded-later.json +14 -0
- package/fixtures/{rechnung-api-beispiele/setup-status-fehler-feld.json → invoice-api-examples/setup-status-error-field.json} +4 -4
- package/fixtures/invoice-api-examples/setup-status-ok.json +8 -0
- package/fixtures/{rechnung-api.schema.json → invoice-api.schema.json} +24 -24
- package/fixtures/{rechnung-rechnen-zufall.json → invoice-calc-random.json} +828 -828
- package/fixtures/{rechnung-rechnen.json → invoice-calc.json} +47 -47
- package/fixtures/invoice-texts.json +464 -0
- package/fixtures/{rechnung-summen.json → invoice-totals.json} +25 -25
- package/fixtures/{position-aus-euro.json → item-from-euro.json} +26 -26
- package/fixtures/manifest.json +252 -252
- package/fixtures/pos-message-cases.json +32 -0
- package/fixtures/pos-settings-defaults.json +149 -0
- package/fixtures/{kasse-texte.json → pos-texts.json} +416 -416
- package/fixtures/receipt-due-generated.json +1218 -0
- package/fixtures/{belege/storno-rabatt.json → receipts/cancellation-discount.json} +3 -3
- package/fixtures/{belege/storno-voll.json → receipts/cancellation-full.json} +3 -3
- package/fixtures/{belege/storno-teil.json → receipts/cancellation-partial.json} +3 -3
- package/fixtures/{belege/storno-split-voll.json → receipts/cancellation-split-full.json} +3 -3
- package/fixtures/{belege/storno-split-teil.json → receipts/cancellation-split-partial.json} +3 -3
- package/fixtures/{belege/karte-eigener.json → receipts/card-custom.json} +2 -2
- package/fixtures/{belege/karte-gptom-ios.json → receipts/card-gptom-ios.json} +2 -2
- package/fixtures/{belege/karte-gptom.json → receipts/card-gptom.json} +2 -2
- package/fixtures/{belege/karte-hobex-cloud.json → receipts/card-hobex-cloud.json} +2 -2
- package/fixtures/{belege/karte-hobex-hps.json → receipts/card-hobex-hps.json} +2 -2
- package/fixtures/{belege/karte-mypos.json → receipts/card-mypos.json} +2 -2
- package/fixtures/{belege/karte-stripe-eps.json → receipts/card-stripe-eps.json} +2 -2
- package/fixtures/{belege/karte-stripe.json → receipts/card-stripe.json} +2 -2
- package/fixtures/{belege/karte-sumup.json → receipts/card-sumup.json} +2 -2
- package/fixtures/{belege/rabattzeilen.json → receipts/discount-lines.json} +2 -2
- package/fixtures/{belege/rabatt-chef-trinkgeld.json → receipts/discount-owner-tip.json} +2 -2
- package/fixtures/{belege/rabatt-einfach.json → receipts/discount-simple.json} +2 -2
- package/fixtures/{belege/rabatt-trinkgeld.json → receipts/discount-tip.json} +2 -2
- package/fixtures/{belege/rabatt-wertgutschein.json → receipts/discount-value-voucher.json} +2 -2
- package/fixtures/{belege/langer-artikelname.json → receipts/long-item-name.json} +2 -2
- package/fixtures/{belege/verkauf-karte.json → receipts/sale-card.json} +2 -2
- package/fixtures/{belege/verkauf-bar.json → receipts/sale-cash.json} +2 -2
- package/fixtures/{belege/verkauf-kleinunternehmer.json → receipts/sale-small-business.json} +1 -1
- package/fixtures/{belege/signaturausfall-verkauf.json → receipts/signature-outage-sale.json} +2 -2
- package/fixtures/{belege/split-karte-karte-bar.json → receipts/split-card-card-cash.json} +2 -2
- package/fixtures/{belege/split-bar-rueckgeld.json → receipts/split-cash-change.json} +2 -2
- package/fixtures/{belege/split-langer-betrag.json → receipts/split-long-amount.json} +2 -2
- package/fixtures/{belege/split-eine-karte-trinkgeld.json → receipts/split-one-card-tip.json} +2 -2
- package/fixtures/{belege/split-tischrunde-trinkgeld.json → receipts/split-table-round-tip.json} +2 -2
- package/fixtures/{belege/split-trinkgeld-karte.json → receipts/split-tip-card.json} +2 -2
- package/fixtures/{belege/split-zwei-karten-gleicher-anbieter.json → receipts/split-two-cards-same-provider.json} +2 -2
- package/fixtures/{belege/testsignatur-verkauf.json → receipts/test-cashregister-sale.json} +3 -3
- package/fixtures/{belege/testkasse-verkauf.json → receipts/test-signature-sale.json} +3 -3
- package/fixtures/{belege → receipts}/training.json +2 -2
- package/fixtures/{belege/null-jahr.json → receipts/zero-annual.json} +5 -5
- package/fixtures/{belege/null-schluss.json → receipts/zero-final.json} +5 -5
- package/fixtures/{belege/null-pruef.json → receipts/zero-manual.json} +5 -5
- package/fixtures/{belege/null-monat.json → receipts/zero-monthly.json} +5 -5
- package/fixtures/{belege/null-ausfall.json → receipts/zero-outage-end.json} +5 -5
- package/fixtures/{belege/null-start.json → receipts/zero-start.json} +5 -5
- package/fixtures/renames-1.0.json +1490 -0
- package/fixtures/{kasse-settings-standard.json → stored/pos-settings-defaults.json} +7 -7
- package/fixtures/surface.json +877 -0
- package/fixtures/v3/README.md +125 -0
- package/fixtures/v3/antworten/belege.json +4738 -0
- package/fixtures/v3/antworten/belegmail.json +154 -0
- package/fixtures/v3/antworten/kasse-belege.json +4304 -0
- package/fixtures/v3/antworten/kasse.json +12716 -0
- package/fixtures/v3/antworten/rechnungen.json +1712 -0
- package/fixtures/v3/antworten/storno.json +737 -0
- package/fixtures/v3/stored/belege.json +502 -0
- package/fixtures/v3/stored/kasse.json +3461 -0
- package/fixtures/v3/stored/rechnungen.json +750 -0
- package/fixtures/v3/v3-vokabular.json +3375 -0
- package/fixtures/v3/zahlbetrag-faelle.json +794 -0
- package/package.json +32 -18
- package/dist/cjs/kasse/artikel.d.ts +0 -83
- package/dist/cjs/kasse/artikel.js +0 -79
- package/dist/cjs/kasse/client.d.ts +0 -10
- package/dist/cjs/kasse/client.js +0 -38
- package/dist/cjs/kasse/drucker.d.ts +0 -59
- package/dist/cjs/kasse/drucker.js +0 -50
- package/dist/cjs/kasse/index.d.ts +0 -13
- package/dist/cjs/kasse/index.js +0 -83
- package/dist/cjs/kasse/settings.d.ts +0 -229
- package/dist/cjs/kasse/settings.js +0 -172
- package/dist/cjs/kasse/texte.d.ts +0 -868
- package/dist/cjs/kasse/texte.js +0 -474
- package/dist/cjs/rechnung/fehler.d.ts +0 -21
- package/dist/cjs/rechnung/fehler.js +0 -44
- package/dist/cjs/rechnung/index.d.ts +0 -21
- package/dist/cjs/rechnung/index.js +0 -82
- package/dist/cjs/rechnung/texte.d.ts +0 -222
- package/dist/cjs/rechnung/texte.js +0 -425
- package/dist/esm/kasse/artikel.d.ts +0 -83
- package/dist/esm/kasse/artikel.js +0 -70
- package/dist/esm/kasse/client.d.ts +0 -10
- package/dist/esm/kasse/client.js +0 -33
- package/dist/esm/kasse/drucker.d.ts +0 -59
- package/dist/esm/kasse/drucker.js +0 -45
- package/dist/esm/kasse/index.d.ts +0 -13
- package/dist/esm/kasse/index.js +0 -18
- package/dist/esm/kasse/settings.d.ts +0 -229
- package/dist/esm/kasse/settings.js +0 -168
- package/dist/esm/kasse/texte.d.ts +0 -868
- package/dist/esm/kasse/texte.js +0 -466
- package/dist/esm/rechnung/fehler.d.ts +0 -21
- package/dist/esm/rechnung/fehler.js +0 -39
- package/dist/esm/rechnung/index.d.ts +0 -21
- package/dist/esm/rechnung/index.js +0 -20
- package/dist/esm/rechnung/texte.d.ts +0 -222
- package/dist/esm/rechnung/texte.js +0 -421
- package/fixtures/erwartet/karte-eigener.blatt32.json +0 -158
- package/fixtures/erwartet/karte-gptom-ios.blatt32.json +0 -230
- package/fixtures/erwartet/karte-gptom.blatt32.json +0 -230
- package/fixtures/erwartet/karte-hobex-cloud.blatt32.json +0 -200
- package/fixtures/erwartet/karte-hobex-hps.blatt32.json +0 -224
- package/fixtures/erwartet/karte-mypos.blatt32.json +0 -254
- package/fixtures/erwartet/karte-stripe-eps.blatt32.json +0 -194
- package/fixtures/erwartet/karte-stripe.blatt32.json +0 -212
- package/fixtures/erwartet/karte-sumup.blatt32.json +0 -218
- package/fixtures/erwartet/langer-artikelname.blatt32.json +0 -176
- package/fixtures/erwartet/null-ausfall.blatt32.json +0 -206
- package/fixtures/erwartet/null-jahr.blatt32.json +0 -212
- package/fixtures/erwartet/null-monat.blatt32.json +0 -206
- package/fixtures/erwartet/null-pruef.blatt32.json +0 -206
- package/fixtures/erwartet/null-schluss.blatt32.json +0 -206
- package/fixtures/erwartet/null-start.blatt32.json +0 -206
- package/fixtures/erwartet/rabatt-chef-trinkgeld.blatt32.json +0 -212
- package/fixtures/erwartet/rabatt-einfach.blatt32.json +0 -182
- package/fixtures/erwartet/rabatt-trinkgeld.blatt32.json +0 -212
- package/fixtures/erwartet/rabatt-wertgutschein.blatt32.json +0 -218
- package/fixtures/erwartet/rabattzeilen.blatt32.json +0 -200
- package/fixtures/erwartet/signaturausfall-verkauf.blatt32.json +0 -194
- package/fixtures/erwartet/split-bar-rueckgeld.blatt32.json +0 -194
- package/fixtures/erwartet/split-eine-karte-trinkgeld.blatt32.json +0 -242
- package/fixtures/erwartet/split-karte-karte-bar.blatt32.json +0 -356
- package/fixtures/erwartet/split-langer-betrag.blatt32.json +0 -266
- package/fixtures/erwartet/split-tischrunde-trinkgeld.blatt32.json +0 -470
- package/fixtures/erwartet/split-trinkgeld-karte.blatt32.json +0 -272
- package/fixtures/erwartet/split-zwei-karten-gleicher-anbieter.blatt32.json +0 -326
- package/fixtures/erwartet/storno-rabatt.blatt32.json +0 -248
- package/fixtures/erwartet/storno-split-teil.blatt32.json +0 -230
- package/fixtures/erwartet/storno-split-voll.blatt32.json +0 -320
- package/fixtures/erwartet/storno-teil.blatt32.json +0 -206
- package/fixtures/erwartet/storno-voll.blatt32.json +0 -218
- package/fixtures/erwartet/testkasse-verkauf.blatt32.json +0 -224
- package/fixtures/erwartet/testsignatur-verkauf.blatt32.json +0 -236
- package/fixtures/erwartet/training.blatt32.json +0 -236
- package/fixtures/erwartet/verkauf-bar.blatt32.json +0 -176
- package/fixtures/erwartet/verkauf-karte.blatt32.json +0 -176
- package/fixtures/erwartet/verkauf-kleinunternehmer.blatt32.json +0 -182
- package/fixtures/kasse-meldungen-faelle.json +0 -32
- package/fixtures/oberflaeche.json +0 -558
- package/fixtures/rechnung-api-beispiele/brands-ok.json +0 -8
- package/fixtures/rechnung-api-beispiele/customer-get-fehler-beide.json +0 -15
- package/fixtures/rechnung-api-beispiele/setup-status-ok.json +0 -8
- package/fixtures/rechnung-api-beispiele/zahlung-fehler-ohne-schluessel.json +0 -14
- package/fixtures/rechnung-api-beispiele/zahlung-fehler-vor-ort.json +0 -15
- package/fixtures/rechnung-api-beispiele/zahlung-nachtrag.json +0 -14
- package/fixtures/rechnung-texte.json +0 -464
- /package/dist/cjs/{rechnung → invoice}/typen.js +0 -0
- /package/dist/esm/{rechnung → invoice}/typen.js +0 -0
- /package/fixtures/{erwartet/storno-rabatt.grid32.txt → expected/cancellation-discount.grid32.txt} +0 -0
- /package/fixtures/{erwartet/storno-rabatt.grid48.txt → expected/cancellation-discount.grid48.txt} +0 -0
- /package/fixtures/{erwartet/storno-voll.grid32.txt → expected/cancellation-full.grid32.txt} +0 -0
- /package/fixtures/{erwartet/storno-voll.grid48.txt → expected/cancellation-full.grid48.txt} +0 -0
- /package/fixtures/{erwartet/storno-teil.grid32.txt → expected/cancellation-partial.grid32.txt} +0 -0
- /package/fixtures/{erwartet/storno-teil.grid48.txt → expected/cancellation-partial.grid48.txt} +0 -0
- /package/fixtures/{erwartet/storno-split-voll.grid32.txt → expected/cancellation-split-full.grid32.txt} +0 -0
- /package/fixtures/{erwartet/storno-split-voll.grid48.txt → expected/cancellation-split-full.grid48.txt} +0 -0
- /package/fixtures/{erwartet/storno-split-teil.grid32.txt → expected/cancellation-split-partial.grid32.txt} +0 -0
- /package/fixtures/{erwartet/storno-split-teil.grid48.txt → expected/cancellation-split-partial.grid48.txt} +0 -0
- /package/fixtures/{erwartet/karte-eigener.grid32.txt → expected/card-custom.grid32.txt} +0 -0
- /package/fixtures/{erwartet/karte-eigener.grid48.txt → expected/card-custom.grid48.txt} +0 -0
- /package/fixtures/{erwartet/karte-gptom-ios.grid32.txt → expected/card-gptom-ios.grid32.txt} +0 -0
- /package/fixtures/{erwartet/karte-gptom-ios.grid48.txt → expected/card-gptom-ios.grid48.txt} +0 -0
- /package/fixtures/{erwartet/karte-gptom.grid32.txt → expected/card-gptom.grid32.txt} +0 -0
- /package/fixtures/{erwartet/karte-gptom.grid48.txt → expected/card-gptom.grid48.txt} +0 -0
- /package/fixtures/{erwartet/karte-hobex-cloud.grid32.txt → expected/card-hobex-cloud.grid32.txt} +0 -0
- /package/fixtures/{erwartet/karte-hobex-cloud.grid48.txt → expected/card-hobex-cloud.grid48.txt} +0 -0
- /package/fixtures/{erwartet/karte-hobex-hps.grid32.txt → expected/card-hobex-hps.grid32.txt} +0 -0
- /package/fixtures/{erwartet/karte-hobex-hps.grid48.txt → expected/card-hobex-hps.grid48.txt} +0 -0
- /package/fixtures/{erwartet/karte-mypos.grid32.txt → expected/card-mypos.grid32.txt} +0 -0
- /package/fixtures/{erwartet/karte-mypos.grid48.txt → expected/card-mypos.grid48.txt} +0 -0
- /package/fixtures/{erwartet/karte-stripe-eps.grid32.txt → expected/card-stripe-eps.grid32.txt} +0 -0
- /package/fixtures/{erwartet/karte-stripe-eps.grid48.txt → expected/card-stripe-eps.grid48.txt} +0 -0
- /package/fixtures/{erwartet/karte-stripe.grid32.txt → expected/card-stripe.grid32.txt} +0 -0
- /package/fixtures/{erwartet/karte-stripe.grid48.txt → expected/card-stripe.grid48.txt} +0 -0
- /package/fixtures/{erwartet/karte-sumup.grid32.txt → expected/card-sumup.grid32.txt} +0 -0
- /package/fixtures/{erwartet/karte-sumup.grid48.txt → expected/card-sumup.grid48.txt} +0 -0
- /package/fixtures/{erwartet/rabattzeilen.grid32.txt → expected/discount-lines.grid32.txt} +0 -0
- /package/fixtures/{erwartet/rabattzeilen.grid48.txt → expected/discount-lines.grid48.txt} +0 -0
- /package/fixtures/{erwartet/rabatt-chef-trinkgeld.grid32.txt → expected/discount-owner-tip.grid32.txt} +0 -0
- /package/fixtures/{erwartet/rabatt-chef-trinkgeld.grid48.txt → expected/discount-owner-tip.grid48.txt} +0 -0
- /package/fixtures/{erwartet/rabatt-einfach.grid32.txt → expected/discount-simple.grid32.txt} +0 -0
- /package/fixtures/{erwartet/rabatt-einfach.grid48.txt → expected/discount-simple.grid48.txt} +0 -0
- /package/fixtures/{erwartet/rabatt-trinkgeld.grid32.txt → expected/discount-tip.grid32.txt} +0 -0
- /package/fixtures/{erwartet/rabatt-trinkgeld.grid48.txt → expected/discount-tip.grid48.txt} +0 -0
- /package/fixtures/{erwartet/rabatt-wertgutschein.grid32.txt → expected/discount-value-voucher.grid32.txt} +0 -0
- /package/fixtures/{erwartet/rabatt-wertgutschein.grid48.txt → expected/discount-value-voucher.grid48.txt} +0 -0
- /package/fixtures/{erwartet/logo-probe-hoch.raster32.txt → expected/logo-sample-tall.raster32.txt} +0 -0
- /package/fixtures/{erwartet/logo-probe.raster32.txt → expected/logo-sample.raster32.txt} +0 -0
- /package/fixtures/{erwartet/langer-artikelname.grid32.txt → expected/long-item-name.grid32.txt} +0 -0
- /package/fixtures/{erwartet/langer-artikelname.grid48.txt → expected/long-item-name.grid48.txt} +0 -0
- /package/fixtures/{erwartet/verkauf-karte.grid32.txt → expected/sale-card.grid32.txt} +0 -0
- /package/fixtures/{erwartet/verkauf-karte.grid48.txt → expected/sale-card.grid48.txt} +0 -0
- /package/fixtures/{erwartet/verkauf-bar.grid32.txt → expected/sale-cash.grid32.txt} +0 -0
- /package/fixtures/{erwartet/verkauf-bar.grid48.txt → expected/sale-cash.grid48.txt} +0 -0
- /package/fixtures/{erwartet/verkauf-kleinunternehmer.grid32.txt → expected/sale-small-business.grid32.txt} +0 -0
- /package/fixtures/{erwartet/verkauf-kleinunternehmer.grid48.txt → expected/sale-small-business.grid48.txt} +0 -0
- /package/fixtures/{erwartet/signaturausfall-verkauf.grid32.txt → expected/signature-outage-sale.grid32.txt} +0 -0
- /package/fixtures/{erwartet/signaturausfall-verkauf.grid48.txt → expected/signature-outage-sale.grid48.txt} +0 -0
- /package/fixtures/{erwartet/split-karte-karte-bar.grid32.txt → expected/split-card-card-cash.grid32.txt} +0 -0
- /package/fixtures/{erwartet/split-karte-karte-bar.grid48.txt → expected/split-card-card-cash.grid48.txt} +0 -0
- /package/fixtures/{erwartet/split-bar-rueckgeld.grid32.txt → expected/split-cash-change.grid32.txt} +0 -0
- /package/fixtures/{erwartet/split-bar-rueckgeld.grid48.txt → expected/split-cash-change.grid48.txt} +0 -0
- /package/fixtures/{erwartet/split-langer-betrag.grid32.txt → expected/split-long-amount.grid32.txt} +0 -0
- /package/fixtures/{erwartet/split-langer-betrag.grid48.txt → expected/split-long-amount.grid48.txt} +0 -0
- /package/fixtures/{erwartet/split-eine-karte-trinkgeld.grid32.txt → expected/split-one-card-tip.grid32.txt} +0 -0
- /package/fixtures/{erwartet/split-eine-karte-trinkgeld.grid48.txt → expected/split-one-card-tip.grid48.txt} +0 -0
- /package/fixtures/{erwartet/split-tischrunde-trinkgeld.grid32.txt → expected/split-table-round-tip.grid32.txt} +0 -0
- /package/fixtures/{erwartet/split-tischrunde-trinkgeld.grid48.txt → expected/split-table-round-tip.grid48.txt} +0 -0
- /package/fixtures/{erwartet/split-trinkgeld-karte.grid32.txt → expected/split-tip-card.grid32.txt} +0 -0
- /package/fixtures/{erwartet/split-trinkgeld-karte.grid48.txt → expected/split-tip-card.grid48.txt} +0 -0
- /package/fixtures/{erwartet/split-zwei-karten-gleicher-anbieter.grid32.txt → expected/split-two-cards-same-provider.grid32.txt} +0 -0
- /package/fixtures/{erwartet/split-zwei-karten-gleicher-anbieter.grid48.txt → expected/split-two-cards-same-provider.grid48.txt} +0 -0
- /package/fixtures/{erwartet/testkasse-verkauf.grid32.txt → expected/test-cashregister-sale.grid32.txt} +0 -0
- /package/fixtures/{erwartet/testkasse-verkauf.grid48.txt → expected/test-cashregister-sale.grid48.txt} +0 -0
- /package/fixtures/{erwartet/testsignatur-verkauf.grid32.txt → expected/test-signature-sale.grid32.txt} +0 -0
- /package/fixtures/{erwartet/testsignatur-verkauf.grid48.txt → expected/test-signature-sale.grid48.txt} +0 -0
- /package/fixtures/{erwartet → expected}/training.grid32.txt +0 -0
- /package/fixtures/{erwartet → expected}/training.grid48.txt +0 -0
- /package/fixtures/{erwartet/null-jahr.grid32.txt → expected/zero-annual.grid32.txt} +0 -0
- /package/fixtures/{erwartet/null-jahr.grid48.txt → expected/zero-annual.grid48.txt} +0 -0
- /package/fixtures/{erwartet/null-schluss.grid32.txt → expected/zero-final.grid32.txt} +0 -0
- /package/fixtures/{erwartet/null-schluss.grid48.txt → expected/zero-final.grid48.txt} +0 -0
- /package/fixtures/{erwartet/null-pruef.grid32.txt → expected/zero-manual.grid32.txt} +0 -0
- /package/fixtures/{erwartet/null-pruef.grid48.txt → expected/zero-manual.grid48.txt} +0 -0
- /package/fixtures/{erwartet/null-monat.grid32.txt → expected/zero-monthly.grid32.txt} +0 -0
- /package/fixtures/{erwartet/null-monat.grid48.txt → expected/zero-monthly.grid48.txt} +0 -0
- /package/fixtures/{erwartet/null-ausfall.grid32.txt → expected/zero-outage-end.grid32.txt} +0 -0
- /package/fixtures/{erwartet/null-ausfall.grid48.txt → expected/zero-outage-end.grid48.txt} +0 -0
- /package/fixtures/{erwartet/null-start.grid32.txt → expected/zero-start.grid32.txt} +0 -0
- /package/fixtures/{erwartet/null-start.grid48.txt → expected/zero-start.grid48.txt} +0 -0
package/README.md
CHANGED
|
@@ -36,6 +36,7 @@ models, same enum values, checked against each other in tests.
|
|
|
36
36
|
- [What a fiscal cash register in Austria must do](#what-a-fiscal-cash-register-in-austria-must-do)
|
|
37
37
|
- [Try it first, or use the ready-made register](#try-it-first-or-use-the-ready-made-register)
|
|
38
38
|
- [Requirements and subpaths](#requirements-and-subpaths)
|
|
39
|
+
- [Base URLs and the `/v3` marker](#base-urls-and-the-v3-marker)
|
|
39
40
|
- [Authentication](#authentication)
|
|
40
41
|
- [Amounts are integer cents](#amounts-are-integer-cents)
|
|
41
42
|
- [Errors](#errors)
|
|
@@ -43,9 +44,12 @@ models, same enum values, checked against each other in tests.
|
|
|
43
44
|
- [Cancellation (Storno)](#cancellation-storno)
|
|
44
45
|
- [Sending a receipt by email](#sending-a-receipt-by-email)
|
|
45
46
|
- [Receipt printing: QR code, logo, printers](#receipt-printing-qr-code-logo-printers)
|
|
47
|
+
- [Register settings, articles and printers (`./pos`)](#register-settings-articles-and-printers-pos)
|
|
48
|
+
- [Stored documents (`./stored`)](#stored-documents-stored)
|
|
46
49
|
- [Card payments](#card-payments)
|
|
47
50
|
- [Partner API (`./partner`)](#partner-api-partner)
|
|
48
|
-
- [Invoice API (`./
|
|
51
|
+
- [Invoice API (`./invoice`)](#invoice-api-invoice)
|
|
52
|
+
- [Migrating from 0.x](#migrating-from-0x)
|
|
49
53
|
- [Development](#development)
|
|
50
54
|
- [Contract files for the twin packages](#contract-files-for-the-twin-packages)
|
|
51
55
|
- [Glossary](#glossary)
|
|
@@ -65,40 +69,70 @@ import {
|
|
|
65
69
|
apiKeyAuth,
|
|
66
70
|
KeckPaymentMethod,
|
|
67
71
|
VatRate,
|
|
72
|
+
receiptDueCents,
|
|
73
|
+
receiptLayoutFromResult,
|
|
68
74
|
} from '@kreiseck/kasseneck-api';
|
|
69
|
-
import {
|
|
75
|
+
import { renderReceiptGrid, escPosLayoutBytes } from '@kreiseck/kasseneck-api/receipt';
|
|
70
76
|
|
|
71
77
|
const api = createKasseneckApi({
|
|
72
78
|
auth: apiKeyAuth({ apiKey: 'kr_live_…', cashregisterToken: 'cb_live_…' }),
|
|
73
79
|
});
|
|
74
80
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
81
|
+
const items = [
|
|
82
|
+
{ name: 'Café Latte', quantity: 2, vat: VatRate.vat20, priceCents: 390 },
|
|
83
|
+
{ name: 'Marmeladeweckerl', quantity: 1, vat: VatRate.vat10, priceCents: 250 },
|
|
84
|
+
];
|
|
85
|
+
// Optional tip in cents; the backend books it as a signed tip line.
|
|
86
|
+
// With its own payment method or recipients: { cents, paymentMethod, recipients }.
|
|
87
|
+
const tip = 100;
|
|
88
|
+
|
|
89
|
+
// The payments must add up to exactly this amount (whole cents). Who gets a
|
|
90
|
+
// tip without recipients is the logged-in register user: 'owner' or 'staff'.
|
|
91
|
+
const dueCents = receiptDueCents(items, [], 'standard', { tip, tipRecipient: 'staff' }); // 1130
|
|
92
|
+
|
|
93
|
+
// Sell, and get the company data and the receipt layout in the same call.
|
|
94
|
+
const result = await api.sellReceiptWithCompany({
|
|
95
|
+
items,
|
|
96
|
+
tip,
|
|
97
|
+
payments: [{ method: KeckPaymentMethod.cash, amountCents: dueCents, tenderedCents: 2000 }],
|
|
85
98
|
});
|
|
86
99
|
|
|
87
|
-
// Layout: a plain data model (lines, alignment, columns, QR code).
|
|
88
|
-
//
|
|
89
|
-
|
|
100
|
+
// Layout: a plain data model (lines, alignment, columns, QR code). The server
|
|
101
|
+
// sends it as `layout` (80 mm), and it always wins; only without it does
|
|
102
|
+
// receiptLayoutFromResult build one from the same response (test banners
|
|
103
|
+
// included) in `fallbackPaperSize` (default 'mm58'). The print width is chosen
|
|
104
|
+
// by the print path (`paperSize` below), never by this helper.
|
|
105
|
+
const layout = receiptLayoutFromResult(result);
|
|
90
106
|
|
|
91
107
|
// Character grid: exactly 32 (58 mm) or 48 (80 mm) characters per line.
|
|
92
108
|
// Screen, printed receipt and PDF all use this one grid.
|
|
93
|
-
const grid = renderReceiptGrid(layout);
|
|
109
|
+
const grid = renderReceiptGrid(layout, { charsPerLine: 32 }); // grid.lines[i].text, .bold, .kind, .qr
|
|
94
110
|
|
|
95
111
|
// ESC/POS bytes for a thermal printer; they print exactly the grid lines.
|
|
96
|
-
const bytes = escPosLayoutBytes(layout);
|
|
112
|
+
const bytes = escPosLayoutBytes(layout, { paperSize: 'mm58' });
|
|
97
113
|
```
|
|
98
114
|
|
|
99
115
|
The receipt returned by `sellReceiptWithCompany` (or `sellReceipt`) has already
|
|
100
116
|
been signed, chained and stored in the data capture log (*DEP*) by the backend.
|
|
101
117
|
|
|
118
|
+
**Payments are mandatory.** Every sale carries `payments[]` (several per receipt:
|
|
119
|
+
card plus cash and so on); card details (`provider`, `providerPaymentId`,
|
|
120
|
+
`providerData`) belong to the single payment. `receiptDueCents` computes the
|
|
121
|
+
amount the payments must match, exactly as the backend does (tax buckets,
|
|
122
|
+
discount vouchers, tips, value vouchers). If they do not match, the backend
|
|
123
|
+
rejects the receipt with `payments_sum_mismatch` without using up a receipt
|
|
124
|
+
number; `paymentsExpectedCents(error)` gives its amount. The package never
|
|
125
|
+
retries on its own: a card payment has already been charged.
|
|
126
|
+
|
|
127
|
+
The list may be empty only when the amount due is 0. The single
|
|
128
|
+
`paymentMethod` of 0.x and the card fields beside it (`creditCardProvider`,
|
|
129
|
+
`cardPaymentId`, `cardPaymentData`) are rejected before anything is sent.
|
|
130
|
+
`receiptDueCents` needs `tipRecipient` (`'owner'` or `'staff'`, the role of the
|
|
131
|
+
signed-in register user) as soon as a tip has no `recipients`: an owner's tip
|
|
132
|
+
is turnover, spread over the VAT rates of the goods and discounted with them,
|
|
133
|
+
while a staff tip goes untouched into the 0 % bucket. Only the register knows
|
|
134
|
+
which one applies, so the helper never guesses.
|
|
135
|
+
|
|
102
136
|
## What a fiscal cash register in Austria must do
|
|
103
137
|
|
|
104
138
|
The obligation to use a fiscal cash register and to issue receipts is set out
|
|
@@ -166,17 +200,70 @@ adapter:
|
|
|
166
200
|
| `…/printing` | ESC/POS generation (byte sequences for thermal printers), QR sizing, printing over WebUSB. |
|
|
167
201
|
| `…/payments` | Stripe payment links, Hobex cloud (both HTTP endpoints of the backend), and Hobex **HPS** via **Kasseneck Connect** (local device agent that talks to the terminal). |
|
|
168
202
|
| `…/register` | Sign-in for the browser register: pair and unpair a device, list its users and sessions, sign in by PIN, renew and end the session. |
|
|
169
|
-
| `…/
|
|
203
|
+
| `…/pos` | Tile register: register settings (business-wide and per device), article groups and articles for tiles, discount distribution per VAT rate, scopes of register permissions, network printers and print jobs, tip recipients, the register's message catalogue. |
|
|
170
204
|
| `…/partner` | Partner API (`/v3`, English): create businesses, FinanzOnline link, signature, cash registers, credentials, webhooks with signature verification. **Belongs on a server.** |
|
|
171
|
-
| `…/
|
|
172
|
-
| `…/
|
|
205
|
+
| `…/stored` | Stored Firestore documents (inner form, German) as the same English models the `/v3` wire returns: receipts with company and layout, register settings, articles. For clients that read Firestore directly, such as the admin panel. |
|
|
206
|
+
| `…/invoice` | Invoice API: create and search customers, issue finalised invoices, credit notes and cancellation, PDF and e-invoice XML, the contract as data. **Belongs on a server.** |
|
|
207
|
+
| `…/invoice/calc` | Pure calculation core for invoice totals (integers, no transport, no dependency beyond types). Safe to run in the browser. |
|
|
173
208
|
| `…/react` | Thin React adapter that renders a receipt layout or a receipt sheet. Needs React. |
|
|
174
|
-
| `…/fixtures/*` | Golden receipts (JSON): inputs `
|
|
209
|
+
| `…/fixtures/*` | Golden receipts (JSON): inputs `receipts/<name>.json`, promised line output `expected/<name>.lines.json`, `manifest.json` with checksums. The backend, the browser register and the Flutter package check against the same files. |
|
|
175
210
|
|
|
176
211
|
Every exported function carries its documentation as TSDoc in the shipped type
|
|
177
212
|
declarations, so your editor shows it on hover. That is also the reference for
|
|
178
213
|
the partner and invoice endpoints; this README shows how to use the client.
|
|
179
214
|
|
|
215
|
+
## Base URLs and the `/v3` marker
|
|
216
|
+
|
|
217
|
+
1.x speaks only the English API `/v3`. Every field name, every value your code
|
|
218
|
+
branches on and every error code is English; texts for people (`message`,
|
|
219
|
+
`serverMessage`, `nextSteps`, the printed receipt) stay German, as do the
|
|
220
|
+
terms of the BMF and FinanzOnline.
|
|
221
|
+
|
|
222
|
+
| Path | Default | Option | Used for |
|
|
223
|
+
|---|---|---|---|
|
|
224
|
+
| public | `https://api.kasseneck.at/v3` (`DEFAULT_BASE_URL`) | `baseUrl` | receipts with `apiKeyAuth`, reports, payments, FinanzOnline, invoice and partner API |
|
|
225
|
+
| register (POS) | `https://kasse.kasseneck.at/api/v3` (`POS_BASE_URL`) | `posBaseUrl` | pairing, sign-in, settings, articles, printers; with `registerUserAuth` also receipts, cancellation and receipt email |
|
|
226
|
+
| same origin | `/api/v3` | `posBaseUrl: '/api/v3'` | the browser register served from `kasse.kasseneck.at` itself |
|
|
227
|
+
|
|
228
|
+
The package picks the path per call; `PUBLIC_CALLS` and `POS_CALLS` list which
|
|
229
|
+
call goes where. A base of your own (a proxy, the emulator) must end in `/v3`
|
|
230
|
+
once trailing slashes are removed, otherwise creating the client throws a
|
|
231
|
+
`KasseneckValidationError` right away. There is no `/v1` and no bare `/api` in
|
|
232
|
+
the 1.x line.
|
|
233
|
+
|
|
234
|
+
```ts
|
|
235
|
+
import { createKasseneckApi, registerUserAuth } from '@kreiseck/kasseneck-api';
|
|
236
|
+
|
|
237
|
+
// Browser register on kasse.kasseneck.at: same origin, no CORS involved.
|
|
238
|
+
const pos = createKasseneckApi({
|
|
239
|
+
auth: registerUserAuth({ getIdToken, getSessionId, cashregisterId: 'kasse-1' }),
|
|
240
|
+
posBaseUrl: '/api/v3',
|
|
241
|
+
clientHeader: 'kasse-web/2026.09.28', // optional; default kasseneck-api/<version>
|
|
242
|
+
});
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**The marker, fail closed.** Each request to a Kasseneck base (the two hosts
|
|
246
|
+
above over https, or a relative path) carries `Kasseneck-Api-Version: v3` and
|
|
247
|
+
`Kasseneck-Client`. Each response is checked **before** its body is read:
|
|
248
|
+
|
|
249
|
+
- HTTP 200 with `text/html` is the hosting fallback page; the call never
|
|
250
|
+
arrived: `KasseneckApiError` with `code: 'route_missing'`.
|
|
251
|
+
- A response without `Kasseneck-Api-Version: v3` came from an edge that does
|
|
252
|
+
not speak `/v3`: `code: 'dialect_mismatch'` with `outcome: 'unknown'`
|
|
253
|
+
(behind an old edge a receipt may have been signed). See [Errors](#errors).
|
|
254
|
+
- HTTP 404 with the marker and an error envelope is how `/v3` answers an
|
|
255
|
+
unknown endpoint: `code: 'not_found'`.
|
|
256
|
+
|
|
257
|
+
The package never falls back to another version. A mismatch is an error, not
|
|
258
|
+
a reason to try `/v1`.
|
|
259
|
+
|
|
260
|
+
**Browser on another origin.** A browser that calls `https://api.kasseneck.at/v3`
|
|
261
|
+
from a foreign origin sends a CORS preflight that asks for the two headers
|
|
262
|
+
above. Until the backend allows them in the `/v3` preflight, set
|
|
263
|
+
`omitKasseneckHeaders: true` on such a client. Only the request headers are
|
|
264
|
+
dropped; the response check stays. The browser register on its own origin
|
|
265
|
+
(`/api/v3`) and any Node process need nothing of this.
|
|
266
|
+
|
|
180
267
|
## Authentication
|
|
181
268
|
|
|
182
269
|
The client takes an **exchangeable authentication**: an object that supplies
|
|
@@ -208,8 +295,8 @@ const register = registerUserAuth({
|
|
|
208
295
|
|
|
209
296
|
Six calls run **without any identity**, because they are how an identity comes
|
|
210
297
|
into being or how a device manages itself. They live in `…/register` and take
|
|
211
|
-
**no authentication**, only the connection settings (
|
|
212
|
-
`fetch`):
|
|
298
|
+
**no authentication**, only the connection settings (`posBaseUrl`, timeout,
|
|
299
|
+
`fetch`); they always go to the register path:
|
|
213
300
|
|
|
214
301
|
| Call | Proof instead of authentication |
|
|
215
302
|
|---|---|
|
|
@@ -226,6 +313,28 @@ const paired = await pairRegisterDevice({ code: 'K7NPQR34', label: 'Bar' });
|
|
|
226
313
|
const session = await registerUserLogin({ ...paired, userId: 'ru-1', pin: '1234' });
|
|
227
314
|
```
|
|
228
315
|
|
|
316
|
+
`paired` carries `companyName`, `cashregisterLabel` and `testEnvironment`. A
|
|
317
|
+
device record stored under 0.x (device id and secret) keeps working: the calls
|
|
318
|
+
only send the device credentials, no new pairing is needed.
|
|
319
|
+
|
|
320
|
+
Sign-in errors carry a code from `REGISTER_ERROR_CODES`. Decide with
|
|
321
|
+
`isRegisterError(error, code)`; seconds to wait, the name of the device that
|
|
322
|
+
holds a session and the like come from `registerErrorDetails(error)`
|
|
323
|
+
(`deviceLabel`, `takeoverAllowed`, `retryAfterSec`, `distanceM`,
|
|
324
|
+
`pairedDevices`, `licenses`), never from the message text:
|
|
325
|
+
|
|
326
|
+
```ts
|
|
327
|
+
import { isRegisterError, registerErrorDetails, registerPinLogin } from '@kreiseck/kasseneck-api/register';
|
|
328
|
+
|
|
329
|
+
try {
|
|
330
|
+
await registerPinLogin({ ...paired, pin });
|
|
331
|
+
} catch (error) {
|
|
332
|
+
if (isRegisterError(error, 'too_many_attempts')) {
|
|
333
|
+
showWait(registerErrorDetails(error).retryAfterSec);
|
|
334
|
+
} else throw error;
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
229
338
|
With `session.customToken` the app signs in to the sign-in service; the
|
|
230
339
|
resulting ID token together with `session.sessionId` feeds `registerUserAuth`.
|
|
231
340
|
`renewRegisterSession` and `endRegisterSession` then run with
|
|
@@ -261,7 +370,7 @@ For the same reason a receipt line's `quantity` is a **whole number**. A
|
|
|
261
370
|
fractional one is rejected before anything is sent.
|
|
262
371
|
|
|
263
372
|
The invoice API has its own units: unit prices in cents or micro-euros,
|
|
264
|
-
quantities with up to three decimals. See [Invoice API](#invoice-api-
|
|
373
|
+
quantities with up to three decimals. See [Invoice API](#invoice-api-invoice).
|
|
265
374
|
|
|
266
375
|
## Errors
|
|
267
376
|
|
|
@@ -271,18 +380,106 @@ a type guard:
|
|
|
271
380
|
|
|
272
381
|
| Class | Guard | Meaning |
|
|
273
382
|
|---|---|---|
|
|
274
|
-
| `KasseneckApiError` | `isKasseneckApiError` | The backend
|
|
275
|
-
| `KasseneckHttpError` | `isKasseneckHttpError` | The response was not a usable envelope: HTTP 404/500, empty body,
|
|
276
|
-
| `KasseneckNetworkError` | `isKasseneckNetworkError` | No response at all: network down, DNS, aborted connection or timeout (`timedOut`). |
|
|
383
|
+
| `KasseneckApiError` | `isKasseneckApiError` | The backend answered with an error envelope (locked register, missing module, invalid parameter), or the package refused the response (`route_missing`, `dialect_mismatch`, `response_unreadable`). Carries `code`, `outcome`, `serverMessage` (German display text) and `details`. |
|
|
384
|
+
| `KasseneckHttpError` | `isKasseneckHttpError` | The response was not a usable envelope: HTTP 404/500 without envelope, empty body, text instead of JSON. `reason` tells the cases apart; `outcome` as below. |
|
|
385
|
+
| `KasseneckNetworkError` | `isKasseneckNetworkError` | No response at all: network down, DNS, aborted connection or timeout (`timedOut`). `outcome` as below. |
|
|
277
386
|
| `KasseneckAuthError` | `isKasseneckAuthError` | The request was never sent because authentication failed (missing credentials, or the token or session provider threw). |
|
|
278
|
-
| `KasseneckValidationError` | `isKasseneckValidationError` | Wrong shape. `scope: 'request'`: your input breaks a rule the package knows before sending. `scope: 'response'`: the backend reported success but the payload lacked what
|
|
387
|
+
| `KasseneckValidationError` | `isKasseneckValidationError` | Wrong shape. `scope: 'request'`: your input breaks a rule the package knows before sending. `scope: 'response'`: the backend reported success but the payload of a non-signing call lacked what it promises (on `createReceipt` and `cancelReceipt` that is `response_unreadable` instead). |
|
|
279
388
|
|
|
280
389
|
**None of them ever contains a secret**: no key, no token, neither the sent nor
|
|
281
390
|
the received body.
|
|
282
391
|
|
|
283
|
-
**Decide on the code, not the text.**
|
|
284
|
-
|
|
285
|
-
|
|
392
|
+
**Decide on the code, not the text.** Every code is English, lower case,
|
|
393
|
+
`snake_case`, and every endpoint group ships its catalogue with a guard:
|
|
394
|
+
|
|
395
|
+
| Catalogue | Guard | Where |
|
|
396
|
+
|---|---|---|
|
|
397
|
+
| `RECEIPT_ERROR_CODES` | `isReceiptError` | `createReceipt`, `getReceipt` |
|
|
398
|
+
| `CANCELLATION_ERROR_CODES` | `isCancellationError` | `cancelReceipt` |
|
|
399
|
+
| `PAYMENT_ERROR_CODES` | `isPaymentError` | `payments[]` of a sale or cancellation |
|
|
400
|
+
| `RECEIPT_EMAIL_ERROR_CODES` | `isReceiptEmailError` | `sendReceiptEmail` |
|
|
401
|
+
| `REGISTER_ERROR_CODES` | `isRegisterError` (`…/register`) | pairing and sign-in |
|
|
402
|
+
| `POS_ERROR_CODES` | `isPosError` (`…/pos`) | settings, articles, printers, tip recipients |
|
|
403
|
+
| `PARTNER_ERROR_CODES` + `PARTNER_REQUEST_ERROR_CODES` | `isPartnerError` (`…/partner`) | partner API |
|
|
404
|
+
| `INVOICE_ERROR_CODES` + `INVOICE_REQUEST_ERROR_CODES` | `isInvoiceError` (`…/invoice`) | invoice API |
|
|
405
|
+
|
|
406
|
+
Every group has the same helpers: `is…ErrorCode(value)`, `…ErrorCode(error)`
|
|
407
|
+
(the code if the group knows it), `is…Error(error, code?)` (a type guard; without
|
|
408
|
+
`code` it asks whether the error belongs to the group) and
|
|
409
|
+
`…FieldErrors(error)` for the fields of a `validation` error
|
|
410
|
+
(`receiptFieldErrors`, `cancellationFieldErrors`, `paymentFieldErrors`,
|
|
411
|
+
`receiptEmailFieldErrors`, `registerFieldErrors`, `posFieldErrors`,
|
|
412
|
+
`invoiceFieldErrors`, `partnerFieldErrors`). Each list holds the group's own
|
|
413
|
+
codes, then the sign-in and edge codes that can reach the same call, then the
|
|
414
|
+
codes the package sets itself (`CLIENT_ERROR_CODES`: `route_missing`, and
|
|
415
|
+
`response_unreadable` on receipts and cancellations). A sale can fail with a
|
|
416
|
+
code from `RECEIPT_ERROR_CODES` or `PAYMENT_ERROR_CODES`, a cancellation with
|
|
417
|
+
one from `CANCELLATION_ERROR_CODES` or `PAYMENT_ERROR_CODES`. The invoice and
|
|
418
|
+
partner catalogues stay exactly the server's; their `…_REQUEST_ERROR_CODES`
|
|
419
|
+
add the rest. The German `serverMessage` is for display and may change.
|
|
420
|
+
|
|
421
|
+
Validation is strict: the 0.x ways of paying (`paymentMethod` and its card
|
|
422
|
+
fields), unknown keys in tips, layout options, register settings and the
|
|
423
|
+
receipt email, and values outside a settings field's value list throw a
|
|
424
|
+
`KasseneckValidationError` before anything is sent, instead of being dropped
|
|
425
|
+
silently. For a layout option of 0.x the message names its English successor.
|
|
426
|
+
|
|
427
|
+
### `outcome: 'unknown'`: never retry, look it up
|
|
428
|
+
|
|
429
|
+
`KasseneckApiError`, `KasseneckHttpError` and `KasseneckNetworkError` carry
|
|
430
|
+
`outcome`. `'rejected'` means no operation with an effect is left open: no
|
|
431
|
+
receipt was signed, nothing went to FinanzOnline and no money moved, so
|
|
432
|
+
retrying the same request does not create a second receipt or charge (whether
|
|
433
|
+
it helps depends on the code). `'unknown'` means the operation **may have been carried out**, for
|
|
434
|
+
`createReceipt` a signed receipt in the chain. Then never send it again: read
|
|
435
|
+
the result back (`getReceipt`, `listMyReceipts`, the original of a
|
|
436
|
+
cancellation) and continue from there. `isOutcomeUnknown(error)` covers all
|
|
437
|
+
three classes. The outcome is unknown for:
|
|
438
|
+
|
|
439
|
+
- `dialect_mismatch`, `receipt_outcome_unknown`, `cancellation_outcome_unknown`;
|
|
440
|
+
- `response_translation_failed`, unless `details.handled === false`;
|
|
441
|
+
- `response_unreadable`: a signing or money-moving call reported success,
|
|
442
|
+
but the response lacks what the call promises (no receipt, no reference, no
|
|
443
|
+
remaining quantities, no Hobex receipt, no captured payment intent);
|
|
444
|
+
- on the calls with an effect: the signing calls `createReceipt`,
|
|
445
|
+
`cancelReceipt` and `financeWebService`, and the money calls `hobexPay`
|
|
446
|
+
(`hobexPayApi`, charges a card), `hobexRefund` (`hobexRefundApi`) and
|
|
447
|
+
`stripeCaptureIntent`: a network error or timeout after sending began, HTTP
|
|
448
|
+
5xx, and HTTP 200 with the `Kasseneck-Api-Version: v3` marker but an empty,
|
|
449
|
+
non-JSON (also `text/html`) or status-less body (`KasseneckHttpError`,
|
|
450
|
+
`reason` `empty-body`, `not-json` or `missing-status`). HTML without the
|
|
451
|
+
marker stays `route_missing` with `'rejected'`: no function saw the call.
|
|
452
|
+
|
|
453
|
+
On the money calls an unknown outcome means the card may have been charged,
|
|
454
|
+
the refund may have gone through, the payment may have been captured. A
|
|
455
|
+
rejection of `hobexRefund` throws a `KasseneckApiError` with its `code`; it
|
|
456
|
+
never returns `false`, because a `false` on an unclear outcome invites a
|
|
457
|
+
second refund.
|
|
458
|
+
|
|
459
|
+
**Never retry these six calls, and never put a retrying layer under the
|
|
460
|
+
package.** A `fetch` passed in `options.fetch` (or a proxy or service worker in
|
|
461
|
+
front of it) must not resend a request by itself after a network error, a
|
|
462
|
+
timeout or a 5xx: a silent second send is a second signed receipt, a second
|
|
463
|
+
charge or a second refund, and the package cannot see it. Look the result up
|
|
464
|
+
instead (`getReceipt`, `listMyReceipts`, the Hobex transaction by its
|
|
465
|
+
`transactionId`, the Stripe session).
|
|
466
|
+
|
|
467
|
+
`outcome` only covers signing and the money calls. After a network error on
|
|
468
|
+
`issueInvoice` an invoice may still have been issued; retry it with the same
|
|
469
|
+
`idempotencyKey`.
|
|
470
|
+
|
|
471
|
+
```ts
|
|
472
|
+
import { isOutcomeUnknown, paymentsExpectedCents } from '@kreiseck/kasseneck-api';
|
|
473
|
+
|
|
474
|
+
try {
|
|
475
|
+
await api.sellReceipt({ items, payments });
|
|
476
|
+
} catch (error) {
|
|
477
|
+
if (isOutcomeUnknown(error)) return reloadReceiptsAndAsk(); // never sell again blindly
|
|
478
|
+
const expected = paymentsExpectedCents(error); // payments_sum_mismatch
|
|
479
|
+
if (expected !== undefined) return askAgain(expected);
|
|
480
|
+
throw error;
|
|
481
|
+
}
|
|
482
|
+
```
|
|
286
483
|
|
|
287
484
|
## Receipts
|
|
288
485
|
|
|
@@ -290,17 +487,48 @@ The facade from `createKasseneckApi` offers `sellReceipt` and
|
|
|
290
487
|
`sellReceiptWithCompany`, `zeroReceipt` for a zero receipt (*Nullbeleg*),
|
|
291
488
|
`getReceipt` and `getReceiptWithCompany`, `listMyReceipts`, `cancelReceipt`,
|
|
292
489
|
`sendReceiptEmail`, the report downloads, the FinanzOnline status queries
|
|
293
|
-
(`getCashboxStatus`, `getSignatureStatus`)
|
|
490
|
+
(`getCashboxStatus`, `getSignatureStatus`), `getReportV2({ start, end })` for
|
|
491
|
+
the raw receipts and company data of a period, and the Stripe and Hobex cloud
|
|
294
492
|
payments.
|
|
295
493
|
|
|
494
|
+
The models are English throughout: the company has `taxNumber` and `vatId`, a
|
|
495
|
+
receipt `headerVersionId`, `layoutRuleset` and `registrationInfo`, a receipt
|
|
496
|
+
in the list `cancellationStatus` (`none`, `partial`, `full`, or `'unknown'` for
|
|
497
|
+
a value this version does not know: then offer no cancellation). The same
|
|
498
|
+
rule holds for print job states and register settings: a value the package
|
|
499
|
+
does not know is shown as `'unknown'` or kept as sent, never mapped onto a
|
|
500
|
+
known one.
|
|
501
|
+
|
|
296
502
|
**Layout rule sets.** `buildReceiptLayout` sets receipts according to a
|
|
297
|
-
numbered rule set. Without the `
|
|
298
|
-
(`
|
|
503
|
+
numbered rule set. Without the `ruleset` option the current one applies
|
|
504
|
+
(`CURRENT_LAYOUT_RULESET`, currently 2: zero receipts carry a block
|
|
299
505
|
"Prüfangaben" with the registration data, which `getReceiptWithCompany`
|
|
300
|
-
returns as `
|
|
506
|
+
returns as `registrationInfo`). The backend stores the rule set with each receipt,
|
|
301
507
|
and `getReceiptWithCompany` also returns the backend-built `layout` in that
|
|
302
508
|
rule set, so an old receipt looks the way it did when it was issued.
|
|
303
509
|
|
|
510
|
+
**Print and show the server's layout.** `layout` in a `…WithCompany` result
|
|
511
|
+
is a `ReceiptLayout` (`ruleset`, banner lines with `tone: 'receipt_type' |
|
|
512
|
+
'warning'`) and goes unchanged to `escPosLayoutBytes`, `eposPrintXml`,
|
|
513
|
+
`receiptSheet` and the React views; `receiptLayoutFromResult(result)` returns
|
|
514
|
+
it whenever it is there. Only without it does the helper build the layout,
|
|
515
|
+
in `fallbackPaperSize` (default `mm58`, as in 0.x). The server layout is
|
|
516
|
+
always 80 mm: on 58 mm paper choose the width at the print path
|
|
517
|
+
(`escPosLayoutBytes(layout, { paperSize: 'mm58' })`, `charsPerLine: 32`); the VAT
|
|
518
|
+
table then keeps the columns of the 80 mm grid. On the public channel only this layout carries the card block, because
|
|
519
|
+
the receipt itself comes without provider data. If you build the layout
|
|
520
|
+
yourself, pass the options from the same response:
|
|
521
|
+
|
|
522
|
+
```ts
|
|
523
|
+
buildReceiptLayout(receipt, company, { paperSize: 'mm80', testCashregister, testSignature, registrationInfo });
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
The options of 0.x (`testKasse`, `testSignatur`, `pruefangaben`,
|
|
527
|
+
`regelwerk`) are rejected with a `KasseneckValidationError` instead of being
|
|
528
|
+
ignored: a test receipt must never lose its "TESTKASSE" banner. The printed
|
|
529
|
+
text stays German, and the CSS classes of the React banner stay
|
|
530
|
+
`keck-receipt-banner--belegart` and `--warnung`.
|
|
531
|
+
|
|
304
532
|
Times on receipts are read as **Vienna wall-clock time**
|
|
305
533
|
(`parseServerTimeStamp`), never through `new Date(text)`.
|
|
306
534
|
|
|
@@ -311,9 +539,12 @@ A cancellation (*Storno*) refers to the original receipt, in full or in part:
|
|
|
311
539
|
```ts
|
|
312
540
|
const result = await api.cancelReceipt({
|
|
313
541
|
receipt: original, // or: cashregisterId + originalReceiptId
|
|
314
|
-
reason: '
|
|
542
|
+
reason: 'input_error', // catalogue: CANCELLATION_REASONS
|
|
315
543
|
items: [{ index: 0, quantity: 1 }], // omit = cancel all remaining quantities
|
|
316
544
|
note: 'Customer only wanted one', // internal, stored, never printed
|
|
545
|
+
// Refund per original payment (negative, refundOf = id of that payment).
|
|
546
|
+
// Omit it and the server refunds the remainder of every original payment.
|
|
547
|
+
payments: [{ method: KeckPaymentMethod.cash, amountCents: -390, refundOf: 'p1' }],
|
|
317
548
|
});
|
|
318
549
|
result.receipt; // the signed cancellation receipt (receiptType cancellation)
|
|
319
550
|
result.cancellationOf; // reference to the original
|
|
@@ -328,20 +559,20 @@ fully cancelled receipt cannot be cancelled again. On a receipt you have read,
|
|
|
328
559
|
cancellation dialog); the server has the final word.
|
|
329
560
|
|
|
330
561
|
Every business error of `cancelReceipt` carries `KasseneckApiError.code` from
|
|
331
|
-
`CANCELLATION_ERROR_CODES` (for example `
|
|
332
|
-
`
|
|
562
|
+
`CANCELLATION_ERROR_CODES` (for example `already_cancelled`,
|
|
563
|
+
`quantity_exceeds_remaining`, `own_receipts_only`):
|
|
333
564
|
|
|
334
565
|
```ts
|
|
335
566
|
import { isKasseneckApiError, isCancellationErrorCode } from '@kreiseck/kasseneck-api';
|
|
336
567
|
|
|
337
568
|
try {
|
|
338
|
-
await api.cancelReceipt({ receipt: original, reason: '
|
|
569
|
+
await api.cancelReceipt({ receipt: original, reason: 'input_error' });
|
|
339
570
|
} catch (error) {
|
|
340
571
|
if (!isKasseneckApiError(error) || !isCancellationErrorCode(error.code)) throw error;
|
|
341
572
|
switch (error.code) {
|
|
342
|
-
case '
|
|
343
|
-
case '
|
|
344
|
-
case '
|
|
573
|
+
case 'already_cancelled': // show the receipt as cancelled, disable the button
|
|
574
|
+
case 'quantity_exceeds_remaining': // reload the remaining quantities (someone was faster)
|
|
575
|
+
case 'own_receipts_only': // ask a manager
|
|
345
576
|
showHint(error.code);
|
|
346
577
|
break;
|
|
347
578
|
default:
|
|
@@ -350,11 +581,14 @@ try {
|
|
|
350
581
|
}
|
|
351
582
|
```
|
|
352
583
|
|
|
353
|
-
**
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
584
|
+
**Card refunds.** The terminal refund needs the transaction id of the original
|
|
585
|
+
card payment: `payments[].providerPaymentId` of the original receipt. Only the
|
|
586
|
+
register channel (`registerUserAuth`, `kasse.kasseneck.at/api/v3`) returns it;
|
|
587
|
+
the public channel leaves provider data out. The refund payment then carries
|
|
588
|
+
the id of the refund itself. `cancellation_outcome_unknown` means the
|
|
589
|
+
cancellation may have been booked: read the original again, never retry.
|
|
590
|
+
|
|
591
|
+
`createCancelReceipt` and cancelling through `createReceipt` are gone in 1.0.
|
|
358
592
|
|
|
359
593
|
**Vouchers.** A value voucher is only mirrored on a full cancellation (without
|
|
360
594
|
`items`); it cannot be split. A discount voucher is already part of the
|
|
@@ -378,11 +612,11 @@ it omit that line.
|
|
|
378
612
|
const confirmation = await api.sendReceiptEmail({
|
|
379
613
|
fullReceiptId: original.fullReceiptId, // or: await api.generateFullReceiptId(receiptId)
|
|
380
614
|
to: 'guest@example.at',
|
|
381
|
-
|
|
615
|
+
language: 'de', // optional; the backend currently only uses 'de'
|
|
382
616
|
});
|
|
383
617
|
confirmation.to; // address as the backend logged it (trimmed, lower case)
|
|
384
618
|
confirmation.at; // time, ISO with Vienna offset
|
|
385
|
-
confirmation.via; // '
|
|
619
|
+
confirmation.via; // 'own' | 'platform' | 'platform_fallback' | null
|
|
386
620
|
```
|
|
387
621
|
|
|
388
622
|
The email contains a **link to the public receipt page**, not a PDF
|
|
@@ -394,8 +628,8 @@ The cash register comes from the authentication (`cashregister-token` header or
|
|
|
394
628
|
the parameter set by `registerUserAuth`), not from the options. A receipt of
|
|
395
629
|
another register therefore gets the same answer as a receipt that does not
|
|
396
630
|
exist. The codes are in `RECEIPT_EMAIL_ERROR_CODES` (`isReceiptEmailErrorCode`):
|
|
397
|
-
`
|
|
398
|
-
24 hours, 30 per register per hour) and `
|
|
631
|
+
`invalid_address`, `receipt_not_found`, `too_many_requests` (5 emails per
|
|
632
|
+
receipt in 24 hours, 30 per register per hour) and `send_failed`.
|
|
399
633
|
|
|
400
634
|
## Receipt printing: QR code, logo, printers
|
|
401
635
|
|
|
@@ -408,34 +642,34 @@ receipt the worst possible result. So this package calculates the size instead
|
|
|
408
642
|
of setting it:
|
|
409
643
|
|
|
410
644
|
```ts
|
|
411
|
-
import {
|
|
645
|
+
import { qrSizingFor, QR_PRINT_WIDTH_DOTS } from '@kreiseck/kasseneck-api/printing';
|
|
412
646
|
|
|
413
|
-
const qrSize =
|
|
414
|
-
// qrSize.
|
|
415
|
-
// qrSize.
|
|
647
|
+
const qrSize = qrSizingFor({ payload: receipt.qr, paperWidthDots: QR_PRINT_WIDTH_DOTS.mm58 });
|
|
648
|
+
// qrSize.moduleDots: dots per module; null = does not fit even with the exception size
|
|
649
|
+
// qrSize.belowMinimum: printed, but below 4 dots per module
|
|
416
650
|
```
|
|
417
651
|
|
|
418
|
-
On the receipt path this happens automatically. `
|
|
652
|
+
On the receipt path this happens automatically. `qrModuleSize` is a **cap**, not
|
|
419
653
|
a target: the largest size that fits is printed, at most the cap. `auto` (the
|
|
420
654
|
default) caps at 6 dots per module, as in the Dart twin and on the Epson path;
|
|
421
|
-
`
|
|
655
|
+
`small` caps at 4, `medium` at 6, `large` at 8. All print paths use error
|
|
422
656
|
correction level M.
|
|
423
657
|
|
|
424
658
|
```ts
|
|
425
|
-
import {
|
|
659
|
+
import { escPosLayoutResult } from '@kreiseck/kasseneck-api/receipt';
|
|
426
660
|
|
|
427
|
-
const { bytes,
|
|
428
|
-
|
|
429
|
-
|
|
661
|
+
const { bytes, qrError, qrFallback } = escPosLayoutResult(layout, {
|
|
662
|
+
qrModuleSize: 'large', // 'auto' | 'small' | 'medium' | 'large'
|
|
663
|
+
qrMode: 'nativeModel1', // older printers that only support model 1
|
|
430
664
|
qrMatrix: matrixFor, // fallback: the QR code as an image instead of none
|
|
431
665
|
});
|
|
432
666
|
```
|
|
433
667
|
|
|
434
668
|
The Epson ePOS path (`eposPrintXml` / `eposDirectPrint`) calculates the same
|
|
435
|
-
way; `
|
|
669
|
+
way; `eposPrintXmlResult` returns `{ xml, qrError, qrFallback }`. The default
|
|
436
670
|
there is also `auto`.
|
|
437
671
|
|
|
438
|
-
`
|
|
672
|
+
`qrError` means "receipt without QR code": tell the customer. `qrFallback`
|
|
439
673
|
means "printed, but the configured mode does not suit this device": tell the
|
|
440
674
|
manager. The image fallback only runs with a `qrMatrix` function that turns
|
|
441
675
|
the payload into a finished matrix; the package itself neither encodes QR
|
|
@@ -448,25 +682,26 @@ logo, QR code and the Kasseneck logo at the end, with sizes as a share of the
|
|
|
448
682
|
sheet width and in lines (one line = two character widths).
|
|
449
683
|
|
|
450
684
|
```tsx
|
|
451
|
-
import {
|
|
685
|
+
import { ReceiptSheetView } from '@kreiseck/kasseneck-api/react';
|
|
452
686
|
|
|
453
|
-
const
|
|
454
|
-
const
|
|
687
|
+
const result = await api.getReceiptWithCompany(receiptId);
|
|
688
|
+
const { company, logoScale } = result;
|
|
689
|
+
const layout = receiptLayoutFromResult(result);
|
|
455
690
|
|
|
456
|
-
<
|
|
691
|
+
<ReceiptSheetView
|
|
457
692
|
layout={layout}
|
|
458
|
-
logo={company.logoUrl ? { url: company.logoUrl,
|
|
459
|
-
|
|
693
|
+
logo={company.logoUrl ? { url: company.logoUrl, size: logoScale } : null}
|
|
694
|
+
brandMark={company.showKreiseckLogo}
|
|
460
695
|
renderQr={(data) => <QrSvg data={data} />}
|
|
461
696
|
/>
|
|
462
697
|
```
|
|
463
698
|
|
|
464
699
|
```ts
|
|
465
|
-
import { escPosLayoutBytes,
|
|
700
|
+
import { escPosLayoutBytes, logoDimensions, rasterizeLogo } from '@kreiseck/kasseneck-api/receipt';
|
|
466
701
|
|
|
467
|
-
const logoSize =
|
|
468
|
-
const raster =
|
|
469
|
-
escPosLayoutBytes(layout, { paperSize: 'mm80', logo: {
|
|
702
|
+
const logoSize = logoDimensions({ size: 'M', pixelWidth: image.width, pixelHeight: image.height }, 48);
|
|
703
|
+
const raster = rasterizeLogo(imageData.data, image.width, image.height, logoSize, 48);
|
|
704
|
+
escPosLayoutBytes(layout, { paperSize: 'mm80', logo: { size: 'M', pixelWidth: image.width, pixelHeight: image.height, raster }, brandMark: true });
|
|
470
705
|
```
|
|
471
706
|
|
|
472
707
|
Logo sizes: S 42 % × 5 lines, M 62 % × 8, L 80 % × 12, XL 94 % × 16, always
|
|
@@ -480,10 +715,91 @@ The package generates ESC/POS bytes and ePOS XML, and it ships three ways to
|
|
|
480
715
|
deliver them: **WebUSB** (`usbConnectPrinter`, `usbPrint` in `…/printing`, for
|
|
481
716
|
Chromium-based browsers), **Epson ePOS over HTTP** (`eposDirectPrint` in
|
|
482
717
|
`…/receipt`) and **print jobs** for network printers managed by the backend
|
|
483
|
-
(`listMyPrinters`, `createPrintJob` in `…/
|
|
718
|
+
(`listMyPrinters`, `createPrintJob` in `…/pos`). Bluetooth, serial ports and
|
|
484
719
|
raw TCP sockets are up to your application. PDF generation is not part of the
|
|
485
720
|
package.
|
|
486
721
|
|
|
722
|
+
## Register settings, articles and printers (`./pos`)
|
|
723
|
+
|
|
724
|
+
The calls of the tile register run on the register path and take a transport
|
|
725
|
+
from `createTransport` with the same options as `createKasseneckApi`.
|
|
726
|
+
Settings come as `{ business, device }` with English keys and values
|
|
727
|
+
(`theme: 'night'`, `receiptOutput: 'ask'`, `shortcuts.checkout`), merged with
|
|
728
|
+
the defaults `POS_BUSINESS_DEFAULTS` and `POS_DEVICE_DEFAULTS`.
|
|
729
|
+
|
|
730
|
+
**Send only what changed.** The server merges deeply, so a write carries only
|
|
731
|
+
the changed fields. `posSettingsChanges(before, after)` computes them; it sends
|
|
732
|
+
`vatRates` and `shortcuts` as whole maps, which is what the server expects:
|
|
733
|
+
|
|
734
|
+
```ts
|
|
735
|
+
import { createTransport, registerUserAuth } from '@kreiseck/kasseneck-api';
|
|
736
|
+
import { getPosSettings, setMyPosSettings, posSettingsChanges, isPosError, posFieldErrors } from '@kreiseck/kasseneck-api/pos';
|
|
737
|
+
|
|
738
|
+
const transport = createTransport({ auth: registerUserAuth({ getIdToken, getSessionId, cashregisterId }), posBaseUrl: '/api/v3' });
|
|
739
|
+
|
|
740
|
+
const before = await getPosSettings(transport);
|
|
741
|
+
const after = { ...before.business, theme: 'night' as const, fontSize: 'L' as const };
|
|
742
|
+
try {
|
|
743
|
+
await setMyPosSettings(transport, posSettingsChanges(before.business, after));
|
|
744
|
+
} catch (error) {
|
|
745
|
+
if (isPosError(error, 'validation')) showFieldErrors(posFieldErrors(error)); // [{ field: 'business.color', message }]
|
|
746
|
+
else throw error;
|
|
747
|
+
}
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
Never send back the whole merged block. A value the server knows and this
|
|
751
|
+
version does not (`theme: 'sepia'`) is read and kept as it is;
|
|
752
|
+
`unknownPosSettingValues(settings)` names such paths, so the interface can show
|
|
753
|
+
them as not editable. Left unchanged, such a value is not sent and stays on the
|
|
754
|
+
server; inside a whole block it would be rejected before sending. The same
|
|
755
|
+
check rejects unknown keys (also the German keys of 0.x such as `stil`),
|
|
756
|
+
values outside a field's list, a `vatRates` map without any rate switched on,
|
|
757
|
+
unknown shortcut actions and a key bound twice (`posShortcutConflict`).
|
|
758
|
+
Per-device settings go through `setMyRegisterDeviceSettings(transport, deviceId,
|
|
759
|
+
changes)`.
|
|
760
|
+
|
|
761
|
+
A state you stored yourself (for example settings cached in `localStorage`)
|
|
762
|
+
goes through `sanitizePosSettings` or `mergePosSettings` first: both drop the
|
|
763
|
+
German values of 0.x, so an old cache falls back to the defaults instead of
|
|
764
|
+
sending a German value.
|
|
765
|
+
|
|
766
|
+
The rest of `…/pos`: `listMyArticles` and `listMyArticleGroups` for the tiles
|
|
767
|
+
(`visible`, `quantityRule: 'piece' | 'decimal'`, `askQuantity`,
|
|
768
|
+
`maxQuantity`), `listMyPrinters`, `createPrintJob` and `getPrintJob` for
|
|
769
|
+
network printers (poll until `isPrintJobFinished(job)`; an unknown state is
|
|
770
|
+
`'unknown'` and ends the polling), `listMyTipRecipients`, `setMyPosLogo`, and
|
|
771
|
+
the register's text catalogue (`MESSAGES`, `LABELS`, `messageText`,
|
|
772
|
+
`labelText`). Text keys are English (`cancellation.outcome_unknown`,
|
|
773
|
+
`split.add_payment`), and so are the placeholders:
|
|
774
|
+
`messageText('checkout.locked', { reason })`. The rendered German texts are
|
|
775
|
+
the same as in 0.x.
|
|
776
|
+
|
|
777
|
+
## Stored documents (`./stored`)
|
|
778
|
+
|
|
779
|
+
For clients that read Firestore directly, such as the admin panel. Stored
|
|
780
|
+
documents keep the internal German form; `…/stored` turns them into the same
|
|
781
|
+
English models the `/v3` wire returns, following the server's own rules
|
|
782
|
+
(layout rule set, logo size, `TESTKASSE` banner, the settings merge):
|
|
783
|
+
|
|
784
|
+
```ts
|
|
785
|
+
import { fromStoredReceiptWithCompany, fromStoredPosSettings, invalidStoredPosSettings } from '@kreiseck/kasseneck-api/stored';
|
|
786
|
+
|
|
787
|
+
// The header version the receipt names (receipt.headerVersionId), plus the account document.
|
|
788
|
+
const result = fromStoredReceiptWithCompany(receiptDoc, {
|
|
789
|
+
headerVersion: { id: headerDoc.id, data: headerDoc.data() },
|
|
790
|
+
account: accountDoc.data(),
|
|
791
|
+
});
|
|
792
|
+
receiptLayoutFromResult(result); // the same layout getReceiptWithCompany returns
|
|
793
|
+
|
|
794
|
+
const settings = fromStoredPosSettings({ betrieb, geraet }); // stored register settings
|
|
795
|
+
invalidStoredPosSettings({ betrieb, geraet }); // paths the server would drop
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
`fromStoredReceipt`, `fromStoredCompany` and `fromStoredArticle` complete the
|
|
799
|
+
set. A broken document throws a `KasseneckValidationError`. There is no
|
|
800
|
+
reader for stored invoices: the server computes the invoice view, so read it
|
|
801
|
+
with `getInvoice` and `listInvoices`.
|
|
802
|
+
|
|
487
803
|
## Card payments
|
|
488
804
|
|
|
489
805
|
`…/payments` covers three ways to take card payments from a browser or a Node
|
|
@@ -494,6 +810,11 @@ process:
|
|
|
494
810
|
- **Hobex cloud** (`hobexPay`, `hobexRefund`): a terminal registered with
|
|
495
811
|
Hobex, controlled over the network through the backend. Amounts are passed in
|
|
496
812
|
cents; the package converts to euros for Hobex.
|
|
813
|
+
|
|
814
|
+
`hobexPay`, `hobexRefund` and `stripeCaptureIntent` move money. They are never
|
|
815
|
+
retried, neither by the app nor by a retrying `fetch` under the package: on
|
|
816
|
+
`isOutcomeUnknown(error)` look the payment up (see
|
|
817
|
+
[`outcome: 'unknown'`](#outcome-unknown-never-retry-look-it-up)).
|
|
497
818
|
- **Hobex HPS via Kasseneck Connect**, described below.
|
|
498
819
|
|
|
499
820
|
### Hobex HPS via Kasseneck Connect
|
|
@@ -538,22 +859,23 @@ The partner key (`pk_live_…`) belongs on a **server**. It can create
|
|
|
538
859
|
businesses and, with the extra scope `credentials:read`, fetch their secrets.
|
|
539
860
|
|
|
540
861
|
This subpath talks to the English Partner API **`/v3`**
|
|
541
|
-
(`PARTNER_BASE_URL`, `https://api.kasseneck.at/v3`)
|
|
542
|
-
every value your code branches on is English,
|
|
543
|
-
|
|
544
|
-
`
|
|
545
|
-
|
|
546
|
-
(`
|
|
862
|
+
(`PARTNER_BASE_URL`, `https://api.kasseneck.at/v3`) like the rest of the
|
|
863
|
+
package: every field name and every value your code branches on is English,
|
|
864
|
+
including every error code (`PARTNER_ERROR_CODES`, and
|
|
865
|
+
`PARTNER_REQUEST_ERROR_CODES` for rejected keys and scopes). Texts for humans
|
|
866
|
+
(`message`, `note`, `statusText`, `nextSteps`) stay German.
|
|
867
|
+
`partner.errorAdvice(code)` always returns a sentence, with a general fallback
|
|
868
|
+
for a code this version does not know.
|
|
547
869
|
|
|
548
870
|
```ts
|
|
549
|
-
import { createPartnerApi,
|
|
871
|
+
import { createPartnerApi, isPartnerError } from '@kreiseck/kasseneck-api/partner';
|
|
550
872
|
|
|
551
873
|
const partner = createPartnerApi({ partnerKey: process.env.KASSENECK_PARTNER_KEY! });
|
|
552
874
|
|
|
553
875
|
const { customerId } = await partner.createPartnerCustomer({
|
|
554
876
|
appId: 'app_…',
|
|
555
877
|
idempotencyKey: customerNumber, // your own number; protects against duplicates
|
|
556
|
-
business, // master data (type
|
|
878
|
+
business, // master data (type Business): legalForm 'sole_proprietor', state 'AT-5', …
|
|
557
879
|
// env: 'test' is allowed even with a LIVE key: that is how you rehearse the
|
|
558
880
|
// whole chain without a second key. Never the other way round.
|
|
559
881
|
});
|
|
@@ -566,20 +888,29 @@ await partner.createCustomerCashregister({ customerId }); // automatic: true is
|
|
|
566
888
|
```
|
|
567
889
|
|
|
568
890
|
The order is strict, and each step complains with its own code if an earlier
|
|
569
|
-
one is missing. The order ships as data (`
|
|
891
|
+
one is missing. The order ships as data (`PARTNER_FLOW`), and for every code
|
|
570
892
|
there is an action hint:
|
|
571
893
|
|
|
572
894
|
```ts
|
|
573
895
|
try {
|
|
574
896
|
await partner.activateCashregister(customerId, cashregisterId);
|
|
575
897
|
} catch (error) {
|
|
576
|
-
if (
|
|
898
|
+
if (isPartnerError(error, 'signature_not_ready')) {
|
|
577
899
|
// The signature of THIS register is not ready yet: wait for signature.ready.
|
|
578
|
-
console.error(partner.
|
|
900
|
+
console.error(partner.errorAdvice('signature_not_ready'));
|
|
579
901
|
}
|
|
580
902
|
}
|
|
581
903
|
```
|
|
582
904
|
|
|
905
|
+
`reportCustomerContract` reports a contract the business accepted through
|
|
906
|
+
the partner (terms of use or data processing agreement, with the text version
|
|
907
|
+
and its hash).
|
|
908
|
+
|
|
909
|
+
The two migration notes below are history from the 0.x line and use the names
|
|
910
|
+
of their time (`PARTNER_FEHLER_CODES`, `partnerFehlerRat`, the aliases
|
|
911
|
+
`Rechtsform`, `Bundesland`, `KontaktRolle`). For the move to 1.0 see
|
|
912
|
+
[Migrating from 0.x](#migrating-from-0x).
|
|
913
|
+
|
|
583
914
|
### Migrating from 0.27.x
|
|
584
915
|
|
|
585
916
|
0.28.0 is a breaking change for `./partner` only. The client now calls `/v3`
|
|
@@ -722,7 +1053,7 @@ app.post('/kasseneck-webhook', express.raw({ type: '*/*' }), async (req, res) =>
|
|
|
722
1053
|
});
|
|
723
1054
|
```
|
|
724
1055
|
|
|
725
|
-
## Invoice API (`./
|
|
1056
|
+
## Invoice API (`./invoice`)
|
|
726
1057
|
|
|
727
1058
|
For shops, accounting and industry software: issue **invoices** (*Rechnung*,
|
|
728
1059
|
§ 11 UStG), not receipts, with the `api_key` of an account. An invoice is
|
|
@@ -730,9 +1061,9 @@ For shops, accounting and industry software: issue **invoices** (*Rechnung*,
|
|
|
730
1061
|
and can only be corrected by a credit note. The key belongs on a **server**.
|
|
731
1062
|
|
|
732
1063
|
```ts
|
|
733
|
-
import {
|
|
1064
|
+
import { createInvoiceApi, isInvoiceError } from '@kreiseck/kasseneck-api/invoice';
|
|
734
1065
|
|
|
735
|
-
const invoices =
|
|
1066
|
+
const invoices = createInvoiceApi({ apiKey: process.env.KASSENECK_API_KEY! });
|
|
736
1067
|
|
|
737
1068
|
// 1. Create the customer once; externalId is your own customer number.
|
|
738
1069
|
let customer;
|
|
@@ -743,7 +1074,7 @@ try {
|
|
|
743
1074
|
externalId: 'shop-4711',
|
|
744
1075
|
});
|
|
745
1076
|
} catch (error) {
|
|
746
|
-
if (!
|
|
1077
|
+
if (!isInvoiceError(error, 'customer_exists')) throw error;
|
|
747
1078
|
customer = await invoices.getCustomer({ externalId: 'shop-4711' });
|
|
748
1079
|
}
|
|
749
1080
|
|
|
@@ -759,7 +1090,7 @@ const { invoice, replayed } = await invoices.issueInvoice({
|
|
|
759
1090
|
|
|
760
1091
|
// 3. Fetch the files.
|
|
761
1092
|
const pdf = await invoices.getInvoicePdf(invoice.id); // Uint8Array, with Factur-X
|
|
762
|
-
const xml = await invoices.getInvoiceXml(invoice.id, 'ubl'); // Peppol UBL
|
|
1093
|
+
const { xml, filename } = await invoices.getInvoiceXml(invoice.id, 'ubl'); // Peppol UBL, filename invoice-<number>.xml
|
|
763
1094
|
|
|
764
1095
|
// 4. Correct, only by credit note.
|
|
765
1096
|
await invoices.createCreditNote({
|
|
@@ -811,13 +1142,13 @@ const copy = await invoices.getInvoicePdf(invoice.id, { language: 'de' });
|
|
|
811
1142
|
The translated copy carries the same number, is marked on every page as a
|
|
812
1143
|
translation that is not an invoice of its own ("Übersetzung – keine eigene
|
|
813
1144
|
Rechnung"), and has no embedded e-invoice. The texts of both languages ship as
|
|
814
|
-
`
|
|
1145
|
+
`INVOICE_TEXTS` and `fixtures/invoice-texts.json`.
|
|
815
1146
|
|
|
816
1147
|
**Units are keys, not free text.** `items[].unit` takes a value from
|
|
817
1148
|
`INVOICE_UNITS` (`piece`, `hour`, `day`, `flat_rate`, `kilogram`,
|
|
818
1149
|
`square_metre`, …; default `piece`). The printed abbreviation follows the
|
|
819
1150
|
invoice language (`Stk` or `pcs`), and the e-invoice carries the UN/ECE code
|
|
820
|
-
from `
|
|
1151
|
+
from `INVOICE_UNIT_CODES` (`C62`, `HUR`, …). Free text such as `"Std"` is
|
|
821
1152
|
a `validation` error on field `items[0].unit`.
|
|
822
1153
|
|
|
823
1154
|
**Already paid?** If you take the payment online and invoice afterwards, pass
|
|
@@ -849,8 +1180,23 @@ invoice anyway.
|
|
|
849
1180
|
`onSite`:
|
|
850
1181
|
|
|
851
1182
|
```ts
|
|
852
|
-
|
|
853
|
-
|
|
1183
|
+
// Terminal at the point of sale: a cash sale.
|
|
1184
|
+
await invoices.issueInvoice({
|
|
1185
|
+
idempotencyKey: `counter-${orderNumber}`,
|
|
1186
|
+
customerId: customer.id,
|
|
1187
|
+
priceMode: 'gross', serviceStart: '2026-09-16',
|
|
1188
|
+
items: [{ description: 'Coffee beans 1 kg', quantity: 1, unitPriceCents: 2490, vatRate: 10, unit: 'piece' }],
|
|
1189
|
+
payment: { method: 'card', onSite: true },
|
|
1190
|
+
});
|
|
1191
|
+
|
|
1192
|
+
// Card payment in the online shop: not a cash sale, so no onSite.
|
|
1193
|
+
await invoices.issueInvoice({
|
|
1194
|
+
idempotencyKey: `shop-${orderNumber}`,
|
|
1195
|
+
customerId: customer.id,
|
|
1196
|
+
priceMode: 'gross', serviceStart: '2026-09-16',
|
|
1197
|
+
items: [{ description: 'Coffee beans 1 kg', quantity: 1, unitPriceCents: 2490, vatRate: 10, unit: 'piece' }],
|
|
1198
|
+
payment: { method: 'card', reference: payment.id },
|
|
1199
|
+
});
|
|
854
1200
|
```
|
|
855
1201
|
|
|
856
1202
|
For those cases the response's `notice` list contains `cash_receipt_required`:
|
|
@@ -869,9 +1215,9 @@ you then get the invoice that was already issued (`replayed: true`). The same
|
|
|
869
1215
|
key with different data gives `idempotency_conflict`.
|
|
870
1216
|
|
|
871
1217
|
Validation errors arrive as `validation` with field paths
|
|
872
|
-
(`
|
|
873
|
-
The contract itself ships as data (`
|
|
874
|
-
`@kreiseck/kasseneck-api/fixtures/
|
|
1218
|
+
(`invoiceFieldErrors(error)` → `[{ field: 'items[0].vatRate', message }]`).
|
|
1219
|
+
The contract itself ships as data (`INVOICE_REQUESTS`) and as a JSON Schema at
|
|
1220
|
+
`@kreiseck/kasseneck-api/fixtures/invoice-api.schema.json`; the backend
|
|
875
1221
|
validates against exactly this file.
|
|
876
1222
|
|
|
877
1223
|
### Calculating invoice totals in advance
|
|
@@ -893,7 +1239,7 @@ const { preview, notice } = await invoices.previewInvoice(request);
|
|
|
893
1239
|
await invoices.issueInvoice(request);
|
|
894
1240
|
```
|
|
895
1241
|
|
|
896
|
-
**Without the server.** `@kreiseck/kasseneck-api/
|
|
1242
|
+
**Without the server.** `@kreiseck/kasseneck-api/invoice/calc` is the pure
|
|
897
1243
|
calculation core: no transport, no key, runs in the browser too. It calculates
|
|
898
1244
|
with integers (BigInt) instead of floating point and rounds exactly once per
|
|
899
1245
|
VAT rate. Prices are in micro-euros (`unitPriceMicros`), quantities in
|
|
@@ -901,19 +1247,19 @@ thousandths (`quantityMilli`), discount and VAT rate in hundredths of a
|
|
|
901
1247
|
percent (`discountBp`, `vatRateBp`):
|
|
902
1248
|
|
|
903
1249
|
```ts
|
|
904
|
-
import {
|
|
1250
|
+
import { calculateInvoice, itemFromEuro } from '@kreiseck/kasseneck-api/invoice/calc';
|
|
905
1251
|
|
|
906
|
-
|
|
1252
|
+
calculateInvoice(
|
|
907
1253
|
[{ unitPriceMicros: 14_790_000, quantityMilli: 1000, vatRateBp: 2000 }],
|
|
908
1254
|
{ priceMode: 'gross' },
|
|
909
1255
|
);
|
|
910
1256
|
// { netCents: 1233, vatCents: 246, grossCents: 1479, byRate: [{ rateBp: 2000, … }], lines: […] }
|
|
911
1257
|
|
|
912
|
-
|
|
1258
|
+
itemFromEuro({ unitPrice: 14.79, quantity: 1, vatRate: 20 });
|
|
913
1259
|
// { ok: true, position: { unitPriceMicros: 14790000, quantityMilli: 1000, discountBp: 0, vatRateBp: 2000 } }
|
|
914
1260
|
```
|
|
915
1261
|
|
|
916
|
-
`
|
|
1262
|
+
`itemFromEuro(item)` converts a euro line (`unitPrice`, `quantity`,
|
|
917
1263
|
`vatRate`, `discountPct`) into this form without loss, or names the field and
|
|
918
1264
|
the reason when that is not possible. Since 23 September 2026 the server
|
|
919
1265
|
calculates every new invoice with this core. In **gross mode** the gross amount
|
|
@@ -921,17 +1267,47 @@ per rate is the agreed price: net = round(gross × 100 / (100 + rate)),
|
|
|
921
1267
|
VAT = gross − net. In **net mode** the VAT per rate is rounded from the net
|
|
922
1268
|
sum. Rounding is commercial (half a cent rounds away from zero). Totals are
|
|
923
1269
|
positive for credit notes too; the sign is in the document type
|
|
924
|
-
(`docType: '
|
|
925
|
-
`fixtures/
|
|
1270
|
+
(`docType: 'credit_note'`). Test cases: `fixtures/invoice-calc.json`,
|
|
1271
|
+
`fixtures/invoice-calc-random.json`, `fixtures/item-from-euro.json`.
|
|
926
1272
|
|
|
927
|
-
**`
|
|
1273
|
+
**`computeInvoiceTotals` is deprecated.** The older helper in `…/invoice` works on
|
|
928
1274
|
`unitPriceCents` lines with the previous floating-point formula and does not
|
|
929
1275
|
run through the core. At half-cent boundaries it can differ from an invoice
|
|
930
1276
|
issued today by one cent per VAT rate, and by a few cents across several
|
|
931
|
-
rates. Example: € 21.35 net at 10 % gives € 23.48 gross with `
|
|
1277
|
+
rates. Example: € 21.35 net at 10 % gives € 23.48 gross with `computeInvoiceTotals`,
|
|
932
1278
|
but € 23.49 with the core and on the invoice. It stays unchanged for existing
|
|
933
|
-
callers; use `
|
|
934
|
-
the old formula: `fixtures/
|
|
1279
|
+
callers; use `calculateInvoice` or `previewInvoice` in new code. Test cases for
|
|
1280
|
+
the old formula: `fixtures/invoice-totals.json`.
|
|
1281
|
+
|
|
1282
|
+
## Migrating from 0.x
|
|
1283
|
+
|
|
1284
|
+
1.0 is one breaking step: the wire, the exported names and the contract files
|
|
1285
|
+
all become English at once. The full list is in the
|
|
1286
|
+
[CHANGELOG](https://github.com/kreiseck-at/kasseneck-api/blob/main/CHANGELOG.md#100);
|
|
1287
|
+
the fixture renames are machine-readable in `fixtures/renames-1.0.json`. The
|
|
1288
|
+
short version:
|
|
1289
|
+
|
|
1290
|
+
- **Wire.** Only `/v3`: `api.kasseneck.at/v3` and `kasse.kasseneck.at/api/v3`.
|
|
1291
|
+
A `baseUrl` ending in `/v1` or `/api` throws. `baseUrl` now covers public
|
|
1292
|
+
calls only; whoever passed it to pairing, sign-in or register calls (the
|
|
1293
|
+
browser register used `/api`) switches to `posBaseUrl: '/api/v3'`.
|
|
1294
|
+
- **Payments.** `payments[]` is mandatory; `paymentMethod`,
|
|
1295
|
+
`createCancelReceipt` and cancelling through `createReceipt` are gone.
|
|
1296
|
+
`receiptDueCents` needs `tipRecipient` for a tip without recipients.
|
|
1297
|
+
- **Outcome.** Check `isOutcomeUnknown(error)` before any retry of a sale or
|
|
1298
|
+
cancellation.
|
|
1299
|
+
- **Names.** German export names are English (`KASSE_BASE_URL` is
|
|
1300
|
+
`POS_BASE_URL`, `mergeKasseSettings` is `mergePosSettings`,
|
|
1301
|
+
`rechnungRechnen` is `calculateInvoice`, …), and so are field names, values
|
|
1302
|
+
and error codes. There are no aliases.
|
|
1303
|
+
- **Subpaths.** `./kasse` is `./pos`, `./rechnung` is `./invoice`,
|
|
1304
|
+
`./rechnung/rechnen` is `./invoice/calc`; `./stored` is new.
|
|
1305
|
+
- **Texts.** Catalogue keys and placeholders are English
|
|
1306
|
+
(`storno.ergebnis_unklar` is `cancellation.outcome_unknown`, `{betrag}` is
|
|
1307
|
+
`{amount}`); every rendered text is byte for byte the same.
|
|
1308
|
+
|
|
1309
|
+
0.x stays on `/v1` and gets fixes only, published under the npm dist-tag `legacy`
|
|
1310
|
+
(`npm install @kreiseck/kasseneck-api@legacy`).
|
|
935
1311
|
|
|
936
1312
|
## Development
|
|
937
1313
|
|
|
@@ -953,18 +1329,20 @@ address returns the HTML fallback page instead of the function, and no mock
|
|
|
953
1329
|
sees that.
|
|
954
1330
|
|
|
955
1331
|
The check needs **no credentials**. A call without authentication answers,
|
|
956
|
-
when there is a function behind it, with
|
|
957
|
-
`
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
1332
|
+
when there is a function behind it, with an error envelope (`status` field)
|
|
1333
|
+
and the header `Kasseneck-Api-Version: v3`. That is the proof: the call was
|
|
1334
|
+
accepted and authentication was checked. An HTML page, a 404 or a missing
|
|
1335
|
+
marker proves that there is no `/v3` function. That is why the script looks
|
|
1336
|
+
for the envelope and the marker, not for success. Each call is asked at the
|
|
1337
|
+
address the transport really picks for it: public calls at
|
|
1338
|
+
`api.kasseneck.at/v3`, register-only calls at `kasse.kasseneck.at/api/v3`.
|
|
961
1339
|
|
|
962
1340
|
It is deliberately outside `npm test` because it needs the network. Without a
|
|
963
|
-
network it says so and exits with 0.
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
If an exception becomes reachable, the check fails; otherwise
|
|
967
|
-
never shrink.
|
|
1341
|
+
network it says so and exits with 0. CI runs the local part on every push;
|
|
1342
|
+
the network part runs daily. A call that deliberately has no function would be
|
|
1343
|
+
listed with a reason in `scripts/erreichbarkeit-ausnahmen.json`; since 1.0 that
|
|
1344
|
+
list is empty. If an exception becomes reachable, the check fails; otherwise
|
|
1345
|
+
the list would never shrink.
|
|
968
1346
|
|
|
969
1347
|
## Contract files for the twin packages
|
|
970
1348
|
|
|
@@ -974,19 +1352,24 @@ in machine form what both sides agreed on, among them:
|
|
|
974
1352
|
|
|
975
1353
|
| File | Contents | Generated by |
|
|
976
1354
|
|---|---|---|
|
|
977
|
-
| `
|
|
978
|
-
| `
|
|
1355
|
+
| `pos-settings-defaults.json` | field names and defaults of the register settings as sent on `/api/v3` (`business`, `device`), derived from the backend contract in `fixtures/v3/` | `npm run fixtures:kasse` |
|
|
1356
|
+
| `stored/pos-settings-defaults.json` | the same defaults in the stored (internal, German) form (`betrieb`, `geraet`) | `npm run fixtures:kasse` |
|
|
1357
|
+
| `surface.json` | base URLs (`baseUrls.public`, `baseUrls.pos`), the calls per path (`calls`, and the backend's `routes`), settings value lists (`enums`, keyed by field), other register lists (`pos`), register error codes, permission keys, shortcut actions, partner and invoice lists | `npm run fixtures:oberflaeche` |
|
|
979
1358
|
| `hobex-hps-codes.json` | measured HPS result codes, their meaning and whether they settle an outcome (the contract behind `isConclusive`) | `npm run fixtures:hobex-hps-codes` |
|
|
980
|
-
| `
|
|
981
|
-
| `
|
|
982
|
-
| `
|
|
1359
|
+
| `pos-texts.json` | the register's message catalogue | `npm run fixtures:texte` |
|
|
1360
|
+
| `invoice-texts.json` | invoice texts in both languages | `npm run fixtures:rechnungstexte` |
|
|
1361
|
+
| `invoice-api.schema.json` | JSON Schema of the invoice API | `npm run fixtures:rechnung` |
|
|
1362
|
+
| `pos-message-cases.json` | error cases and the message each one must show in both registers | by hand |
|
|
1363
|
+
| `receipt-due-generated.json` | 1206 amounts due computed by the backend's own code, the reference for `receiptDueCents` | `node scripts/v3-zahlbetrag-generieren.mjs` |
|
|
1364
|
+
| `v3/` | the backend's `/v3` contract (vocabulary, response cases, stored cases, amounts due), copied byte for byte | `node scripts/v3-vertrag-holen.mjs` |
|
|
1365
|
+
| `renames-1.0.json` | everything in these files that changed from 0.x to 1.0: paths (`files`), text catalogue keys (`texts`), placeholders, structural keys (`structure`), machine values (`values`), shape changes (`shapes`); rendered texts are unchanged | `npm run fixtures:umbenennung` |
|
|
983
1366
|
|
|
984
1367
|
They are generated and never edited by hand. CI regenerates the register
|
|
985
|
-
settings and `
|
|
1368
|
+
settings and `surface.json` and fails if they differ from the committed
|
|
986
1369
|
files; the test suite checks the others against the code.
|
|
987
1370
|
|
|
988
|
-
`
|
|
989
|
-
`
|
|
1371
|
+
`surface.json`, `hobex-hps-codes.json`, `pos-texts.json` and
|
|
1372
|
+
`invoice-texts.json` carry the package version. **After every `npm version`,
|
|
990
1373
|
regenerate them and commit them along**, otherwise the tests fail.
|
|
991
1374
|
|
|
992
1375
|
### And the other direction
|