@kreiseck/kasseneck-api 0.31.0 → 1.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +302 -0
- package/README.de.md +11 -7
- package/README.md +486 -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 +78 -19
- package/dist/cjs/client/errors.js +107 -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 +214 -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 +222 -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 +2 -2
- package/dist/cjs/payments/hobex.js +4 -4
- package/dist/cjs/payments/stripe.d.ts +2 -2
- package/dist/cjs/payments/stripe.js +4 -4
- 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 +78 -19
- package/dist/esm/client/errors.js +105 -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 +213 -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 +221 -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 +2 -2
- package/dist/esm/payments/hobex.js +4 -4
- package/dist/esm/payments/stripe.d.ts +2 -2
- package/dist/esm/payments/stripe.js +4 -4
- 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,88 @@ 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 signing operation is left open: no receipt was
|
|
431
|
+
signed and nothing went to FinanzOnline, so retrying the same request does not
|
|
432
|
+
create a second receipt (whether it helps depends on the code). `'unknown'` means the operation **may have been carried out**, for
|
|
433
|
+
`createReceipt` a signed receipt in the chain. Then never send it again: read
|
|
434
|
+
the result back (`getReceipt`, `listMyReceipts`, the original of a
|
|
435
|
+
cancellation) and continue from there. `isOutcomeUnknown(error)` covers all
|
|
436
|
+
three classes. The outcome is unknown for:
|
|
437
|
+
|
|
438
|
+
- `dialect_mismatch`, `receipt_outcome_unknown`, `cancellation_outcome_unknown`;
|
|
439
|
+
- `response_translation_failed`, unless `details.handled === false`;
|
|
440
|
+
- `response_unreadable`: a signing call reported success, but the response
|
|
441
|
+
lacks what the call promises (no receipt, no reference, no remaining
|
|
442
|
+
quantities);
|
|
443
|
+
- on the signing calls `createReceipt`, `cancelReceipt` and
|
|
444
|
+
`financeWebService`: a network error or timeout after sending began, HTTP
|
|
445
|
+
5xx, and HTTP 200 with the `Kasseneck-Api-Version: v3` marker but an empty,
|
|
446
|
+
non-JSON (also `text/html`) or status-less body (`KasseneckHttpError`,
|
|
447
|
+
`reason` `empty-body`, `not-json` or `missing-status`). HTML without the
|
|
448
|
+
marker stays `route_missing` with `'rejected'`: no function saw the call.
|
|
449
|
+
|
|
450
|
+
`outcome` only covers signing. After a network error on `issueInvoice` an
|
|
451
|
+
invoice may still have been issued; retry it with the same `idempotencyKey`.
|
|
452
|
+
|
|
453
|
+
```ts
|
|
454
|
+
import { isOutcomeUnknown, paymentsExpectedCents } from '@kreiseck/kasseneck-api';
|
|
455
|
+
|
|
456
|
+
try {
|
|
457
|
+
await api.sellReceipt({ items, payments });
|
|
458
|
+
} catch (error) {
|
|
459
|
+
if (isOutcomeUnknown(error)) return reloadReceiptsAndAsk(); // never sell again blindly
|
|
460
|
+
const expected = paymentsExpectedCents(error); // payments_sum_mismatch
|
|
461
|
+
if (expected !== undefined) return askAgain(expected);
|
|
462
|
+
throw error;
|
|
463
|
+
}
|
|
464
|
+
```
|
|
286
465
|
|
|
287
466
|
## Receipts
|
|
288
467
|
|
|
@@ -290,17 +469,48 @@ The facade from `createKasseneckApi` offers `sellReceipt` and
|
|
|
290
469
|
`sellReceiptWithCompany`, `zeroReceipt` for a zero receipt (*Nullbeleg*),
|
|
291
470
|
`getReceipt` and `getReceiptWithCompany`, `listMyReceipts`, `cancelReceipt`,
|
|
292
471
|
`sendReceiptEmail`, the report downloads, the FinanzOnline status queries
|
|
293
|
-
(`getCashboxStatus`, `getSignatureStatus`)
|
|
472
|
+
(`getCashboxStatus`, `getSignatureStatus`), `getReportV2({ start, end })` for
|
|
473
|
+
the raw receipts and company data of a period, and the Stripe and Hobex cloud
|
|
294
474
|
payments.
|
|
295
475
|
|
|
476
|
+
The models are English throughout: the company has `taxNumber` and `vatId`, a
|
|
477
|
+
receipt `headerVersionId`, `layoutRuleset` and `registrationInfo`, a receipt
|
|
478
|
+
in the list `cancellationStatus` (`none`, `partial`, `full`, or `'unknown'` for
|
|
479
|
+
a value this version does not know: then offer no cancellation). The same
|
|
480
|
+
rule holds for print job states and register settings: a value the package
|
|
481
|
+
does not know is shown as `'unknown'` or kept as sent, never mapped onto a
|
|
482
|
+
known one.
|
|
483
|
+
|
|
296
484
|
**Layout rule sets.** `buildReceiptLayout` sets receipts according to a
|
|
297
|
-
numbered rule set. Without the `
|
|
298
|
-
(`
|
|
485
|
+
numbered rule set. Without the `ruleset` option the current one applies
|
|
486
|
+
(`CURRENT_LAYOUT_RULESET`, currently 2: zero receipts carry a block
|
|
299
487
|
"Prüfangaben" with the registration data, which `getReceiptWithCompany`
|
|
300
|
-
returns as `
|
|
488
|
+
returns as `registrationInfo`). The backend stores the rule set with each receipt,
|
|
301
489
|
and `getReceiptWithCompany` also returns the backend-built `layout` in that
|
|
302
490
|
rule set, so an old receipt looks the way it did when it was issued.
|
|
303
491
|
|
|
492
|
+
**Print and show the server's layout.** `layout` in a `…WithCompany` result
|
|
493
|
+
is a `ReceiptLayout` (`ruleset`, banner lines with `tone: 'receipt_type' |
|
|
494
|
+
'warning'`) and goes unchanged to `escPosLayoutBytes`, `eposPrintXml`,
|
|
495
|
+
`receiptSheet` and the React views; `receiptLayoutFromResult(result)` returns
|
|
496
|
+
it whenever it is there. Only without it does the helper build the layout,
|
|
497
|
+
in `fallbackPaperSize` (default `mm58`, as in 0.x). The server layout is
|
|
498
|
+
always 80 mm: on 58 mm paper choose the width at the print path
|
|
499
|
+
(`escPosLayoutBytes(layout, { paperSize: 'mm58' })`, `charsPerLine: 32`); the VAT
|
|
500
|
+
table then keeps the columns of the 80 mm grid. On the public channel only this layout carries the card block, because
|
|
501
|
+
the receipt itself comes without provider data. If you build the layout
|
|
502
|
+
yourself, pass the options from the same response:
|
|
503
|
+
|
|
504
|
+
```ts
|
|
505
|
+
buildReceiptLayout(receipt, company, { paperSize: 'mm80', testCashregister, testSignature, registrationInfo });
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
The options of 0.x (`testKasse`, `testSignatur`, `pruefangaben`,
|
|
509
|
+
`regelwerk`) are rejected with a `KasseneckValidationError` instead of being
|
|
510
|
+
ignored: a test receipt must never lose its "TESTKASSE" banner. The printed
|
|
511
|
+
text stays German, and the CSS classes of the React banner stay
|
|
512
|
+
`keck-receipt-banner--belegart` and `--warnung`.
|
|
513
|
+
|
|
304
514
|
Times on receipts are read as **Vienna wall-clock time**
|
|
305
515
|
(`parseServerTimeStamp`), never through `new Date(text)`.
|
|
306
516
|
|
|
@@ -311,9 +521,12 @@ A cancellation (*Storno*) refers to the original receipt, in full or in part:
|
|
|
311
521
|
```ts
|
|
312
522
|
const result = await api.cancelReceipt({
|
|
313
523
|
receipt: original, // or: cashregisterId + originalReceiptId
|
|
314
|
-
reason: '
|
|
524
|
+
reason: 'input_error', // catalogue: CANCELLATION_REASONS
|
|
315
525
|
items: [{ index: 0, quantity: 1 }], // omit = cancel all remaining quantities
|
|
316
526
|
note: 'Customer only wanted one', // internal, stored, never printed
|
|
527
|
+
// Refund per original payment (negative, refundOf = id of that payment).
|
|
528
|
+
// Omit it and the server refunds the remainder of every original payment.
|
|
529
|
+
payments: [{ method: KeckPaymentMethod.cash, amountCents: -390, refundOf: 'p1' }],
|
|
317
530
|
});
|
|
318
531
|
result.receipt; // the signed cancellation receipt (receiptType cancellation)
|
|
319
532
|
result.cancellationOf; // reference to the original
|
|
@@ -328,20 +541,20 @@ fully cancelled receipt cannot be cancelled again. On a receipt you have read,
|
|
|
328
541
|
cancellation dialog); the server has the final word.
|
|
329
542
|
|
|
330
543
|
Every business error of `cancelReceipt` carries `KasseneckApiError.code` from
|
|
331
|
-
`CANCELLATION_ERROR_CODES` (for example `
|
|
332
|
-
`
|
|
544
|
+
`CANCELLATION_ERROR_CODES` (for example `already_cancelled`,
|
|
545
|
+
`quantity_exceeds_remaining`, `own_receipts_only`):
|
|
333
546
|
|
|
334
547
|
```ts
|
|
335
548
|
import { isKasseneckApiError, isCancellationErrorCode } from '@kreiseck/kasseneck-api';
|
|
336
549
|
|
|
337
550
|
try {
|
|
338
|
-
await api.cancelReceipt({ receipt: original, reason: '
|
|
551
|
+
await api.cancelReceipt({ receipt: original, reason: 'input_error' });
|
|
339
552
|
} catch (error) {
|
|
340
553
|
if (!isKasseneckApiError(error) || !isCancellationErrorCode(error.code)) throw error;
|
|
341
554
|
switch (error.code) {
|
|
342
|
-
case '
|
|
343
|
-
case '
|
|
344
|
-
case '
|
|
555
|
+
case 'already_cancelled': // show the receipt as cancelled, disable the button
|
|
556
|
+
case 'quantity_exceeds_remaining': // reload the remaining quantities (someone was faster)
|
|
557
|
+
case 'own_receipts_only': // ask a manager
|
|
345
558
|
showHint(error.code);
|
|
346
559
|
break;
|
|
347
560
|
default:
|
|
@@ -350,11 +563,14 @@ try {
|
|
|
350
563
|
}
|
|
351
564
|
```
|
|
352
565
|
|
|
353
|
-
**
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
566
|
+
**Card refunds.** The terminal refund needs the transaction id of the original
|
|
567
|
+
card payment: `payments[].providerPaymentId` of the original receipt. Only the
|
|
568
|
+
register channel (`registerUserAuth`, `kasse.kasseneck.at/api/v3`) returns it;
|
|
569
|
+
the public channel leaves provider data out. The refund payment then carries
|
|
570
|
+
the id of the refund itself. `cancellation_outcome_unknown` means the
|
|
571
|
+
cancellation may have been booked: read the original again, never retry.
|
|
572
|
+
|
|
573
|
+
`createCancelReceipt` and cancelling through `createReceipt` are gone in 1.0.
|
|
358
574
|
|
|
359
575
|
**Vouchers.** A value voucher is only mirrored on a full cancellation (without
|
|
360
576
|
`items`); it cannot be split. A discount voucher is already part of the
|
|
@@ -378,11 +594,11 @@ it omit that line.
|
|
|
378
594
|
const confirmation = await api.sendReceiptEmail({
|
|
379
595
|
fullReceiptId: original.fullReceiptId, // or: await api.generateFullReceiptId(receiptId)
|
|
380
596
|
to: 'guest@example.at',
|
|
381
|
-
|
|
597
|
+
language: 'de', // optional; the backend currently only uses 'de'
|
|
382
598
|
});
|
|
383
599
|
confirmation.to; // address as the backend logged it (trimmed, lower case)
|
|
384
600
|
confirmation.at; // time, ISO with Vienna offset
|
|
385
|
-
confirmation.via; // '
|
|
601
|
+
confirmation.via; // 'own' | 'platform' | 'platform_fallback' | null
|
|
386
602
|
```
|
|
387
603
|
|
|
388
604
|
The email contains a **link to the public receipt page**, not a PDF
|
|
@@ -394,8 +610,8 @@ The cash register comes from the authentication (`cashregister-token` header or
|
|
|
394
610
|
the parameter set by `registerUserAuth`), not from the options. A receipt of
|
|
395
611
|
another register therefore gets the same answer as a receipt that does not
|
|
396
612
|
exist. The codes are in `RECEIPT_EMAIL_ERROR_CODES` (`isReceiptEmailErrorCode`):
|
|
397
|
-
`
|
|
398
|
-
24 hours, 30 per register per hour) and `
|
|
613
|
+
`invalid_address`, `receipt_not_found`, `too_many_requests` (5 emails per
|
|
614
|
+
receipt in 24 hours, 30 per register per hour) and `send_failed`.
|
|
399
615
|
|
|
400
616
|
## Receipt printing: QR code, logo, printers
|
|
401
617
|
|
|
@@ -408,34 +624,34 @@ receipt the worst possible result. So this package calculates the size instead
|
|
|
408
624
|
of setting it:
|
|
409
625
|
|
|
410
626
|
```ts
|
|
411
|
-
import {
|
|
627
|
+
import { qrSizingFor, QR_PRINT_WIDTH_DOTS } from '@kreiseck/kasseneck-api/printing';
|
|
412
628
|
|
|
413
|
-
const qrSize =
|
|
414
|
-
// qrSize.
|
|
415
|
-
// qrSize.
|
|
629
|
+
const qrSize = qrSizingFor({ payload: receipt.qr, paperWidthDots: QR_PRINT_WIDTH_DOTS.mm58 });
|
|
630
|
+
// qrSize.moduleDots: dots per module; null = does not fit even with the exception size
|
|
631
|
+
// qrSize.belowMinimum: printed, but below 4 dots per module
|
|
416
632
|
```
|
|
417
633
|
|
|
418
|
-
On the receipt path this happens automatically. `
|
|
634
|
+
On the receipt path this happens automatically. `qrModuleSize` is a **cap**, not
|
|
419
635
|
a target: the largest size that fits is printed, at most the cap. `auto` (the
|
|
420
636
|
default) caps at 6 dots per module, as in the Dart twin and on the Epson path;
|
|
421
|
-
`
|
|
637
|
+
`small` caps at 4, `medium` at 6, `large` at 8. All print paths use error
|
|
422
638
|
correction level M.
|
|
423
639
|
|
|
424
640
|
```ts
|
|
425
|
-
import {
|
|
641
|
+
import { escPosLayoutResult } from '@kreiseck/kasseneck-api/receipt';
|
|
426
642
|
|
|
427
|
-
const { bytes,
|
|
428
|
-
|
|
429
|
-
|
|
643
|
+
const { bytes, qrError, qrFallback } = escPosLayoutResult(layout, {
|
|
644
|
+
qrModuleSize: 'large', // 'auto' | 'small' | 'medium' | 'large'
|
|
645
|
+
qrMode: 'nativeModel1', // older printers that only support model 1
|
|
430
646
|
qrMatrix: matrixFor, // fallback: the QR code as an image instead of none
|
|
431
647
|
});
|
|
432
648
|
```
|
|
433
649
|
|
|
434
650
|
The Epson ePOS path (`eposPrintXml` / `eposDirectPrint`) calculates the same
|
|
435
|
-
way; `
|
|
651
|
+
way; `eposPrintXmlResult` returns `{ xml, qrError, qrFallback }`. The default
|
|
436
652
|
there is also `auto`.
|
|
437
653
|
|
|
438
|
-
`
|
|
654
|
+
`qrError` means "receipt without QR code": tell the customer. `qrFallback`
|
|
439
655
|
means "printed, but the configured mode does not suit this device": tell the
|
|
440
656
|
manager. The image fallback only runs with a `qrMatrix` function that turns
|
|
441
657
|
the payload into a finished matrix; the package itself neither encodes QR
|
|
@@ -448,25 +664,26 @@ logo, QR code and the Kasseneck logo at the end, with sizes as a share of the
|
|
|
448
664
|
sheet width and in lines (one line = two character widths).
|
|
449
665
|
|
|
450
666
|
```tsx
|
|
451
|
-
import {
|
|
667
|
+
import { ReceiptSheetView } from '@kreiseck/kasseneck-api/react';
|
|
452
668
|
|
|
453
|
-
const
|
|
454
|
-
const
|
|
669
|
+
const result = await api.getReceiptWithCompany(receiptId);
|
|
670
|
+
const { company, logoScale } = result;
|
|
671
|
+
const layout = receiptLayoutFromResult(result);
|
|
455
672
|
|
|
456
|
-
<
|
|
673
|
+
<ReceiptSheetView
|
|
457
674
|
layout={layout}
|
|
458
|
-
logo={company.logoUrl ? { url: company.logoUrl,
|
|
459
|
-
|
|
675
|
+
logo={company.logoUrl ? { url: company.logoUrl, size: logoScale } : null}
|
|
676
|
+
brandMark={company.showKreiseckLogo}
|
|
460
677
|
renderQr={(data) => <QrSvg data={data} />}
|
|
461
678
|
/>
|
|
462
679
|
```
|
|
463
680
|
|
|
464
681
|
```ts
|
|
465
|
-
import { escPosLayoutBytes,
|
|
682
|
+
import { escPosLayoutBytes, logoDimensions, rasterizeLogo } from '@kreiseck/kasseneck-api/receipt';
|
|
466
683
|
|
|
467
|
-
const logoSize =
|
|
468
|
-
const raster =
|
|
469
|
-
escPosLayoutBytes(layout, { paperSize: 'mm80', logo: {
|
|
684
|
+
const logoSize = logoDimensions({ size: 'M', pixelWidth: image.width, pixelHeight: image.height }, 48);
|
|
685
|
+
const raster = rasterizeLogo(imageData.data, image.width, image.height, logoSize, 48);
|
|
686
|
+
escPosLayoutBytes(layout, { paperSize: 'mm80', logo: { size: 'M', pixelWidth: image.width, pixelHeight: image.height, raster }, brandMark: true });
|
|
470
687
|
```
|
|
471
688
|
|
|
472
689
|
Logo sizes: S 42 % × 5 lines, M 62 % × 8, L 80 % × 12, XL 94 % × 16, always
|
|
@@ -480,10 +697,91 @@ The package generates ESC/POS bytes and ePOS XML, and it ships three ways to
|
|
|
480
697
|
deliver them: **WebUSB** (`usbConnectPrinter`, `usbPrint` in `…/printing`, for
|
|
481
698
|
Chromium-based browsers), **Epson ePOS over HTTP** (`eposDirectPrint` in
|
|
482
699
|
`…/receipt`) and **print jobs** for network printers managed by the backend
|
|
483
|
-
(`listMyPrinters`, `createPrintJob` in `…/
|
|
700
|
+
(`listMyPrinters`, `createPrintJob` in `…/pos`). Bluetooth, serial ports and
|
|
484
701
|
raw TCP sockets are up to your application. PDF generation is not part of the
|
|
485
702
|
package.
|
|
486
703
|
|
|
704
|
+
## Register settings, articles and printers (`./pos`)
|
|
705
|
+
|
|
706
|
+
The calls of the tile register run on the register path and take a transport
|
|
707
|
+
from `createTransport` with the same options as `createKasseneckApi`.
|
|
708
|
+
Settings come as `{ business, device }` with English keys and values
|
|
709
|
+
(`theme: 'night'`, `receiptOutput: 'ask'`, `shortcuts.checkout`), merged with
|
|
710
|
+
the defaults `POS_BUSINESS_DEFAULTS` and `POS_DEVICE_DEFAULTS`.
|
|
711
|
+
|
|
712
|
+
**Send only what changed.** The server merges deeply, so a write carries only
|
|
713
|
+
the changed fields. `posSettingsChanges(before, after)` computes them; it sends
|
|
714
|
+
`vatRates` and `shortcuts` as whole maps, which is what the server expects:
|
|
715
|
+
|
|
716
|
+
```ts
|
|
717
|
+
import { createTransport, registerUserAuth } from '@kreiseck/kasseneck-api';
|
|
718
|
+
import { getPosSettings, setMyPosSettings, posSettingsChanges, isPosError, posFieldErrors } from '@kreiseck/kasseneck-api/pos';
|
|
719
|
+
|
|
720
|
+
const transport = createTransport({ auth: registerUserAuth({ getIdToken, getSessionId, cashregisterId }), posBaseUrl: '/api/v3' });
|
|
721
|
+
|
|
722
|
+
const before = await getPosSettings(transport);
|
|
723
|
+
const after = { ...before.business, theme: 'night' as const, fontSize: 'L' as const };
|
|
724
|
+
try {
|
|
725
|
+
await setMyPosSettings(transport, posSettingsChanges(before.business, after));
|
|
726
|
+
} catch (error) {
|
|
727
|
+
if (isPosError(error, 'validation')) showFieldErrors(posFieldErrors(error)); // [{ field: 'business.color', message }]
|
|
728
|
+
else throw error;
|
|
729
|
+
}
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
Never send back the whole merged block. A value the server knows and this
|
|
733
|
+
version does not (`theme: 'sepia'`) is read and kept as it is;
|
|
734
|
+
`unknownPosSettingValues(settings)` names such paths, so the interface can show
|
|
735
|
+
them as not editable. Left unchanged, such a value is not sent and stays on the
|
|
736
|
+
server; inside a whole block it would be rejected before sending. The same
|
|
737
|
+
check rejects unknown keys (also the German keys of 0.x such as `stil`),
|
|
738
|
+
values outside a field's list, a `vatRates` map without any rate switched on,
|
|
739
|
+
unknown shortcut actions and a key bound twice (`posShortcutConflict`).
|
|
740
|
+
Per-device settings go through `setMyRegisterDeviceSettings(transport, deviceId,
|
|
741
|
+
changes)`.
|
|
742
|
+
|
|
743
|
+
A state you stored yourself (for example settings cached in `localStorage`)
|
|
744
|
+
goes through `sanitizePosSettings` or `mergePosSettings` first: both drop the
|
|
745
|
+
German values of 0.x, so an old cache falls back to the defaults instead of
|
|
746
|
+
sending a German value.
|
|
747
|
+
|
|
748
|
+
The rest of `…/pos`: `listMyArticles` and `listMyArticleGroups` for the tiles
|
|
749
|
+
(`visible`, `quantityRule: 'piece' | 'decimal'`, `askQuantity`,
|
|
750
|
+
`maxQuantity`), `listMyPrinters`, `createPrintJob` and `getPrintJob` for
|
|
751
|
+
network printers (poll until `isPrintJobFinished(job)`; an unknown state is
|
|
752
|
+
`'unknown'` and ends the polling), `listMyTipRecipients`, `setMyPosLogo`, and
|
|
753
|
+
the register's text catalogue (`MESSAGES`, `LABELS`, `messageText`,
|
|
754
|
+
`labelText`). Text keys are English (`cancellation.outcome_unknown`,
|
|
755
|
+
`split.add_payment`), and so are the placeholders:
|
|
756
|
+
`messageText('checkout.locked', { reason })`. The rendered German texts are
|
|
757
|
+
the same as in 0.x.
|
|
758
|
+
|
|
759
|
+
## Stored documents (`./stored`)
|
|
760
|
+
|
|
761
|
+
For clients that read Firestore directly, such as the admin panel. Stored
|
|
762
|
+
documents keep the internal German form; `…/stored` turns them into the same
|
|
763
|
+
English models the `/v3` wire returns, following the server's own rules
|
|
764
|
+
(layout rule set, logo size, `TESTKASSE` banner, the settings merge):
|
|
765
|
+
|
|
766
|
+
```ts
|
|
767
|
+
import { fromStoredReceiptWithCompany, fromStoredPosSettings, invalidStoredPosSettings } from '@kreiseck/kasseneck-api/stored';
|
|
768
|
+
|
|
769
|
+
// The header version the receipt names (receipt.headerVersionId), plus the account document.
|
|
770
|
+
const result = fromStoredReceiptWithCompany(receiptDoc, {
|
|
771
|
+
headerVersion: { id: headerDoc.id, data: headerDoc.data() },
|
|
772
|
+
account: accountDoc.data(),
|
|
773
|
+
});
|
|
774
|
+
receiptLayoutFromResult(result); // the same layout getReceiptWithCompany returns
|
|
775
|
+
|
|
776
|
+
const settings = fromStoredPosSettings({ betrieb, geraet }); // stored register settings
|
|
777
|
+
invalidStoredPosSettings({ betrieb, geraet }); // paths the server would drop
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
`fromStoredReceipt`, `fromStoredCompany` and `fromStoredArticle` complete the
|
|
781
|
+
set. A broken document throws a `KasseneckValidationError`. There is no
|
|
782
|
+
reader for stored invoices: the server computes the invoice view, so read it
|
|
783
|
+
with `getInvoice` and `listInvoices`.
|
|
784
|
+
|
|
487
785
|
## Card payments
|
|
488
786
|
|
|
489
787
|
`…/payments` covers three ways to take card payments from a browser or a Node
|
|
@@ -538,22 +836,23 @@ The partner key (`pk_live_…`) belongs on a **server**. It can create
|
|
|
538
836
|
businesses and, with the extra scope `credentials:read`, fetch their secrets.
|
|
539
837
|
|
|
540
838
|
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
|
-
(`
|
|
839
|
+
(`PARTNER_BASE_URL`, `https://api.kasseneck.at/v3`) like the rest of the
|
|
840
|
+
package: every field name and every value your code branches on is English,
|
|
841
|
+
including every error code (`PARTNER_ERROR_CODES`, and
|
|
842
|
+
`PARTNER_REQUEST_ERROR_CODES` for rejected keys and scopes). Texts for humans
|
|
843
|
+
(`message`, `note`, `statusText`, `nextSteps`) stay German.
|
|
844
|
+
`partner.errorAdvice(code)` always returns a sentence, with a general fallback
|
|
845
|
+
for a code this version does not know.
|
|
547
846
|
|
|
548
847
|
```ts
|
|
549
|
-
import { createPartnerApi,
|
|
848
|
+
import { createPartnerApi, isPartnerError } from '@kreiseck/kasseneck-api/partner';
|
|
550
849
|
|
|
551
850
|
const partner = createPartnerApi({ partnerKey: process.env.KASSENECK_PARTNER_KEY! });
|
|
552
851
|
|
|
553
852
|
const { customerId } = await partner.createPartnerCustomer({
|
|
554
853
|
appId: 'app_…',
|
|
555
854
|
idempotencyKey: customerNumber, // your own number; protects against duplicates
|
|
556
|
-
business, // master data (type
|
|
855
|
+
business, // master data (type Business): legalForm 'sole_proprietor', state 'AT-5', …
|
|
557
856
|
// env: 'test' is allowed even with a LIVE key: that is how you rehearse the
|
|
558
857
|
// whole chain without a second key. Never the other way round.
|
|
559
858
|
});
|
|
@@ -566,20 +865,29 @@ await partner.createCustomerCashregister({ customerId }); // automatic: true is
|
|
|
566
865
|
```
|
|
567
866
|
|
|
568
867
|
The order is strict, and each step complains with its own code if an earlier
|
|
569
|
-
one is missing. The order ships as data (`
|
|
868
|
+
one is missing. The order ships as data (`PARTNER_FLOW`), and for every code
|
|
570
869
|
there is an action hint:
|
|
571
870
|
|
|
572
871
|
```ts
|
|
573
872
|
try {
|
|
574
873
|
await partner.activateCashregister(customerId, cashregisterId);
|
|
575
874
|
} catch (error) {
|
|
576
|
-
if (
|
|
875
|
+
if (isPartnerError(error, 'signature_not_ready')) {
|
|
577
876
|
// The signature of THIS register is not ready yet: wait for signature.ready.
|
|
578
|
-
console.error(partner.
|
|
877
|
+
console.error(partner.errorAdvice('signature_not_ready'));
|
|
579
878
|
}
|
|
580
879
|
}
|
|
581
880
|
```
|
|
582
881
|
|
|
882
|
+
`reportCustomerContract` reports a contract the business accepted through
|
|
883
|
+
the partner (terms of use or data processing agreement, with the text version
|
|
884
|
+
and its hash).
|
|
885
|
+
|
|
886
|
+
The two migration notes below are history from the 0.x line and use the names
|
|
887
|
+
of their time (`PARTNER_FEHLER_CODES`, `partnerFehlerRat`, the aliases
|
|
888
|
+
`Rechtsform`, `Bundesland`, `KontaktRolle`). For the move to 1.0 see
|
|
889
|
+
[Migrating from 0.x](#migrating-from-0x).
|
|
890
|
+
|
|
583
891
|
### Migrating from 0.27.x
|
|
584
892
|
|
|
585
893
|
0.28.0 is a breaking change for `./partner` only. The client now calls `/v3`
|
|
@@ -722,7 +1030,7 @@ app.post('/kasseneck-webhook', express.raw({ type: '*/*' }), async (req, res) =>
|
|
|
722
1030
|
});
|
|
723
1031
|
```
|
|
724
1032
|
|
|
725
|
-
## Invoice API (`./
|
|
1033
|
+
## Invoice API (`./invoice`)
|
|
726
1034
|
|
|
727
1035
|
For shops, accounting and industry software: issue **invoices** (*Rechnung*,
|
|
728
1036
|
§ 11 UStG), not receipts, with the `api_key` of an account. An invoice is
|
|
@@ -730,9 +1038,9 @@ For shops, accounting and industry software: issue **invoices** (*Rechnung*,
|
|
|
730
1038
|
and can only be corrected by a credit note. The key belongs on a **server**.
|
|
731
1039
|
|
|
732
1040
|
```ts
|
|
733
|
-
import {
|
|
1041
|
+
import { createInvoiceApi, isInvoiceError } from '@kreiseck/kasseneck-api/invoice';
|
|
734
1042
|
|
|
735
|
-
const invoices =
|
|
1043
|
+
const invoices = createInvoiceApi({ apiKey: process.env.KASSENECK_API_KEY! });
|
|
736
1044
|
|
|
737
1045
|
// 1. Create the customer once; externalId is your own customer number.
|
|
738
1046
|
let customer;
|
|
@@ -743,7 +1051,7 @@ try {
|
|
|
743
1051
|
externalId: 'shop-4711',
|
|
744
1052
|
});
|
|
745
1053
|
} catch (error) {
|
|
746
|
-
if (!
|
|
1054
|
+
if (!isInvoiceError(error, 'customer_exists')) throw error;
|
|
747
1055
|
customer = await invoices.getCustomer({ externalId: 'shop-4711' });
|
|
748
1056
|
}
|
|
749
1057
|
|
|
@@ -759,7 +1067,7 @@ const { invoice, replayed } = await invoices.issueInvoice({
|
|
|
759
1067
|
|
|
760
1068
|
// 3. Fetch the files.
|
|
761
1069
|
const pdf = await invoices.getInvoicePdf(invoice.id); // Uint8Array, with Factur-X
|
|
762
|
-
const xml = await invoices.getInvoiceXml(invoice.id, 'ubl'); // Peppol UBL
|
|
1070
|
+
const { xml, filename } = await invoices.getInvoiceXml(invoice.id, 'ubl'); // Peppol UBL, filename invoice-<number>.xml
|
|
763
1071
|
|
|
764
1072
|
// 4. Correct, only by credit note.
|
|
765
1073
|
await invoices.createCreditNote({
|
|
@@ -811,13 +1119,13 @@ const copy = await invoices.getInvoicePdf(invoice.id, { language: 'de' });
|
|
|
811
1119
|
The translated copy carries the same number, is marked on every page as a
|
|
812
1120
|
translation that is not an invoice of its own ("Übersetzung – keine eigene
|
|
813
1121
|
Rechnung"), and has no embedded e-invoice. The texts of both languages ship as
|
|
814
|
-
`
|
|
1122
|
+
`INVOICE_TEXTS` and `fixtures/invoice-texts.json`.
|
|
815
1123
|
|
|
816
1124
|
**Units are keys, not free text.** `items[].unit` takes a value from
|
|
817
1125
|
`INVOICE_UNITS` (`piece`, `hour`, `day`, `flat_rate`, `kilogram`,
|
|
818
1126
|
`square_metre`, …; default `piece`). The printed abbreviation follows the
|
|
819
1127
|
invoice language (`Stk` or `pcs`), and the e-invoice carries the UN/ECE code
|
|
820
|
-
from `
|
|
1128
|
+
from `INVOICE_UNIT_CODES` (`C62`, `HUR`, …). Free text such as `"Std"` is
|
|
821
1129
|
a `validation` error on field `items[0].unit`.
|
|
822
1130
|
|
|
823
1131
|
**Already paid?** If you take the payment online and invoice afterwards, pass
|
|
@@ -849,8 +1157,23 @@ invoice anyway.
|
|
|
849
1157
|
`onSite`:
|
|
850
1158
|
|
|
851
1159
|
```ts
|
|
852
|
-
|
|
853
|
-
|
|
1160
|
+
// Terminal at the point of sale: a cash sale.
|
|
1161
|
+
await invoices.issueInvoice({
|
|
1162
|
+
idempotencyKey: `counter-${orderNumber}`,
|
|
1163
|
+
customerId: customer.id,
|
|
1164
|
+
priceMode: 'gross', serviceStart: '2026-09-16',
|
|
1165
|
+
items: [{ description: 'Coffee beans 1 kg', quantity: 1, unitPriceCents: 2490, vatRate: 10, unit: 'piece' }],
|
|
1166
|
+
payment: { method: 'card', onSite: true },
|
|
1167
|
+
});
|
|
1168
|
+
|
|
1169
|
+
// Card payment in the online shop: not a cash sale, so no onSite.
|
|
1170
|
+
await invoices.issueInvoice({
|
|
1171
|
+
idempotencyKey: `shop-${orderNumber}`,
|
|
1172
|
+
customerId: customer.id,
|
|
1173
|
+
priceMode: 'gross', serviceStart: '2026-09-16',
|
|
1174
|
+
items: [{ description: 'Coffee beans 1 kg', quantity: 1, unitPriceCents: 2490, vatRate: 10, unit: 'piece' }],
|
|
1175
|
+
payment: { method: 'card', reference: payment.id },
|
|
1176
|
+
});
|
|
854
1177
|
```
|
|
855
1178
|
|
|
856
1179
|
For those cases the response's `notice` list contains `cash_receipt_required`:
|
|
@@ -869,9 +1192,9 @@ you then get the invoice that was already issued (`replayed: true`). The same
|
|
|
869
1192
|
key with different data gives `idempotency_conflict`.
|
|
870
1193
|
|
|
871
1194
|
Validation errors arrive as `validation` with field paths
|
|
872
|
-
(`
|
|
873
|
-
The contract itself ships as data (`
|
|
874
|
-
`@kreiseck/kasseneck-api/fixtures/
|
|
1195
|
+
(`invoiceFieldErrors(error)` → `[{ field: 'items[0].vatRate', message }]`).
|
|
1196
|
+
The contract itself ships as data (`INVOICE_REQUESTS`) and as a JSON Schema at
|
|
1197
|
+
`@kreiseck/kasseneck-api/fixtures/invoice-api.schema.json`; the backend
|
|
875
1198
|
validates against exactly this file.
|
|
876
1199
|
|
|
877
1200
|
### Calculating invoice totals in advance
|
|
@@ -893,7 +1216,7 @@ const { preview, notice } = await invoices.previewInvoice(request);
|
|
|
893
1216
|
await invoices.issueInvoice(request);
|
|
894
1217
|
```
|
|
895
1218
|
|
|
896
|
-
**Without the server.** `@kreiseck/kasseneck-api/
|
|
1219
|
+
**Without the server.** `@kreiseck/kasseneck-api/invoice/calc` is the pure
|
|
897
1220
|
calculation core: no transport, no key, runs in the browser too. It calculates
|
|
898
1221
|
with integers (BigInt) instead of floating point and rounds exactly once per
|
|
899
1222
|
VAT rate. Prices are in micro-euros (`unitPriceMicros`), quantities in
|
|
@@ -901,19 +1224,19 @@ thousandths (`quantityMilli`), discount and VAT rate in hundredths of a
|
|
|
901
1224
|
percent (`discountBp`, `vatRateBp`):
|
|
902
1225
|
|
|
903
1226
|
```ts
|
|
904
|
-
import {
|
|
1227
|
+
import { calculateInvoice, itemFromEuro } from '@kreiseck/kasseneck-api/invoice/calc';
|
|
905
1228
|
|
|
906
|
-
|
|
1229
|
+
calculateInvoice(
|
|
907
1230
|
[{ unitPriceMicros: 14_790_000, quantityMilli: 1000, vatRateBp: 2000 }],
|
|
908
1231
|
{ priceMode: 'gross' },
|
|
909
1232
|
);
|
|
910
1233
|
// { netCents: 1233, vatCents: 246, grossCents: 1479, byRate: [{ rateBp: 2000, … }], lines: […] }
|
|
911
1234
|
|
|
912
|
-
|
|
1235
|
+
itemFromEuro({ unitPrice: 14.79, quantity: 1, vatRate: 20 });
|
|
913
1236
|
// { ok: true, position: { unitPriceMicros: 14790000, quantityMilli: 1000, discountBp: 0, vatRateBp: 2000 } }
|
|
914
1237
|
```
|
|
915
1238
|
|
|
916
|
-
`
|
|
1239
|
+
`itemFromEuro(item)` converts a euro line (`unitPrice`, `quantity`,
|
|
917
1240
|
`vatRate`, `discountPct`) into this form without loss, or names the field and
|
|
918
1241
|
the reason when that is not possible. Since 23 September 2026 the server
|
|
919
1242
|
calculates every new invoice with this core. In **gross mode** the gross amount
|
|
@@ -921,17 +1244,47 @@ per rate is the agreed price: net = round(gross × 100 / (100 + rate)),
|
|
|
921
1244
|
VAT = gross − net. In **net mode** the VAT per rate is rounded from the net
|
|
922
1245
|
sum. Rounding is commercial (half a cent rounds away from zero). Totals are
|
|
923
1246
|
positive for credit notes too; the sign is in the document type
|
|
924
|
-
(`docType: '
|
|
925
|
-
`fixtures/
|
|
1247
|
+
(`docType: 'credit_note'`). Test cases: `fixtures/invoice-calc.json`,
|
|
1248
|
+
`fixtures/invoice-calc-random.json`, `fixtures/item-from-euro.json`.
|
|
926
1249
|
|
|
927
|
-
**`
|
|
1250
|
+
**`computeInvoiceTotals` is deprecated.** The older helper in `…/invoice` works on
|
|
928
1251
|
`unitPriceCents` lines with the previous floating-point formula and does not
|
|
929
1252
|
run through the core. At half-cent boundaries it can differ from an invoice
|
|
930
1253
|
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 `
|
|
1254
|
+
rates. Example: € 21.35 net at 10 % gives € 23.48 gross with `computeInvoiceTotals`,
|
|
932
1255
|
but € 23.49 with the core and on the invoice. It stays unchanged for existing
|
|
933
|
-
callers; use `
|
|
934
|
-
the old formula: `fixtures/
|
|
1256
|
+
callers; use `calculateInvoice` or `previewInvoice` in new code. Test cases for
|
|
1257
|
+
the old formula: `fixtures/invoice-totals.json`.
|
|
1258
|
+
|
|
1259
|
+
## Migrating from 0.x
|
|
1260
|
+
|
|
1261
|
+
1.0 is one breaking step: the wire, the exported names and the contract files
|
|
1262
|
+
all become English at once. The full list is in the
|
|
1263
|
+
[CHANGELOG](https://github.com/kreiseck-at/kasseneck-api/blob/main/CHANGELOG.md#100);
|
|
1264
|
+
the fixture renames are machine-readable in `fixtures/renames-1.0.json`. The
|
|
1265
|
+
short version:
|
|
1266
|
+
|
|
1267
|
+
- **Wire.** Only `/v3`: `api.kasseneck.at/v3` and `kasse.kasseneck.at/api/v3`.
|
|
1268
|
+
A `baseUrl` ending in `/v1` or `/api` throws. `baseUrl` now covers public
|
|
1269
|
+
calls only; whoever passed it to pairing, sign-in or register calls (the
|
|
1270
|
+
browser register used `/api`) switches to `posBaseUrl: '/api/v3'`.
|
|
1271
|
+
- **Payments.** `payments[]` is mandatory; `paymentMethod`,
|
|
1272
|
+
`createCancelReceipt` and cancelling through `createReceipt` are gone.
|
|
1273
|
+
`receiptDueCents` needs `tipRecipient` for a tip without recipients.
|
|
1274
|
+
- **Outcome.** Check `isOutcomeUnknown(error)` before any retry of a sale or
|
|
1275
|
+
cancellation.
|
|
1276
|
+
- **Names.** German export names are English (`KASSE_BASE_URL` is
|
|
1277
|
+
`POS_BASE_URL`, `mergeKasseSettings` is `mergePosSettings`,
|
|
1278
|
+
`rechnungRechnen` is `calculateInvoice`, …), and so are field names, values
|
|
1279
|
+
and error codes. There are no aliases.
|
|
1280
|
+
- **Subpaths.** `./kasse` is `./pos`, `./rechnung` is `./invoice`,
|
|
1281
|
+
`./rechnung/rechnen` is `./invoice/calc`; `./stored` is new.
|
|
1282
|
+
- **Texts.** Catalogue keys and placeholders are English
|
|
1283
|
+
(`storno.ergebnis_unklar` is `cancellation.outcome_unknown`, `{betrag}` is
|
|
1284
|
+
`{amount}`); every rendered text is byte for byte the same.
|
|
1285
|
+
|
|
1286
|
+
0.x stays on `/v1` and gets fixes only, published under the npm dist-tag `legacy`
|
|
1287
|
+
(`npm install @kreiseck/kasseneck-api@legacy`).
|
|
935
1288
|
|
|
936
1289
|
## Development
|
|
937
1290
|
|
|
@@ -953,18 +1306,20 @@ address returns the HTML fallback page instead of the function, and no mock
|
|
|
953
1306
|
sees that.
|
|
954
1307
|
|
|
955
1308
|
The check needs **no credentials**. A call without authentication answers,
|
|
956
|
-
when there is a function behind it, with
|
|
957
|
-
`
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
1309
|
+
when there is a function behind it, with an error envelope (`status` field)
|
|
1310
|
+
and the header `Kasseneck-Api-Version: v3`. That is the proof: the call was
|
|
1311
|
+
accepted and authentication was checked. An HTML page, a 404 or a missing
|
|
1312
|
+
marker proves that there is no `/v3` function. That is why the script looks
|
|
1313
|
+
for the envelope and the marker, not for success. Each call is asked at the
|
|
1314
|
+
address the transport really picks for it: public calls at
|
|
1315
|
+
`api.kasseneck.at/v3`, register-only calls at `kasse.kasseneck.at/api/v3`.
|
|
961
1316
|
|
|
962
1317
|
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.
|
|
1318
|
+
network it says so and exits with 0. CI runs the local part on every push;
|
|
1319
|
+
the network part runs daily. A call that deliberately has no function would be
|
|
1320
|
+
listed with a reason in `scripts/erreichbarkeit-ausnahmen.json`; since 1.0 that
|
|
1321
|
+
list is empty. If an exception becomes reachable, the check fails; otherwise
|
|
1322
|
+
the list would never shrink.
|
|
968
1323
|
|
|
969
1324
|
## Contract files for the twin packages
|
|
970
1325
|
|
|
@@ -974,19 +1329,24 @@ in machine form what both sides agreed on, among them:
|
|
|
974
1329
|
|
|
975
1330
|
| File | Contents | Generated by |
|
|
976
1331
|
|---|---|---|
|
|
977
|
-
| `
|
|
978
|
-
| `
|
|
1332
|
+
| `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` |
|
|
1333
|
+
| `stored/pos-settings-defaults.json` | the same defaults in the stored (internal, German) form (`betrieb`, `geraet`) | `npm run fixtures:kasse` |
|
|
1334
|
+
| `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
1335
|
| `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
|
-
| `
|
|
1336
|
+
| `pos-texts.json` | the register's message catalogue | `npm run fixtures:texte` |
|
|
1337
|
+
| `invoice-texts.json` | invoice texts in both languages | `npm run fixtures:rechnungstexte` |
|
|
1338
|
+
| `invoice-api.schema.json` | JSON Schema of the invoice API | `npm run fixtures:rechnung` |
|
|
1339
|
+
| `pos-message-cases.json` | error cases and the message each one must show in both registers | by hand |
|
|
1340
|
+
| `receipt-due-generated.json` | 1206 amounts due computed by the backend's own code, the reference for `receiptDueCents` | `node scripts/v3-zahlbetrag-generieren.mjs` |
|
|
1341
|
+
| `v3/` | the backend's `/v3` contract (vocabulary, response cases, stored cases, amounts due), copied byte for byte | `node scripts/v3-vertrag-holen.mjs` |
|
|
1342
|
+
| `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
1343
|
|
|
984
1344
|
They are generated and never edited by hand. CI regenerates the register
|
|
985
|
-
settings and `
|
|
1345
|
+
settings and `surface.json` and fails if they differ from the committed
|
|
986
1346
|
files; the test suite checks the others against the code.
|
|
987
1347
|
|
|
988
|
-
`
|
|
989
|
-
`
|
|
1348
|
+
`surface.json`, `hobex-hps-codes.json`, `pos-texts.json` and
|
|
1349
|
+
`invoice-texts.json` carry the package version. **After every `npm version`,
|
|
990
1350
|
regenerate them and commit them along**, otherwise the tests fail.
|
|
991
1351
|
|
|
992
1352
|
### And the other direction
|