@flowselections/floriday-klanten-module 1.0.36 → 1.0.37
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/dist-lib/components/klanten/BulkStickerUploadDialog.d.ts.map +1 -1
- package/dist-lib/components/klanten/BulkStickerUploadDialog.js +30 -8
- package/dist-lib/components/klanten/CustomerAssortmentTab.d.ts.map +1 -1
- package/dist-lib/components/klanten/CustomerAssortmentTab.js +48 -10
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +129 -0
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.d.ts +129 -0
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +129 -0
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +129 -0
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/accounting/twinfield/client.server.d.ts +7 -8
- package/dist-lib/lib/accounting/twinfield/client.server.d.ts.map +1 -1
- package/dist-lib/lib/accounting/twinfield/client.server.js +147 -78
- package/dist-lib/lib/accounting/twinfield/worker.functions.d.ts +387 -0
- package/dist-lib/lib/accounting/twinfield/worker.functions.d.ts.map +1 -1
- package/dist-lib/lib/accounting/twinfield/worker.server.d.ts.map +1 -1
- package/dist-lib/lib/accounting/twinfield/worker.server.js +17 -0
- package/dist-lib/lib/accounting.functions.d.ts +387 -0
- package/dist-lib/lib/accounting.functions.d.ts.map +1 -1
- package/dist-lib/lib/customer-analytics.functions.d.ts +129 -0
- package/dist-lib/lib/customer-analytics.functions.d.ts.map +1 -1
- package/dist-lib/lib/customer-assortment.functions.d.ts +132 -3
- package/dist-lib/lib/customer-assortment.functions.d.ts.map +1 -1
- package/dist-lib/lib/customer-assortment.functions.js +12 -0
- package/dist-lib/lib/customer-notes.functions.d.ts +258 -0
- package/dist-lib/lib/customer-notes.functions.d.ts.map +1 -1
- package/dist-lib/lib/customer-revenue.functions.d.ts +129 -0
- package/dist-lib/lib/customer-revenue.functions.d.ts.map +1 -1
- package/dist-lib/lib/customer-stickers.functions.d.ts +1165 -0
- package/dist-lib/lib/customer-stickers.functions.d.ts.map +1 -1
- package/dist-lib/lib/customer-stickers.functions.js +122 -75
- package/dist-lib/lib/customers.functions.d.ts +1161 -0
- package/dist-lib/lib/customers.functions.d.ts.map +1 -1
- package/dist-lib/lib/delivery-locations.functions.d.ts +645 -0
- package/dist-lib/lib/delivery-locations.functions.d.ts.map +1 -1
- package/dist-lib/lib/external-customers.functions.d.ts +516 -0
- package/dist-lib/lib/external-customers.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-assortment.functions.d.ts +129 -0
- package/dist-lib/lib/floriday-assortment.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-discounts.functions.d.ts +258 -0
- package/dist-lib/lib/floriday-discounts.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-price-import.functions.d.ts +258 -0
- package/dist-lib/lib/floriday-price-import.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-sticker-import.functions.d.ts +27323 -0
- package/dist-lib/lib/floriday-sticker-import.functions.d.ts.map +1 -0
- package/dist-lib/lib/floriday-sticker-import.functions.js +307 -0
- package/dist-lib/lib/floriday-trade-items.functions.d.ts +129 -0
- package/dist-lib/lib/floriday-trade-items.functions.d.ts.map +1 -1
- package/dist-lib/lib/local-discounts.functions.d.ts +903 -0
- package/dist-lib/lib/local-discounts.functions.d.ts.map +1 -1
- package/dist-lib/lib/logistics-events.functions.d.ts +129 -0
- package/dist-lib/lib/logistics-events.functions.d.ts.map +1 -1
- package/dist-lib/lib/logistics-strategy.functions.d.ts +516 -0
- package/dist-lib/lib/logistics-strategy.functions.d.ts.map +1 -1
- package/dist-lib/lib/overdue-invoices.functions.d.ts +129 -0
- package/dist-lib/lib/overdue-invoices.functions.d.ts.map +1 -1
- package/dist-lib/lib/price-groups-local.functions.d.ts +1677 -0
- package/dist-lib/lib/price-groups-local.functions.d.ts.map +1 -1
- package/dist-lib/lib/price-groups.functions.d.ts +129 -0
- package/dist-lib/lib/price-groups.functions.d.ts.map +1 -1
- package/dist-lib/lib/twinfield-adopt.functions.d.ts +258 -0
- package/dist-lib/lib/twinfield-adopt.functions.d.ts.map +1 -1
- package/dist-lib/lib/twinfield-ledger.functions.d.ts +129 -0
- package/dist-lib/lib/twinfield-ledger.functions.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* Alle Twinfield-communicatie loopt via de Twinfield-authenticatiemodule.
|
|
3
|
+
* Deze module praat nooit rechtstreeks met Twinfield of Central Auth en gebruikt
|
|
4
|
+
* nooit een vast cluster-adres of vaste administratiecode: die komen per aanroep
|
|
5
|
+
* uit het service-token-antwoord van de authenticatiemodule.
|
|
6
6
|
*/
|
|
7
7
|
export interface TwinfieldConnection {
|
|
8
8
|
id: string;
|
|
@@ -21,13 +21,12 @@ export declare class TwinfieldError extends Error {
|
|
|
21
21
|
export interface TwinfieldToken {
|
|
22
22
|
accessToken: string;
|
|
23
23
|
clusterUri: string;
|
|
24
|
-
companyCode: string
|
|
24
|
+
companyCode: string;
|
|
25
25
|
}
|
|
26
26
|
export declare function loadActiveConnection(preferredId?: string): Promise<TwinfieldConnection | null>;
|
|
27
27
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* dan wordt de opgeslagen omgeving gecorrigeerd.
|
|
28
|
+
* Volledige tokentraject via de authenticatiemodule: statuscontrole, daarna
|
|
29
|
+
* het service-token. Nooit cachen of opslaan.
|
|
31
30
|
*/
|
|
32
31
|
export declare function fetchTwinfieldToken(conn: TwinfieldConnection): Promise<TwinfieldToken>;
|
|
33
32
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.server.d.ts","sourceRoot":"","sources":["../../../../src/lib/accounting/twinfield/client.server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.server.d.ts","sourceRoot":"","sources":["../../../../src/lib/accounting/twinfield/client.server.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,qDAAqD;AACrD,MAAM,MAAM,oBAAoB,GAAG,aAAa,GAAG,QAAQ,GAAG,WAAW,GAAG,UAAU,CAAC;AAEvF,qBAAa,cAAe,SAAQ,KAAK;IACvC,IAAI,EAAE,oBAAoB,CAAC;gBACf,IAAI,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM;CAKxD;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAaD,wBAAsB,oBAAoB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAyBpG;AAwOD;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,cAAc,CAAC,CAK5F;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAiCpF;AAYD,wBAAsB,cAAc,CAAC,IAAI,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAwD5I"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getRequestHeader } from "@tanstack/react-start/server";
|
|
1
2
|
import { supabaseAdmin } from "../../../integrations/supabase/client.server";
|
|
2
3
|
import { buildProcessXmlEnvelope } from "./mapping";
|
|
3
4
|
export class TwinfieldError extends Error {
|
|
@@ -41,103 +42,173 @@ export async function loadActiveConnection(preferredId) {
|
|
|
41
42
|
}
|
|
42
43
|
return null;
|
|
43
44
|
}
|
|
44
|
-
/**
|
|
45
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Het bearer-token van de lopende aanvraag, indien aanwezig. In een cron-run
|
|
47
|
+
* (geen request-context) geeft dit `null` terug.
|
|
48
|
+
*/
|
|
49
|
+
function getCallerBearerToken() {
|
|
50
|
+
try {
|
|
51
|
+
const header = getRequestHeader("authorization");
|
|
52
|
+
if (!header)
|
|
53
|
+
return null;
|
|
54
|
+
const m = /^Bearer\s+(.+)$/i.exec(header.trim());
|
|
55
|
+
return m ? m[1] : null;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Fail closed: adres van de authenticatiemodule uit een omgevingsvariabele,
|
|
63
|
+
* anders uit de eigen instellingentabel. Ontbreekt beide → duidelijke fout.
|
|
64
|
+
*/
|
|
65
|
+
async function resolveAuthModuleUrl() {
|
|
66
|
+
const fromEnv = process.env.TWINFIELD_AUTH_URL;
|
|
67
|
+
if (fromEnv && fromEnv.trim())
|
|
68
|
+
return fromEnv.trim().replace(/\/+$/, "");
|
|
69
|
+
const { data } = await supabaseAdmin
|
|
70
|
+
.from("app_settings")
|
|
71
|
+
.select("value")
|
|
72
|
+
.eq("key", "twinfield_auth_url")
|
|
73
|
+
.maybeSingle();
|
|
74
|
+
const fromSettings = data?.value;
|
|
75
|
+
if (fromSettings && fromSettings.trim())
|
|
76
|
+
return fromSettings.trim().replace(/\/+$/, "");
|
|
77
|
+
// Terugval op het al geconfigureerde adres van de gedeelde authenticatie-
|
|
78
|
+
// module (CENTRAL_AUTH_URL is dezelfde dienst).
|
|
79
|
+
const legacy = process.env.CENTRAL_AUTH_URL;
|
|
80
|
+
if (legacy && legacy.trim())
|
|
81
|
+
return legacy.trim().replace(/\/+$/, "");
|
|
82
|
+
throw new TwinfieldError("config", "Het adres van de Twinfield-authenticatiemodule is niet ingesteld (omgevingsvariabele TWINFIELD_AUTH_URL of instelling 'twinfield_auth_url').");
|
|
83
|
+
}
|
|
84
|
+
/** Machine-sleutelwoord uit de gedeelde database. Alleen server-side, nooit loggen. */
|
|
85
|
+
async function getCronSecret() {
|
|
86
|
+
const { data, error } = await supabaseAdmin
|
|
87
|
+
.from("twinfield_cron_auth")
|
|
88
|
+
.select("secret")
|
|
89
|
+
.eq("id", 1)
|
|
90
|
+
.maybeSingle();
|
|
91
|
+
const secret = data?.secret;
|
|
92
|
+
if (error || !secret) {
|
|
93
|
+
throw new TwinfieldError("config", "Het machine-sleutelwoord voor de Twinfield-authenticatiemodule ontbreekt (twinfield_cron_auth, id = 1).");
|
|
94
|
+
}
|
|
95
|
+
return secret;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Statuscontrole bij de authenticatiemodule. Leesaanvraag met de
|
|
99
|
+
* koppelings-id als parameter in het adres. Auth: bearer-token van de lopende
|
|
100
|
+
* aanvraag indien aanwezig, anders het machine-sleutelwoord.
|
|
101
|
+
*/
|
|
102
|
+
async function checkAuthModuleStatus(baseUrl, conn, cronSecret) {
|
|
103
|
+
const bearer = getCallerBearerToken();
|
|
104
|
+
const headers = bearer
|
|
105
|
+
? { Authorization: `Bearer ${bearer}` }
|
|
106
|
+
: { "x-cron-secret": cronSecret };
|
|
107
|
+
const url = `${baseUrl}/api/public/twinfield/status?connection_id=${encodeURIComponent(conn.id)}`;
|
|
46
108
|
let res;
|
|
47
109
|
try {
|
|
48
|
-
res = await fetch(
|
|
110
|
+
res = await fetch(url, { headers });
|
|
111
|
+
}
|
|
112
|
+
catch (e) {
|
|
113
|
+
throw new TwinfieldError("temporary", `De Twinfield-authenticatiemodule is nu niet bereikbaar: ${e instanceof Error ? e.message : String(e)}`);
|
|
114
|
+
}
|
|
115
|
+
const text = await res.text().catch(() => "");
|
|
116
|
+
if (!res.ok) {
|
|
117
|
+
if (res.status === 502) {
|
|
118
|
+
throw new TwinfieldError("temporary", "De Twinfield-authenticatiemodule is tijdelijk niet bereikbaar (502). Er volgt automatisch een nieuwe poging.");
|
|
119
|
+
}
|
|
120
|
+
throw new TwinfieldError("config", `De statuscontrole van de Twinfield-authenticatiemodule gaf een fout (${res.status}).`);
|
|
121
|
+
}
|
|
122
|
+
let json;
|
|
123
|
+
try {
|
|
124
|
+
json = JSON.parse(text);
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
throw new TwinfieldError("temporary", "De authenticatiemodule gaf een onleesbaar statusantwoord.");
|
|
128
|
+
}
|
|
129
|
+
const lower = text.toLowerCase();
|
|
130
|
+
if (lower.includes("ambiguous") || lower.includes("niet eenduidig")) {
|
|
131
|
+
throw new TwinfieldError("config", "De Twinfield-authenticatiemodule kon de administratie niet eenduidig bepalen. Controleer de koppeling in de authenticatiemodule.");
|
|
132
|
+
}
|
|
133
|
+
const status = String(json.status ?? json.state ?? "").toLowerCase();
|
|
134
|
+
const connected = json.connected === true ||
|
|
135
|
+
status === "connected" ||
|
|
136
|
+
status === "ok" ||
|
|
137
|
+
status === "active";
|
|
138
|
+
if (!connected) {
|
|
139
|
+
throw new TwinfieldError("config", "Er is geen actieve Twinfield-koppeling in de authenticatiemodule. De klant blijft op wachtstatus staan.");
|
|
140
|
+
}
|
|
141
|
+
const connectionId = json.connection_id ??
|
|
142
|
+
json.connectionId ??
|
|
143
|
+
json.connection?.id ??
|
|
144
|
+
null;
|
|
145
|
+
return { connected: true, connectionId };
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Haalt een vers service-token op bij de authenticatiemodule. Dit eindpunt
|
|
149
|
+
* accepteert uitsluitend het machine-sleutelwoord — nooit een inlogtoken.
|
|
150
|
+
* Geeft access_token, cluster_url en administration_code terug; zonder
|
|
151
|
+
* administratiecode stopt de push met een duidelijke melding.
|
|
152
|
+
*/
|
|
153
|
+
async function requestServiceToken(baseUrl, cronSecret, connectionId) {
|
|
154
|
+
let res;
|
|
155
|
+
try {
|
|
156
|
+
res = await fetch(`${baseUrl}/api/public/twinfield/service-token`, {
|
|
49
157
|
method: "POST",
|
|
50
158
|
headers: {
|
|
51
|
-
|
|
159
|
+
"x-cron-secret": cronSecret,
|
|
52
160
|
"Content-Type": "application/json",
|
|
53
161
|
},
|
|
54
|
-
|
|
55
|
-
// negeert Central Auth het filter en antwoordt met ambiguous_account.
|
|
56
|
-
body: JSON.stringify({ account_key: accountKey, environment }),
|
|
162
|
+
body: JSON.stringify({ connection_id: connectionId }),
|
|
57
163
|
});
|
|
58
164
|
}
|
|
59
165
|
catch (e) {
|
|
60
|
-
throw new TwinfieldError("temporary", `
|
|
166
|
+
throw new TwinfieldError("temporary", `De Twinfield-authenticatiemodule is nu niet bereikbaar: ${e instanceof Error ? e.message : String(e)}`);
|
|
61
167
|
}
|
|
62
168
|
const text = await res.text().catch(() => "");
|
|
63
|
-
|
|
64
|
-
|
|
169
|
+
const lower = text.toLowerCase();
|
|
170
|
+
if (res.status === 401 || res.status === 403) {
|
|
171
|
+
if (lower.includes("reauthorize") || lower.includes("herautoris")) {
|
|
172
|
+
throw new TwinfieldError("reauthorize", "De Twinfield-autorisatie is verlopen of ingetrokken. Autoriseer Twinfield opnieuw in de authenticatiemodule; de klant blijft op wachtstatus staan.");
|
|
173
|
+
}
|
|
174
|
+
throw new TwinfieldError("config", "De Twinfield-authenticatiemodule weigerde het machine-sleutelwoord. Controleer twinfield_cron_auth.");
|
|
175
|
+
}
|
|
176
|
+
if (res.status === 502) {
|
|
177
|
+
throw new TwinfieldError("temporary", "De achterliggende Twinfield-dienst was even niet bereikbaar (502). Er volgt automatisch een nieuwe poging.");
|
|
178
|
+
}
|
|
179
|
+
if (lower.includes("ambiguous") || lower.includes("niet eenduidig")) {
|
|
180
|
+
throw new TwinfieldError("config", "De Twinfield-authenticatiemodule kon de administratie niet eenduidig bepalen. Controleer de koppeling in de authenticatiemodule.");
|
|
181
|
+
}
|
|
182
|
+
if (!res.ok) {
|
|
183
|
+
throw new TwinfieldError("temporary", `De Twinfield-authenticatiemodule gaf een fout (${res.status}).`);
|
|
184
|
+
}
|
|
65
185
|
let json;
|
|
66
186
|
try {
|
|
67
187
|
json = JSON.parse(text);
|
|
68
188
|
}
|
|
69
189
|
catch {
|
|
70
|
-
throw new TwinfieldError("temporary", "
|
|
190
|
+
throw new TwinfieldError("temporary", "De authenticatiemodule gaf een onleesbaar tokenantwoord.");
|
|
71
191
|
}
|
|
72
|
-
const accessToken = (json.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
token: {
|
|
78
|
-
accessToken,
|
|
79
|
-
clusterUri: String(json.clusterUri ?? json.cluster_uri ?? "").replace(/\/+$/, ""),
|
|
80
|
-
companyCode: (json.companyCode ?? json.company_code ?? null),
|
|
81
|
-
},
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
function classifyCentralAuthFailure(status, body) {
|
|
85
|
-
const lower = body.toLowerCase();
|
|
86
|
-
if (lower.includes("ambiguous_account")) {
|
|
87
|
-
return new TwinfieldError("config", "Central Auth kon het account niet eenduidig bepalen (ambiguous_account). Controleer de koppeling in de authenticatie-module.");
|
|
192
|
+
const accessToken = (json.access_token ?? json.accessToken);
|
|
193
|
+
const clusterUri = String(json.cluster_url ?? json.clusterUrl ?? "").replace(/\/+$/, "");
|
|
194
|
+
const companyCode = (json.administration_code ?? json.administrationCode ?? null);
|
|
195
|
+
if (!accessToken || !clusterUri) {
|
|
196
|
+
throw new TwinfieldError("temporary", "De authenticatiemodule gaf een onvolledig service-token terug.");
|
|
88
197
|
}
|
|
89
|
-
if (
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
if (status === 401 ||
|
|
93
|
-
status === 403 ||
|
|
94
|
-
/expired|revoked|invalid_grant/.test(lower)) {
|
|
95
|
-
return new TwinfieldError("reauthorize", "De Twinfield-autorisatie is verlopen of ingetrokken. Autoriseer Twinfield opnieuw.");
|
|
198
|
+
if (!companyCode) {
|
|
199
|
+
throw new TwinfieldError("config", "De authenticatiemodule gaf geen administratiecode terug. De push is gestopt; er wordt niet teruggevallen op een opgeslagen code.");
|
|
96
200
|
}
|
|
97
|
-
return
|
|
201
|
+
return { accessToken, clusterUri, companyCode };
|
|
98
202
|
}
|
|
99
203
|
/**
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
* dan wordt de opgeslagen omgeving gecorrigeerd.
|
|
204
|
+
* Volledige tokentraject via de authenticatiemodule: statuscontrole, daarna
|
|
205
|
+
* het service-token. Nooit cachen of opslaan.
|
|
103
206
|
*/
|
|
104
207
|
export async function fetchTwinfieldToken(conn) {
|
|
105
|
-
const baseUrl =
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
const accountKey = (conn.account_key ?? "").trim().toLowerCase();
|
|
111
|
-
if (!accountKey) {
|
|
112
|
-
throw new TwinfieldError("reauthorize", "De Twinfield-koppeling heeft geen account_key. Autoriseer Twinfield opnieuw in de authenticatie-module.");
|
|
113
|
-
}
|
|
114
|
-
const environment = (conn.environment ?? "live").trim().toLowerCase();
|
|
115
|
-
const first = await requestCentralAuthToken(baseUrl, secret, accountKey, environment);
|
|
116
|
-
if (first.ok)
|
|
117
|
-
return withFallbackCluster(conn, first.token);
|
|
118
|
-
// Mogelijke omgeving-mismatch: probeer eenmalig de andere omgeving.
|
|
119
|
-
if (first.status === 404 || first.status === 401) {
|
|
120
|
-
const other = environment === "sandbox" ? "live" : "sandbox";
|
|
121
|
-
const retry = await requestCentralAuthToken(baseUrl, secret, accountKey, other);
|
|
122
|
-
if (retry.ok) {
|
|
123
|
-
await supabaseAdmin
|
|
124
|
-
.from("twinfield_connections")
|
|
125
|
-
.update({ environment: other, updated_at: new Date().toISOString() })
|
|
126
|
-
.eq("id", conn.id);
|
|
127
|
-
conn.environment = other;
|
|
128
|
-
return withFallbackCluster(conn, retry.token);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
throw classifyCentralAuthFailure(first.status, first.body);
|
|
132
|
-
}
|
|
133
|
-
function withFallbackCluster(conn, token) {
|
|
134
|
-
if (!token.clusterUri && conn.cluster_uri) {
|
|
135
|
-
token.clusterUri = conn.cluster_uri.replace(/\/+$/, "");
|
|
136
|
-
}
|
|
137
|
-
if (!token.clusterUri) {
|
|
138
|
-
throw new TwinfieldError("config", "Er is geen Twinfield cluster-URL bekend, niet uit Central Auth en niet uit de koppeling.");
|
|
139
|
-
}
|
|
140
|
-
return token;
|
|
208
|
+
const baseUrl = await resolveAuthModuleUrl();
|
|
209
|
+
const cronSecret = await getCronSecret();
|
|
210
|
+
const status = await checkAuthModuleStatus(baseUrl, conn, cronSecret);
|
|
211
|
+
return requestServiceToken(baseUrl, cronSecret, status.connectionId ?? conn.id);
|
|
141
212
|
}
|
|
142
213
|
/**
|
|
143
214
|
* Leest het antwoord van processxml.asmx strikt uit. Twinfield geeft bij succes
|
|
@@ -190,10 +261,8 @@ function decodeXml(v) {
|
|
|
190
261
|
}
|
|
191
262
|
export async function sendProcessXml(conn, dimensionXml) {
|
|
192
263
|
let token = await fetchTwinfieldToken(conn);
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
throw new TwinfieldError("config", "Twinfield office/company code ontbreekt in de koppeling.");
|
|
196
|
-
}
|
|
264
|
+
// De administratiecode komt uitsluitend uit het service-token-antwoord.
|
|
265
|
+
const companyCode = token.companyCode;
|
|
197
266
|
const doCall = async () => {
|
|
198
267
|
const envelope = buildProcessXmlEnvelope(token.accessToken, companyCode, dimensionXml);
|
|
199
268
|
return fetch(`${token.clusterUri}/webservices/processxml.asmx`, {
|