@kreiseck/kasseneck-api 0.17.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +63 -0
- package/README.md +26 -0
- package/dist/cjs/client/aufrufe.d.ts +1 -1
- package/dist/cjs/client/aufrufe.js +1 -0
- package/dist/cjs/payments/hobex-hps/index.d.ts +1 -1
- package/dist/cjs/payments/hobex-hps/index.js +3 -1
- package/dist/cjs/payments/hobex-hps/payments.d.ts +11 -0
- package/dist/cjs/payments/hobex-hps/payments.js +73 -4
- package/dist/cjs/payments/hobex-hps/tecs-codes.d.ts +16 -0
- package/dist/cjs/payments/hobex-hps/tecs-codes.js +366 -0
- package/dist/cjs/payments/hobex-hps/transaction-response.d.ts +56 -8
- package/dist/cjs/payments/hobex-hps/transaction-response.js +135 -65
- package/dist/cjs/rechnung/api.d.ts +3 -1
- package/dist/cjs/rechnung/api.js +1 -0
- package/dist/cjs/rechnung/endpunkte.d.ts +11 -1
- package/dist/cjs/rechnung/endpunkte.js +22 -0
- package/dist/cjs/rechnung/index.d.ts +3 -3
- package/dist/cjs/rechnung/index.js +4 -1
- package/dist/cjs/rechnung/typen.d.ts +48 -1
- package/dist/cjs/rechnung/vertrag.d.ts +24 -2
- package/dist/cjs/rechnung/vertrag.js +43 -1
- package/dist/esm/client/aufrufe.d.ts +1 -1
- package/dist/esm/client/aufrufe.js +1 -0
- package/dist/esm/payments/hobex-hps/index.d.ts +1 -1
- package/dist/esm/payments/hobex-hps/index.js +1 -1
- package/dist/esm/payments/hobex-hps/payments.d.ts +11 -0
- package/dist/esm/payments/hobex-hps/payments.js +74 -5
- package/dist/esm/payments/hobex-hps/tecs-codes.d.ts +16 -0
- package/dist/esm/payments/hobex-hps/tecs-codes.js +363 -0
- package/dist/esm/payments/hobex-hps/transaction-response.d.ts +56 -8
- package/dist/esm/payments/hobex-hps/transaction-response.js +133 -65
- package/dist/esm/rechnung/api.d.ts +3 -1
- package/dist/esm/rechnung/api.js +2 -1
- package/dist/esm/rechnung/endpunkte.d.ts +11 -1
- package/dist/esm/rechnung/endpunkte.js +21 -0
- package/dist/esm/rechnung/index.d.ts +3 -3
- package/dist/esm/rechnung/index.js +2 -2
- package/dist/esm/rechnung/typen.d.ts +48 -1
- package/dist/esm/rechnung/vertrag.d.ts +24 -2
- package/dist/esm/rechnung/vertrag.js +42 -0
- package/fixtures/hobex-hps-codes.json +4075 -52
- package/fixtures/kasse-texte.json +1 -1
- package/fixtures/oberflaeche.json +16 -3
- package/fixtures/rechnung-api-beispiele/issue-bezahlt.json +32 -0
- package/fixtures/rechnung-api-beispiele/issue-fehler-zahlungsart.json +26 -0
- package/fixtures/rechnung-api-beispiele/zahlung-fehler-ohne-schluessel.json +14 -0
- package/fixtures/rechnung-api-beispiele/zahlung-nachtrag.json +14 -0
- package/fixtures/rechnung-api.schema.json +82 -2
- package/fixtures/rechnung-texte.json +1 -1
- package/package.json +1 -1
|
@@ -25,66 +25,84 @@
|
|
|
25
25
|
* bis dahin unbenannter Code ([TECHNICAL_ERROR_CODE], `9900`) war darueber
|
|
26
26
|
* schluessig und haette eine Zahlung, unter der tatsaechlich Geld geflossen
|
|
27
27
|
* sein kann, als `declined` gemeldet.
|
|
28
|
+
*
|
|
29
|
+
* Seit 16.09.2026 kommt die TECS-Liste dazu (`tecs-codes.ts`): das HPS
|
|
30
|
+
* reicht die Codes der TECS-Plattform durch, auf der hobex autorisiert. Neu
|
|
31
|
+
* sind dabei [HpsCode.sendReversal] (Storno nachschicken, siehe
|
|
32
|
+
* `payments.ts`) und die Schreibweise: TECS fuehrt `0055`, das Terminal
|
|
33
|
+
* sendet `55` -- [normalizeHpsCode] macht beides zu einem Code.
|
|
34
|
+
*
|
|
35
|
+
* **Einen neuen Code aufnehmen:** Eintrag hier oder in `tecs-codes.ts`,
|
|
36
|
+
* derselbe im Dart-Zwilling, `npm run fixtures:hobex-hps-codes`; ein neuer
|
|
37
|
+
* Grund braucht in jeder Kasse eine Uebersetzung.
|
|
28
38
|
*/
|
|
39
|
+
import { TECS_CODES } from './tecs-codes.js';
|
|
29
40
|
/** Der Satz fuer den Bediener je Grund, deutsch. */
|
|
30
41
|
export const HPS_REASON_HINTS = {
|
|
31
42
|
approved: 'Vom Terminal genehmigt.',
|
|
43
|
+
approvedWithCondition: 'Das Terminal meldet eine Genehmigung mit Vorbehalt (etwa nur über einen Teilbetrag). Ob und in welcher Höhe belastet wurde, bitte am Terminalbeleg prüfen — nicht erneut kassieren, bevor es geklärt ist.',
|
|
32
44
|
aborted: 'Der Vorgang wurde abgebrochen. Es wurde kein Geld bewegt.',
|
|
33
|
-
noCard: 'Es wurde keine Karte vorgehalten. Es wurde kein Geld bewegt — '
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
terminalBusy: 'Das Terminal ist noch mit einem anderen Vorgang beschäftigt. Es '
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
+ 'Vorgang selbst storniert. Es wird kein Geld bewegt — bitte erneut '
|
|
64
|
-
+ 'versuchen.',
|
|
65
|
-
hostFault: 'Die Verbindung zwischen Terminal und hobex ist gestört. Ob die '
|
|
66
|
-
+ 'Karte belastet wurde, weiß das Terminal nicht — bitte nicht erneut '
|
|
67
|
-
+ 'kassieren, bevor es geklärt ist.',
|
|
68
|
-
internalError: 'Das Terminal meldet einen internen Fehler. Ob die Karte belastet '
|
|
69
|
-
+ 'wurde, ist unklar — bitte nicht erneut kassieren, bevor es geklärt '
|
|
70
|
-
+ 'ist.',
|
|
45
|
+
noCard: 'Es wurde keine Karte vorgehalten. Es wurde kein Geld bewegt — bitte erneut versuchen.',
|
|
46
|
+
cardReadFailed: 'Die Karte konnte nicht gelesen werden. Es wurde kein Geld bewegt — bitte erneut versuchen, notfalls die Karte stecken statt auflegen.',
|
|
47
|
+
cardDeclined: 'Die Karte wurde vom Terminal abgelehnt. Es wurde kein Geld bewegt — bitte eine andere Karte oder Zahlungsart verwenden.',
|
|
48
|
+
issuerDeclined: 'Die Zahlung wurde von der Bank abgelehnt. Es wurde kein Geld bewegt — bitte eine andere Karte oder Zahlungsart verwenden.',
|
|
49
|
+
cardBlocked: 'Die Karte ist gesperrt. Es wurde kein Geld bewegt — bitte eine andere Karte oder Zahlungsart verwenden.',
|
|
50
|
+
cardExpired: 'Die Karte ist abgelaufen. Es wurde kein Geld bewegt — bitte eine andere Karte oder Zahlungsart verwenden.',
|
|
51
|
+
insufficientFunds: 'Das Konto ist nicht gedeckt oder das Kartenlimit ist erreicht. Es wurde kein Geld bewegt — bitte eine andere Karte oder Zahlungsart verwenden.',
|
|
52
|
+
wrongPin: 'Die PIN war falsch. Es wurde kein Geld bewegt — bitte erneut versuchen.',
|
|
53
|
+
pinTriesExceeded: 'Die PIN wurde zu oft falsch eingegeben. Es wurde kein Geld bewegt — bitte eine andere Karte oder Zahlungsart verwenden.',
|
|
54
|
+
pinRequired: 'Die Bank verlangt die PIN. Es wurde kein Geld bewegt — bitte erneut versuchen, die Karte stecken und die PIN eingeben.',
|
|
55
|
+
amountInvalid: 'Das Terminal nimmt diesen Betrag nicht an. Es wurde kein Geld bewegt.',
|
|
56
|
+
tipNotSelected: 'Das Trinkgeld wurde nicht rechtzeitig gewählt. Es wurde kein Geld bewegt — bitte erneut versuchen.',
|
|
57
|
+
terminalBusy: 'Das Terminal ist noch mit einem anderen Vorgang beschäftigt. Es wurde kein Geld bewegt — kurz warten und erneut versuchen.',
|
|
58
|
+
terminalBlocked: 'Das Terminal ist gesperrt. Es wurde kein Geld bewegt — bitte hobex kontaktieren.',
|
|
59
|
+
terminalSetup: 'Das Terminal ist nicht richtig eingerichtet. Es wurde kein Geld bewegt — bitte die Terminal-ID in den Einstellungen prüfen, sonst hobex kontaktieren.',
|
|
60
|
+
acquirerSetup: 'hobex nimmt dieses Terminal oder diesen Händler so nicht an. Es wurde kein Geld bewegt — bitte hobex kontaktieren.',
|
|
61
|
+
terminalFault: 'Das Terminal meldet eine Störung. Es wurde kein Geld bewegt — bitte das Terminal neu starten und erneut versuchen.',
|
|
62
|
+
requestRejected: 'Das Terminal hat die Anfrage abgewiesen. Es wurde kein Geld bewegt — tritt das wieder auf, bitte den Support kontaktieren.',
|
|
63
|
+
hostRejected: 'hobex hat die Zahlung abgewiesen. Es wurde kein Geld bewegt — bitte erneut versuchen; tritt das wieder auf, hobex kontaktieren.',
|
|
64
|
+
hostUnavailable: 'Die Bank oder hobex ist gerade nicht erreichbar. Es wurde kein Geld bewegt — bitte später erneut versuchen oder eine andere Zahlungsart verwenden.',
|
|
65
|
+
invalidTransaction: 'Das Terminal kennt die ursprüngliche Zahlung nicht. Es wurde kein Geld bewegt.',
|
|
66
|
+
refundPassword: 'Das Passwort für die Gutschrift war falsch oder wurde nicht eingegeben. Es wurde nichts ausgezahlt.',
|
|
67
|
+
refundDisabled: 'Gutschriften sind an diesem Terminal abgeschaltet. Es wurde nichts ausgezahlt — bitte hobex kontaktieren.',
|
|
68
|
+
refundRejected: 'Die Gutschrift wurde abgewiesen (Betrag zu hoch, bereits erstattet oder zu viele Versuche). Es wurde nichts ausgezahlt.',
|
|
69
|
+
hostTimeoutReversed: 'hobex hat nicht rechtzeitig geantwortet, das Terminal hat den Vorgang selbst storniert. Es wird kein Geld bewegt — bitte erneut versuchen.',
|
|
70
|
+
reversedByHost: 'Die Zahlung wurde wegen einer Störung automatisch storniert. Es wurde kein Geld bewegt — bitte erneut versuchen.',
|
|
71
|
+
voidedAfterHostFault: 'hobex hat nicht sauber geantwortet, die Zahlung wurde deshalb sicherheitshalber storniert. Es wurde kein Geld bewegt — bitte erneut versuchen.',
|
|
72
|
+
hostFault: 'Die Verbindung zwischen Terminal und hobex ist gestört. Ob die Karte belastet wurde, weiß das Terminal nicht — bitte nicht erneut kassieren, bevor es geklärt ist.',
|
|
73
|
+
hostTimeout: 'hobex hat nicht rechtzeitig geantwortet. Ob die Karte belastet wurde, weiß das Terminal nicht — bitte nicht erneut kassieren, bevor es geklärt ist.',
|
|
74
|
+
internalError: 'Das Terminal meldet einen internen Fehler. Ob die Karte belastet wurde, ist unklar — bitte nicht erneut kassieren, bevor es geklärt ist.',
|
|
71
75
|
canceled: 'Die Zahlung ist aufgehoben.',
|
|
72
|
-
|
|
73
|
-
|
|
76
|
+
cancelDenied: 'Die Zahlung lässt sich nicht mehr aufheben und bleibt belastet — bitte stattdessen eine Gutschrift ausführen.',
|
|
77
|
+
originalDeclined: 'Die ursprüngliche Zahlung war abgelehnt; es gibt nichts aufzuheben.',
|
|
78
|
+
notAbortable: 'Der Vorgang ist bereits abgeschlossen und lässt sich nicht mehr abbrechen.',
|
|
74
79
|
noStatement: 'Das Terminal hat zu diesem Vorgang keine Auskunft.',
|
|
75
|
-
technicalError: 'Das Terminal meldet einen technischen Fehler; über den Vorgang '
|
|
76
|
-
+ 'sagt das nichts.',
|
|
80
|
+
technicalError: 'Das Terminal meldet einen technischen Fehler; über den Vorgang sagt das nichts.',
|
|
77
81
|
unknown: 'Das Terminal nennt einen Code, dessen Bedeutung nicht bekannt ist.',
|
|
78
82
|
};
|
|
79
83
|
/**
|
|
80
|
-
* Die
|
|
81
|
-
* geflossen ist, weiss das Terminal nicht.
|
|
84
|
+
* Die Gruende hinter einem Code mit `effect: 'hostUncertain'`: ob (und wie
|
|
85
|
+
* viel) Geld geflossen ist, weiss das Terminal nicht.
|
|
82
86
|
*/
|
|
83
87
|
export function isHostUncertainReason(reason) {
|
|
84
|
-
return reason === '
|
|
88
|
+
return reason === 'approvedWithCondition'
|
|
89
|
+
|| reason === 'hostFault'
|
|
90
|
+
|| reason === 'hostTimeout'
|
|
91
|
+
|| reason === 'internalError';
|
|
85
92
|
}
|
|
86
|
-
function code(c, title, meaning, effect, reason, source, rejectsRequest = false) {
|
|
87
|
-
return {
|
|
93
|
+
function code(c, title, meaning, effect, reason, source, rejectsRequest = false, extra = {}) {
|
|
94
|
+
return {
|
|
95
|
+
code: c,
|
|
96
|
+
title,
|
|
97
|
+
meaning,
|
|
98
|
+
conclusive: effect === 'conclusive',
|
|
99
|
+
effect,
|
|
100
|
+
reason,
|
|
101
|
+
source,
|
|
102
|
+
rejectsRequest,
|
|
103
|
+
sendReversal: extra.sendReversal ?? false,
|
|
104
|
+
tecsTitle: extra.tecsTitle ?? null,
|
|
105
|
+
};
|
|
88
106
|
}
|
|
89
107
|
/**
|
|
90
108
|
* Die vollstaendige Codetabelle — Vertrag mit dem Dart-Zwilling
|
|
@@ -109,19 +127,20 @@ function code(c, title, meaning, effect, reason, source, rejectsRequest = false)
|
|
|
109
127
|
* dokumentierten aufsteigend -- identisch mit dem Dart-Zwilling.
|
|
110
128
|
*/
|
|
111
129
|
export const HPS_CODES = [
|
|
112
|
-
code('0', 'Authorized', 'genehmigt', 'conclusive', 'approved', 'measuredAndDocumented'),
|
|
130
|
+
code('0', 'Authorized', 'genehmigt', 'conclusive', 'approved', 'measuredAndDocumented', false, { tecsTitle: 'Approved Transaction / OK' }),
|
|
113
131
|
code('9002', 'Invalid Transaction', 'ungueltiger Vorgang -- das Terminal hat den Vorgang selbst als '
|
|
114
|
-
+ 'unzulaessig verworfen, bevor irgendetwas in Bewegung kam', 'conclusive', 'invalidTransaction', '
|
|
132
|
+
+ 'unzulaessig verworfen, bevor irgendetwas in Bewegung kam', 'conclusive', 'invalidTransaction', 'measuredAndDocumented', true, { tecsTitle: 'Invalid Transaction' }),
|
|
115
133
|
code('9011', 'Transaction Canceled', 'aufgehoben ("Transaction Canceled") -- der Vorgang unter dieser '
|
|
116
|
-
+ 'Kennung wurde storniert', 'conclusive', 'canceled', '
|
|
134
|
+
+ 'Kennung wurde storniert', 'conclusive', 'canceled', 'measuredAndDocumented', false, { tecsTitle: 'Transaction cancelled' }),
|
|
117
135
|
code('9027', 'Original Tx not found', 'keine Aussage -- steht gleichermassen fuer "nie gesehen", "laeuft '
|
|
118
|
-
+ 'gerade", "Karte nicht aufgelegt" und "abgebrochen"', 'noStatement', 'noStatement', '
|
|
136
|
+
+ 'gerade", "Karte nicht aufgelegt" und "abgebrochen"', 'noStatement', 'noStatement', 'measuredAndDocumented', false, { tecsTitle: 'Original Transaction not found' }),
|
|
119
137
|
code('9900', 'Technical Error Database', '"Technical Error Database" -- gemessen im Zusammenhang mit einer '
|
|
120
|
-
+ 'nicht rein numerischen Kennung
|
|
121
|
-
+ '
|
|
138
|
+
+ 'nicht rein numerischen Kennung, NACHDEM die Karte verarbeitet war; '
|
|
139
|
+
+ 'laut TECS ein Datenbankfehler im Backend -- ob belastet wurde, ist '
|
|
140
|
+
+ 'offen', 'hostUncertain', 'internalError', 'measuredAndDocumented', false, { tecsTitle: 'Technical Error: Database (General)' }),
|
|
122
141
|
code('9003', 'Invalid Amount', '"Invalid Amount" -- der Betrag wird abgewiesen, BEVOR eine Karte '
|
|
123
142
|
+ 'verlangt wird (28.08.2026: 99999,99 EUR, Antwort nach 15,7 s ohne '
|
|
124
|
-
+ 'Kartenaufforderung); nichts belastet', 'conclusive', 'amountInvalid', '
|
|
143
|
+
+ 'Kartenaufforderung); nichts belastet', 'conclusive', 'amountInvalid', 'measuredAndDocumented', false, { tecsTitle: 'Invalid Amount' }),
|
|
125
144
|
code('100002', 'Aborted', 'abgebrochen ("Aborted") -- ueber die Kasse oder am Terminal; '
|
|
126
145
|
+ 'nichts belastet', 'conclusive', 'aborted', 'measuredAndDocumented'),
|
|
127
146
|
code('100003', 'Card not present', 'Karte nicht aufgelegt ("Card not present") -- innerhalb der Frist '
|
|
@@ -136,7 +155,7 @@ export const HPS_CODES = [
|
|
|
136
155
|
+ 'gemessene Host-Ablehnung ueberhaupt (02.09.2026 im Betrieb, TID '
|
|
137
156
|
+ '3556988, HPS 1.11.4, Firmware 2.3.9): die Zahlung antwortete '
|
|
138
157
|
+ 'direkt damit, die Statusabfrage danach elfmal in Folge ebenso -- '
|
|
139
|
-
+ 'eine Host-Ablehnung bleibt am Terminal abrufbar; nichts belastet', 'conclusive', 'wrongPin', '
|
|
158
|
+
+ 'eine Host-Ablehnung bleibt am Terminal abrufbar; nichts belastet', 'conclusive', 'wrongPin', 'measuredAndDocumented', false, { tecsTitle: 'Incorrect PIN' }),
|
|
140
159
|
// ---- ab hier: Antwortcodeliste von hobex, erhalten 11.09.2026 ----
|
|
141
160
|
code('100001', 'Bad Request', 'fehlerhafte Anfrage der Kasse ("Bad Request") -- Abweisung vor dem '
|
|
142
161
|
+ 'Kartenfluss; nichts belastet', 'conclusive', 'requestRejected', 'documented', true),
|
|
@@ -148,10 +167,10 @@ export const HPS_CODES = [
|
|
|
148
167
|
+ 'Betrieb danach dauerhaft 9027; nichts belastet', 'conclusive', 'cardReadFailed', 'documented'),
|
|
149
168
|
code('100006', 'Communication with TecsXml failed', 'keine Verbindung zum hobex-Host ("Communication with TecsXml '
|
|
150
169
|
+ 'failed") -- das Terminal storniert NICHT selbst; ob beim Host '
|
|
151
|
-
+ 'etwas angekommen ist, weiss das Terminal nicht', 'hostUncertain', 'hostFault', 'documented'),
|
|
170
|
+
+ 'etwas angekommen ist, weiss das Terminal nicht', 'hostUncertain', 'hostFault', 'documented', false, { sendReversal: true }),
|
|
152
171
|
code('100007', 'Processing of TecsXml step failed', 'Schritt beim hobex-Host gescheitert ("Processing of TecsXml step '
|
|
153
172
|
+ 'failed") -- das Terminal storniert NICHT selbst; ob beim Host '
|
|
154
|
-
+ 'belastet wurde, weiss das Terminal nicht', 'hostUncertain', 'hostFault', 'documented'),
|
|
173
|
+
+ 'belastet wurde, weiss das Terminal nicht', 'hostUncertain', 'hostFault', 'documented', false, { sendReversal: true }),
|
|
155
174
|
code('100008', 'Invalid TID', 'Terminal-Kennung passt nicht ("Invalid TID") -- die TID der '
|
|
156
175
|
+ 'Anfrage ist nicht die eingerichtete; Abweisung vor dem '
|
|
157
176
|
+ 'Kartenfluss, nichts belastet (am Geraet gemessen wurde dafuer '
|
|
@@ -184,18 +203,18 @@ export const HPS_CODES = [
|
|
|
184
203
|
+ 'IN_OPERATION; nichts belastet', 'conclusive', 'terminalBlocked', 'documented', true),
|
|
185
204
|
code('100023', 'Invalid message type', 'ungueltige Antwort des hobex-Hosts ("Invalid message type") -- '
|
|
186
205
|
+ 'Nachricht und Antwortcode in den UserData ungueltig; ob beim Host '
|
|
187
|
-
+ 'belastet wurde, weiss das Terminal nicht', 'hostUncertain', 'hostFault', 'documented'),
|
|
206
|
+
+ 'belastet wurde, weiss das Terminal nicht', 'hostUncertain', 'hostFault', 'documented', false, { sendReversal: true }),
|
|
188
207
|
code('100024', 'Transaction completion has failed', 'Abschluss des Online-Vorgangs gescheitert ("Transaction completion '
|
|
189
208
|
+ 'has failed") -- NACH der Anfrage beim Host; ob belastet bleibt, '
|
|
190
|
-
+ 'weiss das Terminal nicht', 'hostUncertain', 'hostFault', 'documented'),
|
|
209
|
+
+ 'weiss das Terminal nicht', 'hostUncertain', 'hostFault', 'documented', false, { sendReversal: true }),
|
|
191
210
|
code('100025', 'Refund transactions are disabled', 'Gutschriften abgeschaltet ("Refund transactions are disabled") -- '
|
|
192
211
|
+ 'in der Geraeteeinstellung; nichts ausgezahlt', 'conclusive', 'refundDisabled', 'documented'),
|
|
193
212
|
code('100026', 'Transaction was declined.', 'Host-Antwort passt nicht zur Karte ("Transaction was declined.") '
|
|
194
213
|
+ '-- Chip-Daten fuer eine Karte ohne Chip; das Terminal lehnt ab, ob '
|
|
195
|
-
+ 'der Host zuvor belastet hat, ist offen', 'hostUncertain', 'hostFault', 'documented'),
|
|
214
|
+
+ 'der Host zuvor belastet hat, ist offen', 'hostUncertain', 'hostFault', 'documented', false, { sendReversal: true }),
|
|
196
215
|
code('100027', 'Unsupported UserData in TecsXml Response', 'unbekannte Daten in der Antwort des hobex-Hosts ("Unsupported '
|
|
197
216
|
+ 'UserData in TecsXml Response") -- ob beim Host belastet wurde, '
|
|
198
|
-
+ 'weiss das Terminal nicht', 'hostUncertain', 'hostFault', 'documented'),
|
|
217
|
+
+ 'weiss das Terminal nicht', 'hostUncertain', 'hostFault', 'documented', false, { sendReversal: true }),
|
|
199
218
|
code('100028', 'Tip selection process has failed.', 'Trinkgeld nicht gewaehlt ("Tip selection process has failed.") -- '
|
|
200
219
|
+ 'nicht innerhalb der Frist; nichts belastet', 'conclusive', 'tipNotSelected', 'documented'),
|
|
201
220
|
code('100029', 'Communication with TecsXml timeout', 'Zeitueberschreitung zum hobex-Host ("Communication with TecsXml '
|
|
@@ -207,6 +226,7 @@ export const HPS_CODES = [
|
|
|
207
226
|
code('100999', 'Internal Error', 'interner Fehler des Terminals ("Internal Error") -- Sammelcode '
|
|
208
227
|
+ 'fuer jeden sonst nicht benannten Fehler, an jeder Stelle des '
|
|
209
228
|
+ 'Ablaufs moeglich; ob belastet wurde, ist offen', 'hostUncertain', 'internalError', 'documented'),
|
|
229
|
+
...TECS_CODES,
|
|
210
230
|
];
|
|
211
231
|
/**
|
|
212
232
|
* @deprecated Seit 0.10.0 [HPS_CODES] -- die Tabelle fuehrt nicht mehr nur
|
|
@@ -328,9 +348,38 @@ export const TERMINAL_BUSY_HTTP_STATUS = 409;
|
|
|
328
348
|
*/
|
|
329
349
|
export const NOT_FOUND_HTTP_STATUS = 404;
|
|
330
350
|
const CODE_BY_ID = new Map(HPS_CODES.map((c) => [c.code, c]));
|
|
331
|
-
|
|
351
|
+
const PLATZHALTER = 'xx';
|
|
352
|
+
/** Eintraege, die eine ganze Familie abdecken (`81xx`), nach ihrem Praefix. */
|
|
353
|
+
const CODE_BY_PREFIX = new Map(HPS_CODES.filter((c) => c.code.endsWith(PLATZHALTER)).map((c) => [c.code.slice(0, -PLATZHALTER.length), c]));
|
|
354
|
+
/**
|
|
355
|
+
* Die Schreibweise, unter der [code] in [HPS_CODES] steht: ein rein
|
|
356
|
+
* numerischer Code ohne fuehrende Nullen (`0055` -> `55`, `0000` -> `0`),
|
|
357
|
+
* jeder andere unveraendert. Ohne diese Angleichung waere ein `0000` kein
|
|
358
|
+
* `0` -- und damit eine ABLEHNUNG einer genehmigten Zahlung.
|
|
359
|
+
* [parseHpsTransactionResponse] gleicht deshalb schon beim Einlesen an.
|
|
360
|
+
*/
|
|
361
|
+
export function normalizeHpsCode(code) {
|
|
362
|
+
const c = code.trim();
|
|
363
|
+
if (!/^\d+$/.test(c))
|
|
364
|
+
return c;
|
|
365
|
+
const ohneNullen = c.replace(/^0+/, '');
|
|
366
|
+
return ohneNullen === '' ? '0' : ohneNullen;
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Der Eintrag zu [code] in [HPS_CODES], oder `undefined`, wenn seine
|
|
370
|
+
* Bedeutung nicht feststeht. Findet beide Schreibweisen
|
|
371
|
+
* ([normalizeHpsCode]) und die Familien mit Platzhalter (`8105` -> `81xx`).
|
|
372
|
+
*/
|
|
332
373
|
export function hpsCodeInfo(code) {
|
|
333
|
-
|
|
374
|
+
if (code === undefined)
|
|
375
|
+
return undefined;
|
|
376
|
+
const c = normalizeHpsCode(code);
|
|
377
|
+
const genau = CODE_BY_ID.get(c);
|
|
378
|
+
if (genau)
|
|
379
|
+
return genau;
|
|
380
|
+
if (c.length === 4 && /^\d+$/.test(c))
|
|
381
|
+
return CODE_BY_PREFIX.get(c.slice(0, 2));
|
|
382
|
+
return undefined;
|
|
334
383
|
}
|
|
335
384
|
/**
|
|
336
385
|
* Der Grund zu [code] -- `'unknown'` fuer einen Code ausserhalb der Tabelle,
|
|
@@ -374,7 +423,7 @@ export function parseHpsTransactionResponse(raw) {
|
|
|
374
423
|
// responseCode kommt teils als Zahl, teils als Zeichenkette — siehe
|
|
375
424
|
// Zwilling. Ein leerer String traegt keine Aussage und wird wie ein
|
|
376
425
|
// fehlendes Feld behandelt.
|
|
377
|
-
responseCode:
|
|
426
|
+
responseCode: normalizedCode(stringify(r['responseCode'])),
|
|
378
427
|
responseText: asString(r['responseText']),
|
|
379
428
|
state: asString(r['state']),
|
|
380
429
|
raw: r,
|
|
@@ -404,6 +453,14 @@ function stringify(v) {
|
|
|
404
453
|
function nonEmpty(v) {
|
|
405
454
|
return v === undefined || v === '' ? undefined : v;
|
|
406
455
|
}
|
|
456
|
+
/**
|
|
457
|
+
* Der Ergebniscode in der Schreibweise der Tabelle ([normalizeHpsCode]):
|
|
458
|
+
* `0000` wird `0`. Der Rumpf in `raw` bleibt unveraendert.
|
|
459
|
+
*/
|
|
460
|
+
function normalizedCode(v) {
|
|
461
|
+
const c = nonEmpty(v?.trim());
|
|
462
|
+
return c === undefined ? undefined : normalizeHpsCode(c);
|
|
463
|
+
}
|
|
407
464
|
/** `true`, wenn der Vorgang genehmigt ist. */
|
|
408
465
|
export function isApproved(res) {
|
|
409
466
|
return res.responseCode === APPROVED_CODE;
|
|
@@ -426,7 +483,10 @@ export function isNotAbortable(res) {
|
|
|
426
483
|
export function isNoStatement(res) {
|
|
427
484
|
return res.responseCode === NO_STATEMENT_CODE;
|
|
428
485
|
}
|
|
429
|
-
/**
|
|
486
|
+
/**
|
|
487
|
+
* `true`, wenn das Terminal einen technischen Fehler meldet (9900). Seit der
|
|
488
|
+
* TECS-Liste zugleich [isHostUncertain]: ob belastet wurde, ist offen.
|
|
489
|
+
*/
|
|
430
490
|
export function isTechnicalError(res) {
|
|
431
491
|
return res.responseCode === TECHNICAL_ERROR_CODE;
|
|
432
492
|
}
|
|
@@ -470,6 +530,14 @@ export function isConclusiveAsStatus(res) {
|
|
|
470
530
|
export function isHostUncertain(res) {
|
|
471
531
|
return hpsCodeInfo(res.responseCode)?.effect === 'hostUncertain';
|
|
472
532
|
}
|
|
533
|
+
/**
|
|
534
|
+
* `true`, wenn zu diesem Code ein Storno nachzuschicken ist
|
|
535
|
+
* ([HpsCode.sendReversal]) -- der Host hat nicht oder nicht brauchbar
|
|
536
|
+
* geantwortet, etwa `9908`.
|
|
537
|
+
*/
|
|
538
|
+
export function needsReversal(res) {
|
|
539
|
+
return hpsCodeInfo(res.responseCode)?.sendReversal ?? false;
|
|
540
|
+
}
|
|
473
541
|
/**
|
|
474
542
|
* `true`, wenn ein Ergebniscode VORHANDEN ist, dessen Bedeutung aber nicht
|
|
475
543
|
* feststeht -- er fehlt in [HPS_CODES]. Ein Code, den dieses Modell schlicht
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { type FetchLike } from '../client/transport.js';
|
|
8
8
|
import type { EInvoiceFormat, InvoiceLanguage } from './vertrag.js';
|
|
9
|
-
import type { Brand, CancelInvoiceRequest, CancelResult, CreditNoteRequest, CreditNoteResult, Customer, CustomerInput, CustomerPage, CustomerSearch, InvoiceDetail, InvoiceListQuery, InvoicePage, InvoiceSetupStatus, IssueInvoiceRequest, IssueResult } from './typen.js';
|
|
9
|
+
import type { Brand, CancelInvoiceRequest, CancelResult, CreditNoteRequest, CreditNoteResult, Customer, CustomerInput, CustomerPage, CustomerSearch, InvoiceDetail, InvoiceListQuery, InvoicePage, InvoiceSetupStatus, IssueInvoiceRequest, IssueResult, RecordPaymentRequest, RecordPaymentResult } from './typen.js';
|
|
10
10
|
export interface RechnungApiOptions {
|
|
11
11
|
/** `api_key` des Kontos (`kr_live_…` / `kr_test_…`). Gehoert auf einen Server. */
|
|
12
12
|
apiKey: string;
|
|
@@ -37,6 +37,8 @@ export interface RechnungApi {
|
|
|
37
37
|
number: string;
|
|
38
38
|
}): Promise<InvoiceDetail>;
|
|
39
39
|
listInvoices(abfrage?: InvoiceListQuery): Promise<InvoicePage>;
|
|
40
|
+
/** Eine spaeter eingetroffene Zahlung nachtragen; `idempotencyKey` ist Pflicht. */
|
|
41
|
+
recordInvoicePayment(anfrage: RecordPaymentRequest): Promise<RecordPaymentResult>;
|
|
40
42
|
/** Mit `language` ungleich der Rechnungssprache: gekennzeichnete Uebersetzungskopie. */
|
|
41
43
|
getInvoicePdf(invoiceId: string, optionen?: {
|
|
42
44
|
language?: InvoiceLanguage;
|
package/dist/esm/rechnung/api.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { createBinaryTransport, createTransport } from '../client/transport.js';
|
|
8
8
|
import { rechnungKeyAuth } from './auth.js';
|
|
9
|
-
import { cancelInvoice, createCreditNote, createCustomer, getCustomer, getInvoice, getInvoicePdf, getInvoiceSetupStatus, getInvoiceXml, issueInvoice, listBrands, listInvoices, searchCustomers, updateCustomer, } from './endpunkte.js';
|
|
9
|
+
import { cancelInvoice, createCreditNote, createCustomer, getCustomer, getInvoice, getInvoicePdf, getInvoiceSetupStatus, getInvoiceXml, issueInvoice, listBrands, listInvoices, recordInvoicePayment, searchCustomers, updateCustomer, } from './endpunkte.js';
|
|
10
10
|
export function createRechnungApi(optionen) {
|
|
11
11
|
const transportOptionen = {
|
|
12
12
|
auth: rechnungKeyAuth({ apiKey: optionen.apiKey }),
|
|
@@ -29,6 +29,7 @@ export function createRechnungApi(optionen) {
|
|
|
29
29
|
getInvoicePdf: (id, o) => getInvoicePdf(rufenBinaer, id, o),
|
|
30
30
|
getInvoiceXml: (id, format) => getInvoiceXml(rufen, id, format),
|
|
31
31
|
getInvoiceSetupStatus: () => getInvoiceSetupStatus(rufen),
|
|
32
|
+
recordInvoicePayment: (anfrage) => recordInvoicePayment(rufen, anfrage),
|
|
32
33
|
listBrands: () => listBrands(rufen),
|
|
33
34
|
};
|
|
34
35
|
}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import type { InternerBinaerTransport, InternerTransport } from '../client/aufrufe.js';
|
|
20
20
|
import type { EInvoiceFormat, InvoiceLanguage } from './vertrag.js';
|
|
21
|
-
import type { Brand, CancelInvoiceRequest, CancelResult, CreditNoteRequest, CreditNoteResult, Customer, CustomerInput, CustomerPage, CustomerSearch, InvoiceDetail, InvoiceListQuery, InvoicePage, InvoiceSetupStatus, IssueInvoiceRequest, IssueResult } from './typen.js';
|
|
21
|
+
import type { Brand, CancelInvoiceRequest, CancelResult, CreditNoteRequest, CreditNoteResult, Customer, CustomerInput, CustomerPage, CustomerSearch, InvoiceDetail, InvoiceListQuery, InvoicePage, InvoiceSetupStatus, IssueInvoiceRequest, IssueResult, RecordPaymentRequest, RecordPaymentResult } from './typen.js';
|
|
22
22
|
export declare function createCustomer(rufen: InternerTransport, customer: CustomerInput, optionen?: {
|
|
23
23
|
idempotencyKey?: string;
|
|
24
24
|
}): Promise<Customer>;
|
|
@@ -53,6 +53,16 @@ export declare function getInvoiceSetupStatus(rufen: InternerTransport): Promise
|
|
|
53
53
|
export declare function getInvoicePdf(rufenBinaer: InternerBinaerTransport, invoiceId: string, optionen?: {
|
|
54
54
|
language?: InvoiceLanguage;
|
|
55
55
|
}): Promise<Uint8Array>;
|
|
56
|
+
/**
|
|
57
|
+
* Eine Zahlung nachtragen, die nach dem Ausstellen eingetroffen ist
|
|
58
|
+
* (Ueberweisung, Teilzahlung). Der `idempotencyKey` ist Pflicht: ohne ihn
|
|
59
|
+
* bucht ein Wiederholungslauf nach einem Zeitlimit eine zweite Zahlung.
|
|
60
|
+
*
|
|
61
|
+
* Bei `method: 'cash'` wird die Zahlung gebucht und die Antwort traegt
|
|
62
|
+
* zusaetzlich `notice` — eine Barzahlung ist ein Barumsatz und braucht einen
|
|
63
|
+
* Beleg (§ 132a BAO), den dieser Vermerk nicht ersetzt.
|
|
64
|
+
*/
|
|
65
|
+
export declare function recordInvoicePayment(rufen: InternerTransport, anfrage: RecordPaymentRequest): Promise<RecordPaymentResult>;
|
|
56
66
|
/** Die Marken des Kontos — die Kennung geht als `brandId` in `issueInvoice`. */
|
|
57
67
|
export declare function listBrands(rufen: InternerTransport): Promise<Brand[]>;
|
|
58
68
|
/**
|
|
@@ -126,6 +126,27 @@ export function getInvoicePdf(rufenBinaer, invoiceId, optionen = {}) {
|
|
|
126
126
|
params['language'] = optionen.language;
|
|
127
127
|
return rufenBinaer('getInvoicePdf', params);
|
|
128
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* Eine Zahlung nachtragen, die nach dem Ausstellen eingetroffen ist
|
|
131
|
+
* (Ueberweisung, Teilzahlung). Der `idempotencyKey` ist Pflicht: ohne ihn
|
|
132
|
+
* bucht ein Wiederholungslauf nach einem Zeitlimit eine zweite Zahlung.
|
|
133
|
+
*
|
|
134
|
+
* Bei `method: 'cash'` wird die Zahlung gebucht und die Antwort traegt
|
|
135
|
+
* zusaetzlich `notice` — eine Barzahlung ist ein Barumsatz und braucht einen
|
|
136
|
+
* Beleg (§ 132a BAO), den dieser Vermerk nicht ersetzt.
|
|
137
|
+
*/
|
|
138
|
+
export async function recordInvoicePayment(rufen, anfrage) {
|
|
139
|
+
const daten = await rufen('recordInvoicePayment', nutzlast(anfrage));
|
|
140
|
+
const roh = objekt(daten);
|
|
141
|
+
const ergebnis = {
|
|
142
|
+
invoice: pflichtObjekt('recordInvoicePayment', daten, 'invoice'),
|
|
143
|
+
payment: pflichtObjekt('recordInvoicePayment', daten, 'payment'),
|
|
144
|
+
replayed: roh['replayed'] === true,
|
|
145
|
+
};
|
|
146
|
+
if (roh['notice'])
|
|
147
|
+
ergebnis.notice = roh['notice'];
|
|
148
|
+
return ergebnis;
|
|
149
|
+
}
|
|
129
150
|
/** Die Marken des Kontos — die Kennung geht als `brandId` in `issueInvoice`. */
|
|
130
151
|
export async function listBrands(rufen) {
|
|
131
152
|
const brands = objekt(await rufen('listBrands', {}))['brands'];
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
export { createRechnungApi, type RechnungApi, type RechnungApiOptions } from './api.js';
|
|
14
14
|
export { rechnungKeyAuth, type RechnungKeyAuthOptions } from './auth.js';
|
|
15
15
|
export { istRechnungFehler, rechnungFehlerCode, rechnungFeldFehler, type RechnungFeldFehler, } from './fehler.js';
|
|
16
|
-
export { cancelInvoice, createCreditNote, createCustomer, getCustomer, getInvoice, getInvoicePdf, getInvoiceSetupStatus, getInvoiceXml, issueInvoice, listBrands, listInvoices, searchCustomers, updateCustomer, } from './endpunkte.js';
|
|
17
|
-
export type { Brand, CancelInvoiceRequest, CancelResult, CreditNoteRequest, CreditNoteResult, Customer, CustomerInput, CustomerPage, CustomerSearch, EInvoiceStatus, Invoice, InvoiceDetail, InvoiceItem, InvoiceItemInput, InvoiceListQuery, InvoicePage, InvoiceRecipient, InvoiceSetupGap, InvoiceSetupStatus, InvoiceTotals, IssueInvoiceRequest, IssueResult, } from './typen.js';
|
|
16
|
+
export { cancelInvoice, createCreditNote, createCustomer, getCustomer, getInvoice, getInvoicePdf, getInvoiceSetupStatus, getInvoiceXml, issueInvoice, listBrands, listInvoices, recordInvoicePayment, searchCustomers, updateCustomer, } from './endpunkte.js';
|
|
17
|
+
export type { Brand, CancelInvoiceRequest, CancelResult, CreditNoteRequest, CreditNoteResult, Customer, CustomerInput, CustomerPage, CustomerSearch, EInvoiceStatus, Invoice, InvoiceDetail, InvoiceItem, InvoiceItemInput, InvoiceListQuery, InvoicePage, InvoiceRecipient, InvoiceSetupGap, InvoiceSetupStatus, InvoiceTotals, InvoiceNotice, InvoicePayment, IssueInvoiceRequest, IssueResult, PaymentInput, RecordPaymentRequest, RecordPaymentResult, } from './typen.js';
|
|
18
18
|
export { RECHNUNG_TEXTE, rechnungText, type RechnungTextSchluessel } from './texte.js';
|
|
19
|
-
export { RECHNUNG_VERTRAG_VERSION, RECHNUNG_AUFRUFE, INVOICE_ERROR_CODES, CREDIT_NOTE_REASONS, TAX_SCHEMES, PRICE_MODES, VAT_RATES, CUSTOMER_TYPES, INVOICE_LIST_STATUS, DOC_TYPES, EINVOICE_FORMATS, INVOICE_LANGUAGES, INVOICE_UNITS, RECHNUNG_EINHEITEN_CODES, INVOICE_SETUP_REQUIREMENTS, KUNDE_FELDER, POSITION_FELDER, RECHNUNG_ANFRAGEN, RECHNUNG_GENAU_EINS, RECHNUNG_MINDESTENS_EINS, type RechnungAufruf, type InvoiceErrorCode, type CreditNoteReason, type TaxScheme, type PriceMode, type VatRatePercent, type CustomerType, type InvoiceListStatus, type DocType, type EInvoiceFormat, type InvoiceLanguage, type InvoiceUnit, type InvoiceSetupRequirement, type Format, type Feld, } from './vertrag.js';
|
|
19
|
+
export { RECHNUNG_VERTRAG_VERSION, RECHNUNG_AUFRUFE, INVOICE_ERROR_CODES, CREDIT_NOTE_REASONS, TAX_SCHEMES, PRICE_MODES, VAT_RATES, CUSTOMER_TYPES, INVOICE_LIST_STATUS, DOC_TYPES, EINVOICE_FORMATS, INVOICE_LANGUAGES, INVOICE_PAYMENT_METHODS, INVOICE_NOTICE_CODES, INVOICE_UNITS, RECHNUNG_EINHEITEN_CODES, INVOICE_SETUP_REQUIREMENTS, KUNDE_FELDER, POSITION_FELDER, RECHNUNG_ANFRAGEN, RECHNUNG_GENAU_EINS, RECHNUNG_MINDESTENS_EINS, type RechnungAufruf, type InvoiceErrorCode, type CreditNoteReason, type TaxScheme, type PriceMode, type VatRatePercent, type CustomerType, type InvoiceListStatus, type DocType, type EInvoiceFormat, type InvoiceLanguage, type InvoicePaymentMethod, type InvoiceNoticeCode, type InvoiceUnit, type InvoiceSetupRequirement, type Format, type Feld, } from './vertrag.js';
|
|
@@ -13,6 +13,6 @@
|
|
|
13
13
|
export { createRechnungApi } from './api.js';
|
|
14
14
|
export { rechnungKeyAuth } from './auth.js';
|
|
15
15
|
export { istRechnungFehler, rechnungFehlerCode, rechnungFeldFehler, } from './fehler.js';
|
|
16
|
-
export { cancelInvoice, createCreditNote, createCustomer, getCustomer, getInvoice, getInvoicePdf, getInvoiceSetupStatus, getInvoiceXml, issueInvoice, listBrands, listInvoices, searchCustomers, updateCustomer, } from './endpunkte.js';
|
|
16
|
+
export { cancelInvoice, createCreditNote, createCustomer, getCustomer, getInvoice, getInvoicePdf, getInvoiceSetupStatus, getInvoiceXml, issueInvoice, listBrands, listInvoices, recordInvoicePayment, searchCustomers, updateCustomer, } from './endpunkte.js';
|
|
17
17
|
export { RECHNUNG_TEXTE, rechnungText } from './texte.js';
|
|
18
|
-
export { RECHNUNG_VERTRAG_VERSION, RECHNUNG_AUFRUFE, INVOICE_ERROR_CODES, CREDIT_NOTE_REASONS, TAX_SCHEMES, PRICE_MODES, VAT_RATES, CUSTOMER_TYPES, INVOICE_LIST_STATUS, DOC_TYPES, EINVOICE_FORMATS, INVOICE_LANGUAGES, INVOICE_UNITS, RECHNUNG_EINHEITEN_CODES, INVOICE_SETUP_REQUIREMENTS, KUNDE_FELDER, POSITION_FELDER, RECHNUNG_ANFRAGEN, RECHNUNG_GENAU_EINS, RECHNUNG_MINDESTENS_EINS, } from './vertrag.js';
|
|
18
|
+
export { RECHNUNG_VERTRAG_VERSION, RECHNUNG_AUFRUFE, INVOICE_ERROR_CODES, CREDIT_NOTE_REASONS, TAX_SCHEMES, PRICE_MODES, VAT_RATES, CUSTOMER_TYPES, INVOICE_LIST_STATUS, DOC_TYPES, EINVOICE_FORMATS, INVOICE_LANGUAGES, INVOICE_PAYMENT_METHODS, INVOICE_NOTICE_CODES, INVOICE_UNITS, RECHNUNG_EINHEITEN_CODES, INVOICE_SETUP_REQUIREMENTS, KUNDE_FELDER, POSITION_FELDER, RECHNUNG_ANFRAGEN, RECHNUNG_GENAU_EINS, RECHNUNG_MINDESTENS_EINS, } from './vertrag.js';
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Betraege sind ueberall ganze Cent. Datumsangaben sind `YYYY-MM-DD` nach
|
|
6
6
|
* Wiener Kalender.
|
|
7
7
|
*/
|
|
8
|
-
import type { CreditNoteReason, CustomerType, DocType, InvoiceLanguage, InvoiceUnit, InvoiceSetupRequirement, InvoiceListStatus, PriceMode, TaxScheme, VatRatePercent } from './vertrag.js';
|
|
8
|
+
import type { CreditNoteReason, CustomerType, DocType, InvoiceLanguage, InvoiceNoticeCode, InvoicePaymentMethod, InvoiceUnit, InvoiceSetupRequirement, InvoiceListStatus, PriceMode, TaxScheme, VatRatePercent } from './vertrag.js';
|
|
9
9
|
export interface CustomerInput {
|
|
10
10
|
type: CustomerType;
|
|
11
11
|
name: string;
|
|
@@ -102,6 +102,49 @@ export interface IssueInvoiceRequest {
|
|
|
102
102
|
language?: InvoiceLanguage;
|
|
103
103
|
/** Marke (Kennung aus `listBrands`); sonst die Standardmarke. Unbekannt = `brand_not_found`. */
|
|
104
104
|
brandId?: string;
|
|
105
|
+
/**
|
|
106
|
+
* Schon bezahlt (Shop kassiert online, Rechnung folgt). Die Zahlung entsteht
|
|
107
|
+
* in derselben Transaktion wie das Festschreiben: das PDF traegt dann keine
|
|
108
|
+
* Zahlungsinformationen und keinen Giro-QR.
|
|
109
|
+
*/
|
|
110
|
+
payment?: PaymentInput;
|
|
111
|
+
}
|
|
112
|
+
/** Eine Zahlung, wie das Fremdsystem sie meldet. */
|
|
113
|
+
export interface PaymentInput {
|
|
114
|
+
method: InvoicePaymentMethod;
|
|
115
|
+
/** Ohne Angabe der volle Bruttobetrag. */
|
|
116
|
+
amountCents?: number;
|
|
117
|
+
/** Ohne Angabe der heutige Wiener Tag; nie in der Zukunft. */
|
|
118
|
+
paidAt?: string;
|
|
119
|
+
/** Zahlungskennung des Fremdsystems — gespeichert, aber nicht gedruckt. */
|
|
120
|
+
reference?: string;
|
|
121
|
+
}
|
|
122
|
+
export interface RecordPaymentRequest extends PaymentInput {
|
|
123
|
+
/** Pflicht: ohne ihn bucht eine Wiederholung eine zweite Zahlung. */
|
|
124
|
+
idempotencyKey: string;
|
|
125
|
+
invoiceId: string;
|
|
126
|
+
}
|
|
127
|
+
/** Eine gebuchte Zahlung, wie die API sie zurueckgibt. */
|
|
128
|
+
export interface InvoicePayment {
|
|
129
|
+
id: string;
|
|
130
|
+
amountCents: number;
|
|
131
|
+
paidAt: string;
|
|
132
|
+
method: InvoicePaymentMethod;
|
|
133
|
+
reference: string | null;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Ein Hinweis zu einer erfolgreichen Antwort — kein Fehler, sondern etwas,
|
|
137
|
+
* das der Aufrufer wissen sollte (heute nur `cash_receipt_required`).
|
|
138
|
+
*/
|
|
139
|
+
export interface InvoiceNotice {
|
|
140
|
+
code: InvoiceNoticeCode;
|
|
141
|
+
message: string;
|
|
142
|
+
}
|
|
143
|
+
export interface RecordPaymentResult {
|
|
144
|
+
invoice: Invoice;
|
|
145
|
+
payment: InvoicePayment;
|
|
146
|
+
replayed: boolean;
|
|
147
|
+
notice?: InvoiceNotice;
|
|
105
148
|
}
|
|
106
149
|
export interface CancelInvoiceRequest {
|
|
107
150
|
idempotencyKey: string;
|
|
@@ -147,6 +190,10 @@ export interface Invoice {
|
|
|
147
190
|
id: string | null;
|
|
148
191
|
name: string | null;
|
|
149
192
|
} | null;
|
|
193
|
+
/** Summe der gebuchten Zahlungen. */
|
|
194
|
+
paidCents: number;
|
|
195
|
+
/** Was noch offen ist; `0` heisst bezahlt. */
|
|
196
|
+
openCents: number;
|
|
150
197
|
}
|
|
151
198
|
/** Eine Marke des Kontos (Logo, Farbe, Absender) — `id` geht als `brandId` in `issueInvoice`. */
|
|
152
199
|
export interface Brand {
|
|
@@ -18,13 +18,13 @@
|
|
|
18
18
|
* Nummer, Summen — ist bewusst **nicht** setzbar.
|
|
19
19
|
*/
|
|
20
20
|
export declare const RECHNUNG_VERTRAG_VERSION = 1;
|
|
21
|
-
export declare const RECHNUNG_AUFRUFE: readonly ["createCustomer", "getCustomer", "updateCustomer", "searchCustomers", "issueInvoice", "cancelInvoice", "createCreditNote", "getInvoice", "listInvoices", "getInvoicePdf", "getInvoiceXml", "getInvoiceSetupStatus", "listBrands"];
|
|
21
|
+
export declare const RECHNUNG_AUFRUFE: readonly ["createCustomer", "getCustomer", "updateCustomer", "searchCustomers", "issueInvoice", "cancelInvoice", "createCreditNote", "getInvoice", "listInvoices", "getInvoicePdf", "getInvoiceXml", "getInvoiceSetupStatus", "listBrands", "recordInvoicePayment"];
|
|
22
22
|
export type RechnungAufruf = (typeof RECHNUNG_AUFRUFE)[number];
|
|
23
23
|
/**
|
|
24
24
|
* Stabile Fehlercodes. Das Fremdsystem verzweigt am Code, der Text darf sich
|
|
25
25
|
* aendern. `validation` traegt zusaetzlich `errors: [{ field, message }]`.
|
|
26
26
|
*/
|
|
27
|
-
export declare const INVOICE_ERROR_CODES: readonly ["validation", "idempotency_conflict", "module_inactive", "customer_not_found", "customer_exists", "short_code_taken", "short_code_immutable", "recipient_required", "invoice_requirements_missing", "invoice_not_found", "invoice_ambiguous", "not_cancellable", "partial_credit_exists", "credit_exceeds_invoice", "einvoice_incomplete", "invoice_api_not_enabled", "invoice_setup_incomplete", "language_not_allowed", "brand_not_found"];
|
|
27
|
+
export declare const INVOICE_ERROR_CODES: readonly ["validation", "idempotency_conflict", "module_inactive", "customer_not_found", "customer_exists", "short_code_taken", "short_code_immutable", "recipient_required", "invoice_requirements_missing", "invoice_not_found", "invoice_ambiguous", "not_cancellable", "partial_credit_exists", "credit_exceeds_invoice", "einvoice_incomplete", "invoice_api_not_enabled", "invoice_setup_incomplete", "language_not_allowed", "brand_not_found", "not_payable", "payment_exceeds_invoice"];
|
|
28
28
|
export type InvoiceErrorCode = (typeof INVOICE_ERROR_CODES)[number];
|
|
29
29
|
/** Gruende einer Gutschrift. Der Server druckt den deutschen Anzeigetext. */
|
|
30
30
|
export declare const CREDIT_NOTE_REASONS: readonly ["cancellation", "price_reduction", "return", "incorrect_invoice", "other"];
|
|
@@ -51,6 +51,20 @@ export type EInvoiceFormat = (typeof EINVOICE_FORMATS)[number];
|
|
|
51
51
|
*/
|
|
52
52
|
export declare const INVOICE_LANGUAGES: readonly ["de", "en"];
|
|
53
53
|
export type InvoiceLanguage = (typeof INVOICE_LANGUAGES)[number];
|
|
54
|
+
/**
|
|
55
|
+
* Wie eine Rechnung bezahlt wurde. Der Vermerk ist Buchhaltung, kein Beleg:
|
|
56
|
+
* `cash` wird gebucht, die Antwort traegt dann zusaetzlich den Hinweis
|
|
57
|
+
* `cash_receipt_required` — eine Barzahlung ist ein Barumsatz und braucht
|
|
58
|
+
* einen Beleg (§ 132a BAO), bei Registrierkassenpflicht ueber die Kasse.
|
|
59
|
+
*/
|
|
60
|
+
export declare const INVOICE_PAYMENT_METHODS: readonly ["transfer", "card", "online", "cash"];
|
|
61
|
+
export type InvoicePaymentMethod = (typeof INVOICE_PAYMENT_METHODS)[number];
|
|
62
|
+
/**
|
|
63
|
+
* Hinweise, die eine erfolgreiche Antwort zusaetzlich tragen kann (`data.notice`).
|
|
64
|
+
* Sie sind keine Fehler: der Aufruf hat gewirkt, es gibt nur etwas zu wissen.
|
|
65
|
+
*/
|
|
66
|
+
export declare const INVOICE_NOTICE_CODES: readonly ["cash_receipt_required"];
|
|
67
|
+
export type InvoiceNoticeCode = (typeof INVOICE_NOTICE_CODES)[number];
|
|
54
68
|
/**
|
|
55
69
|
* Einheiten einer Position. Die API nimmt nur diese Schluessel an; gedruckt
|
|
56
70
|
* wird das Kuerzel in der Sprache der Rechnung (`RECHNUNG_TEXTE`,
|
|
@@ -129,6 +143,14 @@ export type Feld = {
|
|
|
129
143
|
export declare const KUNDE_FELDER: Readonly<Record<string, Feld>>;
|
|
130
144
|
/** Eine Rechnungs- oder Gutschriftsposition. Preise in ganzen Cent. */
|
|
131
145
|
export declare const POSITION_FELDER: Readonly<Record<string, Feld>>;
|
|
146
|
+
/**
|
|
147
|
+
* Eine Zahlung zu einer Rechnung. Ohne `amountCents` gilt der volle
|
|
148
|
+
* Bruttobetrag, ohne `paidAt` der heutige Wiener Tag. `reference` ist die
|
|
149
|
+
* Zahlungskennung des Fremdsystems (z. B. `pi_3Q...`) — sie wird gespeichert,
|
|
150
|
+
* aber **nicht gedruckt**: die Rechnung wird aufbewahrt und vervielfaeltigt,
|
|
151
|
+
* und dem Empfaenger nuetzt sie nichts.
|
|
152
|
+
*/
|
|
153
|
+
export declare const PAYMENT_FELDER: Readonly<Record<string, Feld>>;
|
|
132
154
|
export declare const RECHNUNG_ANFRAGEN: Readonly<Record<RechnungAufruf, Readonly<Record<string, Feld>>>>;
|
|
133
155
|
/** Genau eines dieser Felder muss gesetzt sein (je Aufruf, je Gruppe). */
|
|
134
156
|
export declare const RECHNUNG_GENAU_EINS: Readonly<Partial<Record<RechnungAufruf, readonly (readonly string[])[]>>>;
|