@kreiseck/kasseneck-api 0.27.3 → 0.29.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 +94 -0
- package/README.md +87 -2
- package/dist/cjs/partner/ablauf.d.ts +4 -3
- package/dist/cjs/partner/ablauf.js +4 -3
- package/dist/cjs/partner/api.d.ts +20 -8
- package/dist/cjs/partner/api.js +12 -1
- package/dist/cjs/partner/endpunkte.d.ts +9 -12
- package/dist/cjs/partner/endpunkte.js +85 -26
- package/dist/cjs/partner/fehler.d.ts +28 -2
- package/dist/cjs/partner/fehler.js +58 -9
- package/dist/cjs/partner/index.d.ts +7 -3
- package/dist/cjs/partner/index.js +7 -2
- package/dist/cjs/partner/typen.d.ts +152 -35
- package/dist/cjs/partner/typen.js +4 -0
- package/dist/cjs/partner/webhooks.d.ts +76 -14
- package/dist/cjs/partner/webhooks.js +40 -12
- package/dist/esm/partner/ablauf.d.ts +4 -3
- package/dist/esm/partner/ablauf.js +4 -3
- package/dist/esm/partner/api.d.ts +20 -8
- package/dist/esm/partner/api.js +11 -1
- package/dist/esm/partner/endpunkte.d.ts +9 -12
- package/dist/esm/partner/endpunkte.js +85 -26
- package/dist/esm/partner/fehler.d.ts +28 -2
- package/dist/esm/partner/fehler.js +58 -9
- package/dist/esm/partner/index.d.ts +7 -3
- package/dist/esm/partner/index.js +5 -1
- package/dist/esm/partner/typen.d.ts +152 -35
- package/dist/esm/partner/typen.js +4 -0
- package/dist/esm/partner/webhooks.d.ts +76 -14
- package/dist/esm/partner/webhooks.js +40 -12
- package/fixtures/hobex-hps-codes.json +1 -1
- package/fixtures/kasse-texte.json +1 -1
- package/fixtures/oberflaeche.json +12 -4
- package/fixtures/rechnung-api.schema.json +1 -1
- package/fixtures/rechnung-texte.json +1 -1
- package/package.json +1 -1
|
@@ -26,11 +26,11 @@ const webhook_signatur_js_1 = require("./webhook-signatur.js");
|
|
|
26
26
|
* Alle Ereignisse, die ein Webhook abonnieren **und proben** kann. Ein
|
|
27
27
|
* Endpunkt bekommt ausschliesslich die, die in seiner `events`-Liste stehen.
|
|
28
28
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
29
|
+
* **Noch nicht in der Liste:** `customer.avv_accepted` und
|
|
30
|
+
* `customer.terms_accepted`. Das Backend bietet sie inzwischen zum Abonnieren
|
|
31
|
+
* an; die Liste wird mit dem Dart-Zwilling gemeinsam erweitert, weil beide
|
|
32
|
+
* gegeneinander geprueft werden. Abonnieren geht trotzdem schon (`events`
|
|
33
|
+
* nimmt jeden Namen), die Nutzlast beschreibt [ContractAcceptedEventData].
|
|
34
34
|
*/
|
|
35
35
|
exports.PARTNER_WEBHOOK_EVENTS = [
|
|
36
36
|
'customer.created',
|
|
@@ -112,16 +112,30 @@ async function parseWebhookEvent(optionen) {
|
|
|
112
112
|
function objekt(wert) {
|
|
113
113
|
return wert !== null && typeof wert === 'object' && !Array.isArray(wert) ? wert : {};
|
|
114
114
|
}
|
|
115
|
+
function letzteZustellung(wert) {
|
|
116
|
+
if (wert === null || typeof wert !== 'object' || Array.isArray(wert))
|
|
117
|
+
return null;
|
|
118
|
+
const z = wert;
|
|
119
|
+
return {
|
|
120
|
+
at: typeof z['at'] === 'number' ? z['at'] : null,
|
|
121
|
+
status: typeof z['status'] === 'string' ? z['status'] : '',
|
|
122
|
+
statusCode: typeof z['statusCode'] === 'number' ? z['statusCode'] : null,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
115
125
|
function webhook(eintrag) {
|
|
116
126
|
const w = objekt(eintrag);
|
|
117
127
|
return {
|
|
118
128
|
webhookId: typeof w['webhookId'] === 'string' ? w['webhookId'] : '',
|
|
129
|
+
// Fehlt das Feld, ist es ein Bestands-Webhook: der spricht v1. Kein
|
|
130
|
+
// `v3` aus Kulanz, sonst verzweigt ein Empfaenger auf englische Werte,
|
|
131
|
+
// die nie kommen.
|
|
132
|
+
apiVersion: typeof w['apiVersion'] === 'string' && w['apiVersion'] ? w['apiVersion'] : 'v1',
|
|
119
133
|
url: typeof w['url'] === 'string' ? w['url'] : '',
|
|
120
134
|
events: Array.isArray(w['events']) ? w['events'].filter((e) => typeof e === 'string') : [],
|
|
121
135
|
active: w['active'] !== false,
|
|
122
136
|
description: typeof w['description'] === 'string' ? w['description'] : null,
|
|
123
137
|
createdAt: typeof w['createdAt'] === 'number' ? w['createdAt'] : null,
|
|
124
|
-
lastDelivery:
|
|
138
|
+
lastDelivery: letzteZustellung(w['lastDelivery']),
|
|
125
139
|
consecutiveFailures: typeof w['consecutiveFailures'] === 'number' ? w['consecutiveFailures'] : 0,
|
|
126
140
|
};
|
|
127
141
|
}
|
|
@@ -198,13 +212,19 @@ async function updatePartnerWebhook(rufen, webhookId, patch) {
|
|
|
198
212
|
const daten = objekt(await rufen('updatePartnerWebhook', { webhookId: id, patch }));
|
|
199
213
|
return webhook(daten['webhook']);
|
|
200
214
|
}
|
|
201
|
-
/**
|
|
215
|
+
/**
|
|
216
|
+
* Loescht einen Endpunkt. Danach kommt dort nichts mehr an; offene
|
|
217
|
+
* Zustellungen werden verworfen (`dropped`).
|
|
218
|
+
*/
|
|
202
219
|
async function deletePartnerWebhook(rufen, webhookId) {
|
|
203
220
|
const id = typeof webhookId === 'string' ? webhookId.trim() : '';
|
|
204
221
|
if (!id)
|
|
205
222
|
throw new errors_js_1.KasseneckValidationError('deletePartnerWebhook', 'webhookId fehlt', 'request');
|
|
206
223
|
const daten = objekt(await rufen('deletePartnerWebhook', { webhookId: id }));
|
|
207
|
-
return
|
|
224
|
+
return {
|
|
225
|
+
webhookId: typeof daten['webhookId'] === 'string' ? daten['webhookId'] : id,
|
|
226
|
+
deleted: daten['deleted'] === true,
|
|
227
|
+
};
|
|
208
228
|
}
|
|
209
229
|
/**
|
|
210
230
|
* Schickt eine Probe an genau diesen Endpunkt.
|
|
@@ -234,8 +254,16 @@ async function sendPartnerWebhookTest(rufen, webhookId, event) {
|
|
|
234
254
|
const daten = objekt(await rufen('sendPartnerWebhookTest', { webhookId: id, event: ereignis || undefined }));
|
|
235
255
|
return {
|
|
236
256
|
eventId: typeof daten['eventId'] === 'string' ? daten['eventId'] : '',
|
|
237
|
-
|
|
238
|
-
deliveries: Array.isArray(daten['deliveries']) ? daten['deliveries'] : []
|
|
257
|
+
event: typeof daten['event'] === 'string' ? daten['event'] : ereignis || 'webhook.test',
|
|
258
|
+
deliveries: (Array.isArray(daten['deliveries']) ? daten['deliveries'] : []).map((eintrag) => {
|
|
259
|
+
const z = objekt(eintrag);
|
|
260
|
+
return {
|
|
261
|
+
deliveryId: typeof z['deliveryId'] === 'string' ? z['deliveryId'] : '',
|
|
262
|
+
webhookId: typeof z['webhookId'] === 'string' ? z['webhookId'] : id,
|
|
263
|
+
status: typeof z['status'] === 'string' ? z['status'] : '',
|
|
264
|
+
statusCode: typeof z['statusCode'] === 'number' ? z['statusCode'] : null,
|
|
265
|
+
};
|
|
266
|
+
}),
|
|
239
267
|
};
|
|
240
268
|
}
|
|
241
269
|
/**
|
|
@@ -259,8 +287,8 @@ async function listPartnerWebhookDeliveries(rufen, optionen = {}) {
|
|
|
259
287
|
eventId: txt(z['eventId']) ?? '',
|
|
260
288
|
status: txt(z['status']) ?? '',
|
|
261
289
|
attempts: zahl(z['attempts']) ?? 0,
|
|
262
|
-
|
|
263
|
-
|
|
290
|
+
lastAttemptAt: zahl(z['lastAttemptAt']),
|
|
291
|
+
nextAttemptAt: zahl(z['nextAttemptAt']),
|
|
264
292
|
statusCode: zahl(z['statusCode']),
|
|
265
293
|
response: txt(z['response']),
|
|
266
294
|
createdAt: zahl(z['createdAt']),
|
|
@@ -10,9 +10,10 @@
|
|
|
10
10
|
* Fehler. Hier steht sie vorher — abfragbar, ausgebbar, und in
|
|
11
11
|
* [naechsterSchritt] auch beantwortbar.
|
|
12
12
|
*
|
|
13
|
-
* **
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* **Kein eigener Vertragsschritt.** AVV und Nutzungsvertrag bestaetigt der
|
|
14
|
+
* Betrieb ueber denselben Einrichtungs-Link wie seinen FinanzOnline-Zugang
|
|
15
|
+
* (Schritt `fon`). Live geht ohne beide keine Kasse live
|
|
16
|
+
* (`vertrag_offen`); den Stand zeigen `avv` und `terms` am Betrieb.
|
|
16
17
|
*
|
|
17
18
|
* Zwei Dinge laufen bewusst **parallel**: der Signaturantrag und das Anlegen
|
|
18
19
|
* der Kasse. Eine mit `automatic:true` angelegte Kasse wartet, bis die
|
|
@@ -10,9 +10,10 @@
|
|
|
10
10
|
* Fehler. Hier steht sie vorher — abfragbar, ausgebbar, und in
|
|
11
11
|
* [naechsterSchritt] auch beantwortbar.
|
|
12
12
|
*
|
|
13
|
-
* **
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* **Kein eigener Vertragsschritt.** AVV und Nutzungsvertrag bestaetigt der
|
|
14
|
+
* Betrieb ueber denselben Einrichtungs-Link wie seinen FinanzOnline-Zugang
|
|
15
|
+
* (Schritt `fon`). Live geht ohne beide keine Kasse live
|
|
16
|
+
* (`vertrag_offen`); den Stand zeigen `avv` und `terms` am Betrieb.
|
|
16
17
|
*
|
|
17
18
|
* Zwei Dinge laufen bewusst **parallel**: der Signaturantrag und das Anlegen
|
|
18
19
|
* der Kasse. Eine mit `automatic:true` angelegte Kasse wartet, bis die
|
|
@@ -5,12 +5,27 @@
|
|
|
5
5
|
* Funktionen und bleiben einzeln importierbar.
|
|
6
6
|
*/
|
|
7
7
|
import { type FetchLike } from '../client/transport.js';
|
|
8
|
-
import { type CreateWebhookOptions, type CreateWebhookResult, type PartnerWebhook, type WebhookListe, type PartnerWebhookEventType, type WebhookPatch, type WebhookTestResult, type WebhookZustellung } from './webhooks.js';
|
|
9
|
-
import type { ActivateCashregisterResult, CreateCashregisterOptions, CreateCashregisterResult, CreateCustomerOptions, CreateCustomerResult, CustomerCredentials, FonLinkResult, KassenListe, Kunde, KundenListe, ListCustomersOptions, PartnerInfo, RequestSignatureResult, SignaturStand } from './typen.js';
|
|
8
|
+
import { type CreateWebhookOptions, type CreateWebhookResult, type DeleteWebhookResult, type PartnerWebhook, type WebhookListe, type PartnerWebhookEventType, type WebhookPatch, type WebhookTestResult, type WebhookZustellung } from './webhooks.js';
|
|
9
|
+
import type { ActivateCashregisterResult, CreateCashregisterOptions, CreateCashregisterResult, CreateCustomerOptions, CreateCustomerResult, CustomerCredentials, FonLinkResult, KassenListe, Kunde, KundenListe, ListCustomersOptions, PartnerInfo, RequestSignatureOptions, RequestSignatureResult, SignaturStand } from './typen.js';
|
|
10
|
+
/**
|
|
11
|
+
* Die Basis-URL der Partner-API: `/v3`, die englische Fassung.
|
|
12
|
+
*
|
|
13
|
+
* Nur der Partner-Teil spricht `/v3`. Belege, Rechnungen, Kasse und Zahlungen
|
|
14
|
+
* laufen weiter ueber [DEFAULT_BASE_URL] (`/v1`), bis es fuer sie eine `/v3`
|
|
15
|
+
* gibt. Die Partner-Endpunkte unter `/v1` antworten weiter, deutsch und
|
|
16
|
+
* abgekuendigt (Kopfzeilen `Deprecation`/`Sunset`); dieser Client spricht sie
|
|
17
|
+
* nicht mehr.
|
|
18
|
+
*/
|
|
19
|
+
export declare const PARTNER_BASE_URL = "https://api.kasseneck.at/v3";
|
|
10
20
|
export interface PartnerApiOptions {
|
|
11
21
|
/** Partner-Schluessel `pk_test_…` / `pk_live_…`. Gehoert auf einen Server. */
|
|
12
22
|
partnerKey: string;
|
|
13
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* Abweichende Basis-URL; Vorgabe [PARTNER_BASE_URL]
|
|
25
|
+
* (`https://api.kasseneck.at/v3`). Die Antworten werden in der Form der
|
|
26
|
+
* `/v3` gelesen: eine `/v1`-Adresse hier liefert deutsche Werte, die diese
|
|
27
|
+
* Typen nicht beschreiben.
|
|
28
|
+
*/
|
|
14
29
|
baseUrl?: string;
|
|
15
30
|
/** Zeitlimit je Aufruf in Millisekunden. */
|
|
16
31
|
timeoutMs?: number;
|
|
@@ -23,10 +38,7 @@ export interface PartnerApi {
|
|
|
23
38
|
listPartnerCustomers(optionen?: ListCustomersOptions): Promise<KundenListe>;
|
|
24
39
|
getPartnerCustomer(customerId: string): Promise<Kunde>;
|
|
25
40
|
sendPartnerCustomerFonLink(customerId: string): Promise<FonLinkResult>;
|
|
26
|
-
requestCustomerSignature(customerId: string, optionen?:
|
|
27
|
-
art?: string;
|
|
28
|
-
additional?: boolean;
|
|
29
|
-
}): Promise<RequestSignatureResult>;
|
|
41
|
+
requestCustomerSignature(customerId: string, optionen?: RequestSignatureOptions): Promise<RequestSignatureResult>;
|
|
30
42
|
getCustomerSignatureStatus(customerId: string): Promise<SignaturStand>;
|
|
31
43
|
createCustomerCashregister(optionen: CreateCashregisterOptions): Promise<CreateCashregisterResult>;
|
|
32
44
|
activateCashregister(customerId: string, cashregisterId: string): Promise<ActivateCashregisterResult>;
|
|
@@ -42,7 +54,7 @@ export interface PartnerApi {
|
|
|
42
54
|
createPartnerWebhook(optionen: CreateWebhookOptions): Promise<CreateWebhookResult>;
|
|
43
55
|
listPartnerWebhooks(): Promise<WebhookListe>;
|
|
44
56
|
updatePartnerWebhook(webhookId: string, patch: WebhookPatch): Promise<PartnerWebhook>;
|
|
45
|
-
deletePartnerWebhook(webhookId: string): Promise<
|
|
57
|
+
deletePartnerWebhook(webhookId: string): Promise<DeleteWebhookResult>;
|
|
46
58
|
/**
|
|
47
59
|
* Neues Secret fuer denselben Endpunkt — dieselbe `webhookId`, dieselben
|
|
48
60
|
* Ereignisse. Das alte gilt ab der Antwort nicht mehr.
|
package/dist/esm/partner/api.js
CHANGED
|
@@ -9,10 +9,20 @@ import { partnerKeyAuth } from './auth.js';
|
|
|
9
9
|
import { partnerFehlerRat } from './fehler.js';
|
|
10
10
|
import { activateCashregister, createCustomerCashregister, createPartnerCustomer, getCustomerCredentials, getCustomerSignatureStatus, getPartnerCustomer, getPartnerInfo, checkPartnerCustomerEmail, listCustomerCashregisters, listPartnerCustomers, requestCustomerSignature, sendPartnerCustomerFonLink, } from './endpunkte.js';
|
|
11
11
|
import { createPartnerWebhook, deletePartnerWebhook, listPartnerWebhookDeliveries, listPartnerWebhooks, rotatePartnerWebhookSecret, sendPartnerWebhookTest, updatePartnerWebhook, } from './webhooks.js';
|
|
12
|
+
/**
|
|
13
|
+
* Die Basis-URL der Partner-API: `/v3`, die englische Fassung.
|
|
14
|
+
*
|
|
15
|
+
* Nur der Partner-Teil spricht `/v3`. Belege, Rechnungen, Kasse und Zahlungen
|
|
16
|
+
* laufen weiter ueber [DEFAULT_BASE_URL] (`/v1`), bis es fuer sie eine `/v3`
|
|
17
|
+
* gibt. Die Partner-Endpunkte unter `/v1` antworten weiter, deutsch und
|
|
18
|
+
* abgekuendigt (Kopfzeilen `Deprecation`/`Sunset`); dieser Client spricht sie
|
|
19
|
+
* nicht mehr.
|
|
20
|
+
*/
|
|
21
|
+
export const PARTNER_BASE_URL = 'https://api.kasseneck.at/v3';
|
|
12
22
|
export function createPartnerApi(optionen) {
|
|
13
23
|
const rufen = createTransport({
|
|
14
24
|
auth: partnerKeyAuth({ partnerKey: optionen.partnerKey }),
|
|
15
|
-
baseUrl: optionen.baseUrl,
|
|
25
|
+
baseUrl: optionen.baseUrl ?? PARTNER_BASE_URL,
|
|
16
26
|
timeoutMs: optionen.timeoutMs,
|
|
17
27
|
fetch: optionen.fetch,
|
|
18
28
|
});
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* einen `TypeError` an unpassender Stelle.
|
|
20
20
|
*/
|
|
21
21
|
import type { InternerTransport } from '../client/aufrufe.js';
|
|
22
|
-
import type { ActivateCashregisterResult, CreateCashregisterOptions, CreateCashregisterResult, CreateCustomerOptions, CreateCustomerResult, CustomerCredentials, FonLinkResult, KassenListe, Kunde, KundenListe, ListCustomersOptions, PartnerInfo, RequestSignatureResult, SignaturStand } from './typen.js';
|
|
22
|
+
import type { ActivateCashregisterResult, CreateCashregisterOptions, CreateCashregisterResult, CreateCustomerOptions, CreateCustomerResult, CustomerCredentials, FonLinkResult, KassenListe, Kunde, KundenListe, ListCustomersOptions, PartnerInfo, RequestSignatureOptions, RequestSignatureResult, SignaturStand } from './typen.js';
|
|
23
23
|
/**
|
|
24
24
|
* Wer bin ich, in welcher Umgebung, mit welchen Rechten — und welche Apps
|
|
25
25
|
* gehoeren mir. `apps[].id` ist die `appId` fuer [createPartnerCustomer].
|
|
@@ -76,8 +76,8 @@ export declare function sendPartnerCustomerFonLink(rufen: InternerTransport, cus
|
|
|
76
76
|
* Vertrauensdiensteanbieter **auf diesen Betrieb** ausstellen und meldet sie
|
|
77
77
|
* bei FinanzOnline an; einen Vorrat fertiger Karten gibt es nicht.
|
|
78
78
|
*
|
|
79
|
-
* Der Antrag erzeugt sofort ein Signatur-OBJEKT: `
|
|
80
|
-
* zugleich die `
|
|
79
|
+
* Der Antrag erzeugt sofort ein Signatur-OBJEKT: `request.requestId` ist
|
|
80
|
+
* zugleich die `signatureRequestId`, auf die sich eine Kasse beruft — auch solange
|
|
81
81
|
* noch keine Karte zugewiesen ist.
|
|
82
82
|
*
|
|
83
83
|
* **Je Betrieb laeuft nur ein Antrag.** Ein zweiter Aufruf liefert den
|
|
@@ -87,23 +87,20 @@ export declare function sendPartnerCustomerFonLink(rufen: InternerTransport, cus
|
|
|
87
87
|
* Abschluss kommt als Ereignis `signature.ready`, nicht als Antwort auf diesen
|
|
88
88
|
* Aufruf.
|
|
89
89
|
*/
|
|
90
|
-
export declare function requestCustomerSignature(rufen: InternerTransport, customerId: string, optionen?:
|
|
91
|
-
|
|
92
|
-
additional?: boolean;
|
|
93
|
-
}): Promise<RequestSignatureResult>;
|
|
94
|
-
/** Stand der Signatur eines Betriebs samt aller Antraege und des FON-Zugangs. */
|
|
90
|
+
export declare function requestCustomerSignature(rufen: InternerTransport, customerId: string, optionen?: RequestSignatureOptions): Promise<RequestSignatureResult>;
|
|
91
|
+
/** Stand der Signatur eines Betriebs samt aller Signaturen, Antraege und des FON-Zugangs. */
|
|
95
92
|
export declare function getCustomerSignatureStatus(rufen: InternerTransport, customerId: string): Promise<SignaturStand>;
|
|
96
93
|
/**
|
|
97
94
|
* Legt eine Kasse an.
|
|
98
95
|
*
|
|
99
96
|
* **Jede Kasse bezieht sich auf eine Signatur.** Ohne eine einzige — auch eine
|
|
100
97
|
* noch laufende zaehlt — entsteht keine (`signature_missing`); bei mehreren
|
|
101
|
-
* muss `
|
|
98
|
+
* muss `signatureRequestId` dastehen (`signature_ambiguous`).
|
|
102
99
|
*
|
|
103
100
|
* **Darf vor der fertigen Signatur aufgerufen werden:** die Kasse bleibt dann
|
|
104
|
-
* auf `
|
|
105
|
-
* (`automatic:true`, Vorgabe). `
|
|
106
|
-
* nichts lief: `signature_not_ready` oder `
|
|
101
|
+
* auf `draft` und geht von selbst live, sobald IHRE Signatur bereit ist
|
|
102
|
+
* (`automatic:true`, Vorgabe). `activation.reason` sagt, warum gerade
|
|
103
|
+
* nichts lief: `signature_not_ready` oder `automation_off`.
|
|
107
104
|
*
|
|
108
105
|
* Hoechstens 20 Kassen je Betrieb (`cashregister_limit`); ohne gebuchtes Modul
|
|
109
106
|
* `module_inactive`.
|
|
@@ -45,6 +45,19 @@ function zahlOderNull(wert) {
|
|
|
45
45
|
function jaNein(wert, rueckfall = false) {
|
|
46
46
|
return typeof wert === 'boolean' ? wert : rueckfall;
|
|
47
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Das gebuchte Entgelt (`fee`), falls die Antwort eines fuehrt. Ohne Betrag
|
|
50
|
+
* ist es keines: ein erfundenes `0` saehe aus wie ein kostenloser Posten.
|
|
51
|
+
*/
|
|
52
|
+
function entgelt(wert) {
|
|
53
|
+
if (wert === null || typeof wert !== 'object' || Array.isArray(wert))
|
|
54
|
+
return null;
|
|
55
|
+
const f = wert;
|
|
56
|
+
const cents = zahlOderNull(f['cents']);
|
|
57
|
+
if (cents === null)
|
|
58
|
+
return null;
|
|
59
|
+
return { cents, interval: text(f['interval']), test: jaNein(f['test']) };
|
|
60
|
+
}
|
|
48
61
|
/**
|
|
49
62
|
* Verlangt ein Feld der Antwort. Der Fehler nennt das Feld und den Vorgang,
|
|
50
63
|
* damit ein Aufrufer nicht raten muss, welcher der Aufrufe etwas anderes
|
|
@@ -158,6 +171,7 @@ export async function createPartnerCustomer(rufen, optionen) {
|
|
|
158
171
|
appId: text(daten['appId'], appId),
|
|
159
172
|
access: { invited: jaNein(zugang['invited']), sentTo: textOderNull(zugang['sentTo']) },
|
|
160
173
|
nextSteps: liste(daten['nextSteps']).filter((s) => typeof s === 'string'),
|
|
174
|
+
fee: entgelt(daten['fee']),
|
|
161
175
|
replayed: jaNein(daten['replayed']),
|
|
162
176
|
};
|
|
163
177
|
}
|
|
@@ -186,26 +200,38 @@ function kundenZeile(eintrag) {
|
|
|
186
200
|
appId: textOderNull(k['appId']),
|
|
187
201
|
env: text(k['env']) === 'test' ? 'test' : 'live',
|
|
188
202
|
createdAt: zahlOderNull(k['createdAt']),
|
|
203
|
+
fon: fonStand(k['fon']),
|
|
189
204
|
avv: avvStand(k['avv']),
|
|
205
|
+
terms: vertragStand(k['terms']),
|
|
190
206
|
};
|
|
191
207
|
}
|
|
192
|
-
|
|
193
|
-
* Der Vertragsstand, **falls** die Antwort ihn ueberhaupt fuehrt — heute tut
|
|
194
|
-
* sie das nicht, dann bleibt es bei `null`. Kein erfundenes `offen`: „nicht
|
|
195
|
-
* mitgeliefert" und „nicht bestaetigt" duerfen fuer einen Aufrufer nicht
|
|
196
|
-
* dasselbe sein.
|
|
197
|
-
*/
|
|
198
|
-
function avvStand(wert) {
|
|
208
|
+
function fonStand(wert) {
|
|
199
209
|
if (wert === null || typeof wert !== 'object' || Array.isArray(wert))
|
|
200
210
|
return null;
|
|
201
|
-
const
|
|
211
|
+
const f = wert;
|
|
202
212
|
return {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
mode: textOderNull(a['mode']),
|
|
213
|
+
configured: jaNein(f['configured']),
|
|
214
|
+
linkSentAt: zahlOderNull(f['linkSentAt']),
|
|
215
|
+
linkOpenedAt: zahlOderNull(f['linkOpenedAt']),
|
|
207
216
|
};
|
|
208
217
|
}
|
|
218
|
+
function vertragStand(wert) {
|
|
219
|
+
if (wert === null || typeof wert !== 'object' || Array.isArray(wert))
|
|
220
|
+
return null;
|
|
221
|
+
const v = wert;
|
|
222
|
+
return { status: text(v['status']), version: textOderNull(v['version']), confirmedAt: zahlOderNull(v['confirmedAt']) };
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Der AVV-Stand, **falls** die Antwort ihn fuehrt; sonst `null`. Kein
|
|
226
|
+
* erfundenes `pending`: „nicht mitgeliefert" und „nicht bestaetigt" duerfen
|
|
227
|
+
* fuer einen Aufrufer nicht dasselbe sein.
|
|
228
|
+
*/
|
|
229
|
+
function avvStand(wert) {
|
|
230
|
+
const v = vertragStand(wert);
|
|
231
|
+
if (!v)
|
|
232
|
+
return null;
|
|
233
|
+
return { ...v, mode: textOderNull(wert['mode']) };
|
|
234
|
+
}
|
|
209
235
|
/** Ein Betrieb mit allem, was der Partner ueber ihn sehen darf — nie Geheimnisse. */
|
|
210
236
|
export async function getPartnerCustomer(rufen, customerId) {
|
|
211
237
|
const id = pflicht(customerId, 'getPartnerCustomer', 'customerId');
|
|
@@ -220,7 +246,13 @@ export async function getPartnerCustomer(rufen, customerId) {
|
|
|
220
246
|
createdAt: zahlOderNull(k['createdAt']),
|
|
221
247
|
createdVia: textOderNull(k['createdVia']),
|
|
222
248
|
business: objekt(k['business']),
|
|
223
|
-
fon: {
|
|
249
|
+
fon: {
|
|
250
|
+
configured: jaNein(fon['configured']),
|
|
251
|
+
verifiedAt: zahlOderNull(fon['verifiedAt']),
|
|
252
|
+
linkSentAt: zahlOderNull(fon['linkSentAt']),
|
|
253
|
+
linkSentTo: textOderNull(fon['linkSentTo']),
|
|
254
|
+
linkOpenedAt: zahlOderNull(fon['linkOpenedAt']),
|
|
255
|
+
},
|
|
224
256
|
access: zugang === null || typeof zugang !== 'object'
|
|
225
257
|
? null
|
|
226
258
|
: {
|
|
@@ -274,7 +306,7 @@ function antrag(eintrag) {
|
|
|
274
306
|
requestId: text(a['requestId']),
|
|
275
307
|
status: text(a['status']),
|
|
276
308
|
statusText: text(a['statusText']),
|
|
277
|
-
|
|
309
|
+
kind: text(a['kind'], 'signature_card'),
|
|
278
310
|
vdaId: textOderNull(a['vdaId']),
|
|
279
311
|
signatureId: textOderNull(a['signatureId']),
|
|
280
312
|
error: fehler === null || typeof fehler !== 'object'
|
|
@@ -290,8 +322,8 @@ function antrag(eintrag) {
|
|
|
290
322
|
history: liste(a['history']).map((h) => {
|
|
291
323
|
const e = objekt(h);
|
|
292
324
|
return {
|
|
293
|
-
|
|
294
|
-
|
|
325
|
+
from: textOderNull(e['from']),
|
|
326
|
+
to: text(e['to']),
|
|
295
327
|
at: zahlOderNull(e['at']) ?? 0,
|
|
296
328
|
reason: textOderNull(e['reason']),
|
|
297
329
|
};
|
|
@@ -303,8 +335,8 @@ function antrag(eintrag) {
|
|
|
303
335
|
* Vertrauensdiensteanbieter **auf diesen Betrieb** ausstellen und meldet sie
|
|
304
336
|
* bei FinanzOnline an; einen Vorrat fertiger Karten gibt es nicht.
|
|
305
337
|
*
|
|
306
|
-
* Der Antrag erzeugt sofort ein Signatur-OBJEKT: `
|
|
307
|
-
* zugleich die `
|
|
338
|
+
* Der Antrag erzeugt sofort ein Signatur-OBJEKT: `request.requestId` ist
|
|
339
|
+
* zugleich die `signatureRequestId`, auf die sich eine Kasse beruft — auch solange
|
|
308
340
|
* noch keine Karte zugewiesen ist.
|
|
309
341
|
*
|
|
310
342
|
* **Je Betrieb laeuft nur ein Antrag.** Ein zweiter Aufruf liefert den
|
|
@@ -318,27 +350,54 @@ export async function requestCustomerSignature(rufen, customerId, optionen = {})
|
|
|
318
350
|
const id = pflicht(customerId, 'requestCustomerSignature', 'customerId');
|
|
319
351
|
const daten = objekt(await rufen('requestCustomerSignature', {
|
|
320
352
|
customerId: id,
|
|
321
|
-
|
|
353
|
+
kind: optionen.kind,
|
|
322
354
|
additional: optionen.additional,
|
|
323
355
|
}));
|
|
324
356
|
return {
|
|
325
357
|
request: antrag(verlangt(daten['request'], 'requestCustomerSignature', 'request')),
|
|
326
358
|
replayed: jaNein(daten['replayed']),
|
|
327
359
|
note: textOderNull(daten['note']),
|
|
360
|
+
fee: entgelt(daten['fee']),
|
|
328
361
|
};
|
|
329
362
|
}
|
|
330
|
-
|
|
363
|
+
function signaturEinzeln(eintrag) {
|
|
364
|
+
const s = objekt(eintrag);
|
|
365
|
+
const fehler = s['error'];
|
|
366
|
+
return {
|
|
367
|
+
signatureRequestId: text(s['signatureRequestId']),
|
|
368
|
+
status: text(s['status']),
|
|
369
|
+
statusText: text(s['statusText']),
|
|
370
|
+
inProgress: jaNein(s['inProgress']),
|
|
371
|
+
ready: jaNein(s['ready']),
|
|
372
|
+
kind: text(s['kind'], 'signature_card'),
|
|
373
|
+
vdaId: textOderNull(s['vdaId']),
|
|
374
|
+
requestId: textOderNull(s['requestId']),
|
|
375
|
+
signatureId: textOderNull(s['signatureId']),
|
|
376
|
+
error: fehler === null || typeof fehler !== 'object'
|
|
377
|
+
? null
|
|
378
|
+
: {
|
|
379
|
+
code: textOderNull(objekt(fehler)['code']),
|
|
380
|
+
message: textOderNull(objekt(fehler)['message']),
|
|
381
|
+
rc: textOderNull(objekt(fehler)['rc']),
|
|
382
|
+
},
|
|
383
|
+
createdAt: zahlOderNull(s['createdAt']),
|
|
384
|
+
updatedAt: zahlOderNull(s['updatedAt']),
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
/** Stand der Signatur eines Betriebs samt aller Signaturen, Antraege und des FON-Zugangs. */
|
|
331
388
|
export async function getCustomerSignatureStatus(rufen, customerId) {
|
|
332
389
|
const id = pflicht(customerId, 'getCustomerSignatureStatus', 'customerId');
|
|
333
390
|
const daten = objekt(await rufen('getCustomerSignatureStatus', { customerId: id }));
|
|
334
|
-
const signatur = objekt(daten['
|
|
391
|
+
const signatur = objekt(daten['signature']);
|
|
335
392
|
const fon = objekt(daten['fon']);
|
|
336
393
|
return {
|
|
337
|
-
|
|
394
|
+
customerId: text(daten['customerId'], id),
|
|
395
|
+
signature: {
|
|
338
396
|
ready: jaNein(signatur['ready']),
|
|
339
397
|
signatureId: textOderNull(signatur['signatureId']),
|
|
340
398
|
vdaId: textOderNull(signatur['vdaId']),
|
|
341
399
|
},
|
|
400
|
+
signatures: liste(daten['signatures']).map(signaturEinzeln),
|
|
342
401
|
requests: liste(daten['requests']).map(antrag),
|
|
343
402
|
fon: { present: jaNein(fon['present']), verifiedAt: zahlOderNull(fon['verifiedAt']) },
|
|
344
403
|
};
|
|
@@ -378,12 +437,12 @@ function kasse(eintrag) {
|
|
|
378
437
|
*
|
|
379
438
|
* **Jede Kasse bezieht sich auf eine Signatur.** Ohne eine einzige — auch eine
|
|
380
439
|
* noch laufende zaehlt — entsteht keine (`signature_missing`); bei mehreren
|
|
381
|
-
* muss `
|
|
440
|
+
* muss `signatureRequestId` dastehen (`signature_ambiguous`).
|
|
382
441
|
*
|
|
383
442
|
* **Darf vor der fertigen Signatur aufgerufen werden:** die Kasse bleibt dann
|
|
384
|
-
* auf `
|
|
385
|
-
* (`automatic:true`, Vorgabe). `
|
|
386
|
-
* nichts lief: `signature_not_ready` oder `
|
|
443
|
+
* auf `draft` und geht von selbst live, sobald IHRE Signatur bereit ist
|
|
444
|
+
* (`automatic:true`, Vorgabe). `activation.reason` sagt, warum gerade
|
|
445
|
+
* nichts lief: `signature_not_ready` oder `automation_off`.
|
|
387
446
|
*
|
|
388
447
|
* Hoechstens 20 Kassen je Betrieb (`cashregister_limit`); ohne gebuchtes Modul
|
|
389
448
|
* `module_inactive`.
|
|
@@ -19,6 +19,32 @@
|
|
|
19
19
|
* unterscheiden. Deshalb stehen hier BEIDE Flaechen: die der Schnittstelle
|
|
20
20
|
* ([PARTNER_FEHLER_CODES]) und die des Partner-Portals
|
|
21
21
|
* ([PARTNER_PORTAL_FEHLER_CODES]).
|
|
22
|
+
*
|
|
23
|
+
* **Seit 0.29.0 englisch, wie der Rest von `/v3`.** Dieser Client spricht seit
|
|
24
|
+
* 0.28.0 ausschliesslich `/v3` (`PARTNER_BASE_URL`): die paar deutschen Codes,
|
|
25
|
+
* die der Server bis dahin noch roh durchreichte, kommen jetzt genauso englisch
|
|
26
|
+
* an wie alle anderen. [PARTNER_FEHLER_CODES] fuehrt deshalb ausnahmslos die
|
|
27
|
+
* `/v3`-Schreibweise aus `fehlercodes.json`s `v3`-Zuordnung (deutsch -> englisch);
|
|
28
|
+
* ein Aufrufer bekommt vom Server nie mehr die deutsche Form.
|
|
29
|
+
*
|
|
30
|
+
* **`kein_partnerbetrieb` und `request_not_found` fehlen absichtlich.** Beide
|
|
31
|
+
* sind admin-only (`partner-endpoints.js`, ausserhalb von `FEHLER_KATALOG`) und
|
|
32
|
+
* erreichen `/v3` nie: ein Partner-Aufruf kann sie unter keinem Pfad bekommen.
|
|
33
|
+
* Sie standen frueher versehentlich in dieser Liste; `dart-partner.json` (ein
|
|
34
|
+
* eingefrorener Abzug aus Dart 5.3.0, bevor das korrigiert wurde) fuehrt sie
|
|
35
|
+
* weiterhin, siehe die Ausnahme in `test/partner-enums.test.ts`.
|
|
36
|
+
*
|
|
37
|
+
* **Die Vertrags-Codes (`kind_not_allowed`, `mode_not_allowed`,
|
|
38
|
+
* `power_of_attorney_missing`, `not_found`, `no_version`,
|
|
39
|
+
* `unknown_version`, `text_changed`, `already_accepted`) stehen hier, obwohl
|
|
40
|
+
* dieses Paket `reportCustomerContract` nicht anbietet.** Der Katalog des
|
|
41
|
+
* Backends fuehrt sie mit `flaeche: 'api'`/`'beide'`, dieselbe Regel wie bei
|
|
42
|
+
* den Portal-Codes oben: vollstaendig heisst vollstaendig, auch fuer einen
|
|
43
|
+
* Endpunkt, den (noch) kein Aufruf dieses Clients ausloest. Ein Server-Update,
|
|
44
|
+
* das den Endpunkt ergaenzt, bräuchte dann keinen zweiten Fehlerkatalog-Umbau.
|
|
45
|
+
* `not_required` fehlt bewusst: derselbe gemeinsame Server-Zweig wie die
|
|
46
|
+
* anderen sechs, aber ueber die Partner-API nicht erreichbar (der Server hat
|
|
47
|
+
* ihn aus `FEHLER_KATALOG` entfernt, siehe `partner-core.js` im Backend).
|
|
22
48
|
*/
|
|
23
49
|
/**
|
|
24
50
|
* Alle Codes, die die **Schnittstelle** kennt. Als Liste und nicht nur als
|
|
@@ -27,7 +53,7 @@
|
|
|
27
53
|
*
|
|
28
54
|
* Reihenfolge und Bestand wie im Abzug des Backends.
|
|
29
55
|
*/
|
|
30
|
-
export declare const PARTNER_FEHLER_CODES: readonly ["validation", "rate_limited", "app_not_found", "app_not_accepted", "
|
|
56
|
+
export declare const PARTNER_FEHLER_CODES: readonly ["validation", "rate_limited", "app_not_found", "app_not_accepted", "live_not_allowed", "customer_exists", "customer_conflict", "customer_limit", "access_not_allowed", "email_taken", "no_email", "tax_number_missing", "fon_missing", "signature_pending", "signature_missing", "signature_unknown", "signature_ambiguous", "signature_not_ready", "signature_limit", "signature_failed", "module_inactive", "cashregister_limit", "cashregister_not_found", "contracts_pending", "kind_not_allowed", "mode_not_allowed", "power_of_attorney_missing", "not_found", "no_version", "unknown_version", "text_changed", "already_accepted", "activation_failed", "webhook_limit", "webhook_inactive", "event_not_subscribed"];
|
|
31
57
|
/**
|
|
32
58
|
* Die Codes, die nur im **Partner-Portal** entstehen — beim Pflegen der App,
|
|
33
59
|
* der Schluessel, der Mitglieder und der Signaturkarten.
|
|
@@ -58,7 +84,7 @@ export declare function istPartnerFehler(error: unknown, code: PartnerCode): boo
|
|
|
58
84
|
export interface PartnerFeldFehler {
|
|
59
85
|
/**
|
|
60
86
|
* Der Feldpfad, so wie er im gesendeten Betrieb steht — verschachtelt und je
|
|
61
|
-
* Kontakt: `address.
|
|
87
|
+
* Kontakt: `address.zip`, `taxDetails.taxNumber`, `contacts.0.email`.
|
|
62
88
|
*/
|
|
63
89
|
field: string;
|
|
64
90
|
message: string;
|
|
@@ -19,6 +19,32 @@
|
|
|
19
19
|
* unterscheiden. Deshalb stehen hier BEIDE Flaechen: die der Schnittstelle
|
|
20
20
|
* ([PARTNER_FEHLER_CODES]) und die des Partner-Portals
|
|
21
21
|
* ([PARTNER_PORTAL_FEHLER_CODES]).
|
|
22
|
+
*
|
|
23
|
+
* **Seit 0.29.0 englisch, wie der Rest von `/v3`.** Dieser Client spricht seit
|
|
24
|
+
* 0.28.0 ausschliesslich `/v3` (`PARTNER_BASE_URL`): die paar deutschen Codes,
|
|
25
|
+
* die der Server bis dahin noch roh durchreichte, kommen jetzt genauso englisch
|
|
26
|
+
* an wie alle anderen. [PARTNER_FEHLER_CODES] fuehrt deshalb ausnahmslos die
|
|
27
|
+
* `/v3`-Schreibweise aus `fehlercodes.json`s `v3`-Zuordnung (deutsch -> englisch);
|
|
28
|
+
* ein Aufrufer bekommt vom Server nie mehr die deutsche Form.
|
|
29
|
+
*
|
|
30
|
+
* **`kein_partnerbetrieb` und `request_not_found` fehlen absichtlich.** Beide
|
|
31
|
+
* sind admin-only (`partner-endpoints.js`, ausserhalb von `FEHLER_KATALOG`) und
|
|
32
|
+
* erreichen `/v3` nie: ein Partner-Aufruf kann sie unter keinem Pfad bekommen.
|
|
33
|
+
* Sie standen frueher versehentlich in dieser Liste; `dart-partner.json` (ein
|
|
34
|
+
* eingefrorener Abzug aus Dart 5.3.0, bevor das korrigiert wurde) fuehrt sie
|
|
35
|
+
* weiterhin, siehe die Ausnahme in `test/partner-enums.test.ts`.
|
|
36
|
+
*
|
|
37
|
+
* **Die Vertrags-Codes (`kind_not_allowed`, `mode_not_allowed`,
|
|
38
|
+
* `power_of_attorney_missing`, `not_found`, `no_version`,
|
|
39
|
+
* `unknown_version`, `text_changed`, `already_accepted`) stehen hier, obwohl
|
|
40
|
+
* dieses Paket `reportCustomerContract` nicht anbietet.** Der Katalog des
|
|
41
|
+
* Backends fuehrt sie mit `flaeche: 'api'`/`'beide'`, dieselbe Regel wie bei
|
|
42
|
+
* den Portal-Codes oben: vollstaendig heisst vollstaendig, auch fuer einen
|
|
43
|
+
* Endpunkt, den (noch) kein Aufruf dieses Clients ausloest. Ein Server-Update,
|
|
44
|
+
* das den Endpunkt ergaenzt, bräuchte dann keinen zweiten Fehlerkatalog-Umbau.
|
|
45
|
+
* `not_required` fehlt bewusst: derselbe gemeinsame Server-Zweig wie die
|
|
46
|
+
* anderen sechs, aber ueber die Partner-API nicht erreichbar (der Server hat
|
|
47
|
+
* ihn aus `FEHLER_KATALOG` entfernt, siehe `partner-core.js` im Backend).
|
|
22
48
|
*/
|
|
23
49
|
import { KasseneckApiError } from '../client/errors.js';
|
|
24
50
|
/**
|
|
@@ -34,19 +60,19 @@ export const PARTNER_FEHLER_CODES = [
|
|
|
34
60
|
'rate_limited',
|
|
35
61
|
'app_not_found',
|
|
36
62
|
'app_not_accepted',
|
|
37
|
-
'kein_partnerbetrieb',
|
|
38
63
|
'live_not_allowed',
|
|
39
64
|
// Betrieb anlegen
|
|
40
65
|
'customer_exists',
|
|
41
66
|
'customer_conflict',
|
|
42
67
|
'customer_limit',
|
|
43
|
-
'
|
|
68
|
+
'access_not_allowed',
|
|
44
69
|
'email_taken',
|
|
45
70
|
'no_email',
|
|
71
|
+
// FinanzOnline-Link
|
|
72
|
+
'tax_number_missing',
|
|
46
73
|
// Signatur
|
|
47
74
|
'fon_missing',
|
|
48
75
|
'signature_pending',
|
|
49
|
-
'request_not_found',
|
|
50
76
|
'signature_missing',
|
|
51
77
|
'signature_unknown',
|
|
52
78
|
'signature_ambiguous',
|
|
@@ -57,6 +83,17 @@ export const PARTNER_FEHLER_CODES = [
|
|
|
57
83
|
'module_inactive',
|
|
58
84
|
'cashregister_limit',
|
|
59
85
|
'cashregister_not_found',
|
|
86
|
+
'contracts_pending',
|
|
87
|
+
// Vertraege (reportCustomerContract: dieses Paket bietet den Endpunkt nicht
|
|
88
|
+
// an, der Katalog fuehrt die Codes trotzdem vollstaendig, siehe oben)
|
|
89
|
+
'kind_not_allowed',
|
|
90
|
+
'mode_not_allowed',
|
|
91
|
+
'power_of_attorney_missing',
|
|
92
|
+
'not_found',
|
|
93
|
+
'no_version',
|
|
94
|
+
'unknown_version',
|
|
95
|
+
'text_changed',
|
|
96
|
+
'already_accepted',
|
|
60
97
|
'activation_failed',
|
|
61
98
|
// Webhooks
|
|
62
99
|
'webhook_limit',
|
|
@@ -106,26 +143,38 @@ const RAT = {
|
|
|
106
143
|
rate_limited: 'Zu viele Aufrufe. data.retryAfterSec Sekunden warten und denselben Aufruf wiederholen.',
|
|
107
144
|
app_not_found: 'Die appId gibt es nicht. getPartnerInfo liefert die eigenen Apps samt id.',
|
|
108
145
|
app_not_accepted: 'Diese App hat noch keine abgenommene Version. Mit einem pk_test_-Schluessel oder mit env:"test" geht es sofort weiter; live erst nach der Abnahme.',
|
|
109
|
-
kein_partnerbetrieb: 'Dieser Betrieb gehoert nicht zu diesem Partner-Konto. Die eigenen stehen in listPartnerCustomers.',
|
|
110
146
|
live_not_allowed: 'Ein Test-Schluessel erzeugt nichts Echtes. Fuer einen Live-Betrieb den Live-Schluessel nehmen — umgekehrt darf ein Live-Schluessel mit env:"test" sehr wohl einen Testbetrieb anlegen.',
|
|
111
147
|
customer_exists: 'Diesen Betrieb gibt es schon (data.customerId). Mit derselben customerId weiterarbeiten.',
|
|
112
148
|
customer_conflict: 'Die Steuernummer ist bei Kasseneck bereits registriert. Die Zuordnung zum Partner macht Kasseneck — hello@kasseneck.at.',
|
|
113
149
|
customer_limit: 'Das Tageslimit fuer neue Betriebe ist erreicht (data.max, data.resetAt). Morgen weiter.',
|
|
114
|
-
|
|
150
|
+
access_not_allowed: 'Fuer dieses Partner-Konto sind Zugaenge zum Kundenpanel nicht freigeschaltet — es entstand NICHTS, auch kein Betrieb. Ohne access{invite:true} erneut anlegen oder die Freischaltung erfragen (Stand: getPartnerInfo.partner.canCreateAccess).',
|
|
115
151
|
email_taken: 'Fuer diese E-Mail gibt es schon einen Kasseneck-Zugang. Eine andere Adresse waehlen, auf die Einladung verzichten oder den Betrieb zuordnen lassen.',
|
|
116
152
|
no_email: 'Im Konto des Betriebs steht keine E-Mail-Adresse. Ohne sie geht weder eine Einladung noch der FinanzOnline-Link hinaus.',
|
|
153
|
+
tax_number_missing: 'Am Betrieb ist keine Steuernummer hinterlegt, ohne sie gibt es keinen Einrichtungs-Link. Die Steuernummer bei Kasseneck nachtragen lassen (hello@kasseneck.at), dann sendPartnerCustomerFonLink erneut.',
|
|
117
154
|
fon_missing: 'Der Betrieb hat noch keinen FinanzOnline-Zugang. sendPartnerCustomerFonLink senden und customer.fon_verified abwarten. Betrifft das ANMELDEN der Signatureinheit, nicht das Beantragen.',
|
|
118
155
|
signature_pending: 'Fuer diesen Betrieb laeuft bereits ein Antrag. Auf signature.ready warten.',
|
|
119
|
-
request_not_found: 'Diese signaturId gibt es nicht. getCustomerSignatureStatus nennt die des Betriebs.',
|
|
120
156
|
signature_missing: 'Der Betrieb hat ueberhaupt keine Signatur, und jede Kasse bezieht sich auf eine. Zuerst requestCustomerSignature.',
|
|
121
|
-
signature_unknown: 'Die genannte
|
|
122
|
-
signature_ambiguous: 'Der Betrieb hat mehrere Signaturen; welche die Kasse benutzt, muss dastehen. Eine aus data.choices als
|
|
157
|
+
signature_unknown: 'Die genannte signatureRequestId gehoert nicht zu diesem Betrieb. getCustomerSignatureStatus nennt die seinen.',
|
|
158
|
+
signature_ambiguous: 'Der Betrieb hat mehrere Signaturen; welche die Kasse benutzt, muss dastehen. Eine aus data.choices als signatureRequestId mitgeben.',
|
|
123
159
|
signature_not_ready: 'Die Signatur DIESER Kasse ist noch nicht bereit. Auf signature.ready warten; eine mit automatic:true angelegte Kasse geht danach von selbst live.',
|
|
124
160
|
signature_limit: 'Hoechstens zehn Signaturen je Betrieb. Eine bestehende benutzen, statt mit additional:true eine weitere zu beantragen.',
|
|
125
161
|
signature_failed: 'FinanzOnline hat die Anmeldung abgelehnt (data.rc). Kasseneck klaert das — hello@kasseneck.at.',
|
|
126
|
-
module_inactive: 'Das Modul (data.
|
|
162
|
+
module_inactive: 'Das Modul (data.module, z. B. "cash_register", Text in data.detail) ist fuer diesen Betrieb nicht gebucht. Kasseneck schaltet es frei.',
|
|
127
163
|
cashregister_limit: 'Hoechstens 20 Registrierkassen je Betrieb. Eine bestehende nutzen.',
|
|
128
164
|
cashregister_not_found: 'Diese cashregisterId gibt es bei diesem Betrieb nicht.',
|
|
165
|
+
contracts_pending: 'Nur live: der Betrieb hat Auftragsverarbeitungs- und Nutzungsvertrag noch nicht bestaetigt. An der Kasse aendert sich nichts. Den Betrieb ueber den Einrichtungs-Link bestaetigen lassen (sendPartnerCustomerFonLink, Stand in avv/terms von getPartnerCustomer), danach activateCashregister erneut.',
|
|
166
|
+
// -- Vertraege (reportCustomerContract) ------------------------------------
|
|
167
|
+
// Dieser Client bietet den Endpunkt (noch) nicht an; die Codes stehen hier
|
|
168
|
+
// nur fuer die Katalogseite und fuer einen Aufrufer, der die rohe Antwort
|
|
169
|
+
// selbst auswertet (siehe Kopfkommentar der Datei).
|
|
170
|
+
kind_not_allowed: 'reportCustomerContract mit einer anderen Art als "avv". Der Vollmachtsweg nimmt nur den Auftragsverarbeitungsvertrag entgegen. Dieser Client bietet den Endpunkt nicht an.',
|
|
171
|
+
mode_not_allowed: 'Der Vollmachtsweg ist fuer dieses Partner-Konto nicht freigeschaltet. Kasseneck fragen (hello@kasseneck.at).',
|
|
172
|
+
power_of_attorney_missing: 'Der Partnervertrag mit dem Vollmachts-Kapitel ist noch nicht bestaetigt. Erst danach nimmt der Vollmachtsweg Meldungen entgegen.',
|
|
173
|
+
not_found: 'Die genannte customerId gehoert nicht zu diesem Partner-Konto oder existiert nicht. listPartnerCustomers nennt die eigenen.',
|
|
174
|
+
no_version: 'Fuer die gemeldete Vertragsart gibt es derzeit keine gueltige Fassung. Bei Kasseneck nachfragen.',
|
|
175
|
+
unknown_version: 'Die gemeldete Vertragsversion gibt es nicht. Die aktuell geltende Fassung neu abrufen.',
|
|
176
|
+
text_changed: 'Der gezeigte Vertragstext hat sich seit dem Laden geaendert (data.textHash traegt die aktuell geltende Pruefsumme). Neu laden und danach erneut bestaetigen lassen.',
|
|
177
|
+
already_accepted: 'Diese Fassung ist bereits bestaetigt (data.contractId). Nichts weiter zu tun.',
|
|
129
178
|
activation_failed: 'Die Inbetriebnahme blieb an data.step haengen (ggf. data.rc). activateCashregister erneut aufrufen — jeder Schritt ist idempotent, der Lauf setzt an der Bruchstelle an.',
|
|
130
179
|
webhook_limit: 'Hoechstens 10 Webhook-Endpunkte je Partner. Einen ungenutzten loeschen.',
|
|
131
180
|
webhook_inactive: 'Der Webhook steht auf active:false. Zuerst aktivieren, dann erneut proben.',
|