@flowselections/floriday-verkoop-module 1.0.55 → 1.0.57
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/verkoop/OrderAfleverbrievenCard.d.ts.map +1 -1
- package/dist-lib/components/verkoop/OrderAfleverbrievenCard.js +5 -5
- package/dist-lib/components/verkoop/OrderKarindelingCard.d.ts.map +1 -1
- package/dist-lib/components/verkoop/OrderKarindelingCard.js +2 -1
- package/dist-lib/components/verkoop/SalesOrdersTable.d.ts.map +1 -1
- package/dist-lib/components/verkoop/SalesOrdersTable.js +17 -4
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +355 -18
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.d.ts +355 -18
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +355 -18
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +357 -18
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/cart-lock.functions.d.ts +355 -18
- package/dist-lib/lib/cart-lock.functions.d.ts.map +1 -1
- package/dist-lib/lib/cart-planning-settings.functions.d.ts +3948 -241
- package/dist-lib/lib/cart-planning-settings.functions.d.ts.map +1 -1
- package/dist-lib/lib/cart-replan.functions.d.ts +1065 -54
- package/dist-lib/lib/cart-replan.functions.d.ts.map +1 -1
- package/dist-lib/lib/cart-replan.functions.js +38 -31
- package/dist-lib/lib/create-order.functions.d.ts +6164 -435
- package/dist-lib/lib/create-order.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-auto-fulfillment.functions.d.ts +1065 -54
- package/dist-lib/lib/floriday-auto-fulfillment.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-gateway.server.d.ts +14 -0
- package/dist-lib/lib/floriday-gateway.server.d.ts.map +1 -1
- package/dist-lib/lib/floriday-gateway.server.js +46 -0
- package/dist-lib/lib/floriday-logistic-labels.functions.d.ts +23972 -28
- package/dist-lib/lib/floriday-logistic-labels.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-logistic-labels.functions.js +209 -90
- package/dist-lib/lib/floriday-mirror.functions.d.ts +355 -18
- package/dist-lib/lib/floriday-mirror.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-public.functions.d.ts +2485 -126
- package/dist-lib/lib/floriday-public.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-sync.d.ts.map +1 -1
- package/dist-lib/lib/floriday-writes.functions.d.ts +1775 -90
- package/dist-lib/lib/floriday-writes.functions.d.ts.map +1 -1
- package/dist-lib/lib/invoice-timing.functions.d.ts +1420 -72
- package/dist-lib/lib/invoice-timing.functions.d.ts.map +1 -1
- package/dist-lib/lib/load-carriers.functions.d.ts +355 -18
- package/dist-lib/lib/load-carriers.functions.d.ts.map +1 -1
- package/dist-lib/lib/logistics-engine.functions.d.ts +1775 -90
- package/dist-lib/lib/logistics-engine.functions.d.ts.map +1 -1
- package/dist-lib/lib/logistics-stock.functions.d.ts +710 -36
- package/dist-lib/lib/logistics-stock.functions.d.ts.map +1 -1
- package/dist-lib/lib/order-addresses.functions.d.ts +355 -18
- package/dist-lib/lib/order-addresses.functions.d.ts.map +1 -1
- package/dist-lib/lib/order-buffers.functions.d.ts +1065 -54
- package/dist-lib/lib/order-buffers.functions.d.ts.map +1 -1
- package/dist-lib/lib/order-carrier.functions.d.ts +710 -36
- package/dist-lib/lib/order-carrier.functions.d.ts.map +1 -1
- package/dist-lib/lib/order-pickup.functions.d.ts +710 -36
- package/dist-lib/lib/order-pickup.functions.d.ts.map +1 -1
- package/dist-lib/lib/order-shipments.functions.d.ts +1420 -72
- package/dist-lib/lib/order-shipments.functions.d.ts.map +1 -1
- package/dist-lib/lib/product-name.d.ts +3 -0
- package/dist-lib/lib/product-name.d.ts.map +1 -0
- package/dist-lib/lib/product-name.js +43 -0
- package/dist-lib/lib/salesorders-list.functions.d.ts +355 -18
- package/dist-lib/lib/salesorders-list.functions.d.ts.map +1 -1
- package/dist-lib/lib/salesorders-list.server.d.ts.map +1 -1
- package/dist-lib/lib/salesorders-list.server.js +43 -1
- package/dist-lib/lib/salesorders-mapping.d.ts +8 -0
- package/dist-lib/lib/salesorders-mapping.d.ts.map +1 -1
- package/dist-lib/lib/salesorders.functions.d.ts +1775 -90
- package/dist-lib/lib/salesorders.functions.d.ts.map +1 -1
- package/dist-lib/lib/stock-consumption-alerts.functions.d.ts +710 -36
- package/dist-lib/lib/stock-consumption-alerts.functions.d.ts.map +1 -1
- package/dist-lib/lib/tradeitems.functions.d.ts +355 -18
- package/dist-lib/lib/tradeitems.functions.d.ts.map +1 -1
- package/package.json +131 -131
|
@@ -1,12 +1,32 @@
|
|
|
1
|
-
// Server functions
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
1
|
+
// Server functions voor afleverbrieven.
|
|
2
|
+
//
|
|
3
|
+
// Eén waarheid: public.delivery_notes. Elke afleverbrief hangt daar aan onze
|
|
4
|
+
// eigen order (order_id + order_number, bijv. FO-2600033), ongeacht herkomst:
|
|
5
|
+
// - source 'floriday' : PDF opgehaald bij Floriday
|
|
6
|
+
// GET /fulfillment-orders/{fulfillmentOrderId}/logistic-labels → één PDF
|
|
7
|
+
// per fulfillment order; die PDF hoort bij álle codes van die order.
|
|
8
|
+
// - source 'engine' : PDF gegenereerd door onze logistieke engine
|
|
9
|
+
// (HO/handmatige en MO/mail-bestellingen) via registerDeliveryNote().
|
|
10
|
+
//
|
|
11
|
+
// PDF's staan in de private bucket "delivery-notes"; de UI krijgt een
|
|
12
|
+
// signed URL. Fouten worden NIET stil geslikt: statuscode + leesbare tekst
|
|
13
|
+
// komen mee naar de UI (423 = levering nog in concept, 404 = niet gevonden).
|
|
5
14
|
import { createServerFn } from "@tanstack/react-start";
|
|
6
15
|
import { z } from "zod";
|
|
7
16
|
import { requireSupabaseAuth } from "../integrations/supabase/auth-middleware";
|
|
8
|
-
import {
|
|
9
|
-
|
|
17
|
+
import { florydayFetchBinary } from "./floriday-gateway.server";
|
|
18
|
+
import { resolveOrderRow } from "./order-row.server";
|
|
19
|
+
const BUCKET = "delivery-notes";
|
|
20
|
+
function foutTekst(status, detail) {
|
|
21
|
+
if (status === 423) {
|
|
22
|
+
return "Levering staat nog in concept — bevestig de levering in Floriday, daarna is de afleverbrief beschikbaar.";
|
|
23
|
+
}
|
|
24
|
+
if (status === 404)
|
|
25
|
+
return "Afleverbrief niet gevonden bij Floriday (404).";
|
|
26
|
+
if (status === 401 || status === 403)
|
|
27
|
+
return `Geen toegang tot Floriday (${status}).`;
|
|
28
|
+
return `Ophalen bij Floriday mislukt (${status})${detail ? `: ${detail}` : ""}.`;
|
|
29
|
+
}
|
|
10
30
|
async function collectRefsForOrder(supabase, salesOrderId) {
|
|
11
31
|
const { data, error } = await supabase
|
|
12
32
|
.from("floriday_fulfillment_orders_cache")
|
|
@@ -14,7 +34,6 @@ async function collectRefsForOrder(supabase, salesOrderId) {
|
|
|
14
34
|
.eq("is_deleted", false);
|
|
15
35
|
if (error)
|
|
16
36
|
throw new Error(`fulfillment orders lezen faalde: ${error.message}`);
|
|
17
|
-
// env per connection
|
|
18
37
|
const connIds = Array.from(new Set((data ?? []).map((r) => r.connection_id).filter(Boolean)));
|
|
19
38
|
const envByConn = new Map();
|
|
20
39
|
if (connIds.length > 0) {
|
|
@@ -50,7 +69,6 @@ async function collectRefsForOrder(supabase, salesOrderId) {
|
|
|
50
69
|
});
|
|
51
70
|
}
|
|
52
71
|
}
|
|
53
|
-
// dedupe on (fulfillmentOrderId, code) — keep first
|
|
54
72
|
const seen = new Set();
|
|
55
73
|
return refs.filter((r) => {
|
|
56
74
|
const k = `${r.fulfillmentOrderId}:${r.code}`;
|
|
@@ -60,45 +78,29 @@ async function collectRefsForOrder(supabase, salesOrderId) {
|
|
|
60
78
|
return true;
|
|
61
79
|
});
|
|
62
80
|
}
|
|
63
|
-
|
|
81
|
+
/** Haalt de gecombineerde PDF van één fulfillment order op bij Floriday. */
|
|
82
|
+
async function fetchPdfForFulfillmentOrder(supabase, connectionId, fulfillmentOrderId) {
|
|
64
83
|
const { data: conn, error } = await supabase
|
|
65
84
|
.from("floriday_connections")
|
|
66
85
|
.select("id, environment, api_key")
|
|
67
|
-
.eq("id",
|
|
86
|
+
.eq("id", connectionId)
|
|
68
87
|
.maybeSingle();
|
|
69
88
|
if (error || !conn) {
|
|
70
|
-
return { ok: false, status: 0, error: `connectie ${
|
|
89
|
+
return { ok: false, status: 0, error: `Floriday-connectie ${connectionId} niet gevonden.` };
|
|
71
90
|
}
|
|
72
|
-
|
|
73
|
-
const { getFlorydayTokenFromCentral } = await import("./floriday-central-token.server");
|
|
74
|
-
const tokenRes = await getFlorydayTokenFromCentral(conn.environment ?? "staging");
|
|
75
|
-
if (!tokenRes.ok) {
|
|
76
|
-
return {
|
|
77
|
-
ok: false,
|
|
78
|
-
status: tokenRes.status,
|
|
79
|
-
error: `central token faalde: ${tokenRes.raw.slice(0, 200)}`,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
const base = apiBaseFor(conn.environment);
|
|
83
|
-
// Floriday endpoint: GET /logistic-labels/{fulfillmentOrderId}/{code} → application/pdf
|
|
84
|
-
const url = `${base}/logistic-labels/${encodeURIComponent(ref.fulfillmentOrderId)}/${encodeURIComponent(ref.code)}`;
|
|
85
|
-
const res = await fetch(url, {
|
|
91
|
+
const res = await florydayFetchBinary(supabase, conn, {
|
|
86
92
|
method: "GET",
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
Authorization: `Bearer ${tokenRes.access_token}`,
|
|
90
|
-
...(conn.api_key ? { "x-api-key": conn.api_key } : {}),
|
|
91
|
-
},
|
|
93
|
+
path: `/fulfillment-orders/${encodeURIComponent(fulfillmentOrderId)}/logistic-labels`,
|
|
94
|
+
accept: "application/pdf",
|
|
92
95
|
});
|
|
93
96
|
if (!res.ok) {
|
|
94
|
-
return { ok: false, status: res.status, error:
|
|
97
|
+
return { ok: false, status: res.status, error: foutTekst(res.status, res.rawText) };
|
|
95
98
|
}
|
|
96
|
-
const buf = new Uint8Array(await res.arrayBuffer());
|
|
97
99
|
return {
|
|
98
100
|
ok: true,
|
|
99
101
|
status: res.status,
|
|
100
|
-
bytes:
|
|
101
|
-
contentType: res.
|
|
102
|
+
bytes: res.bytes ?? undefined,
|
|
103
|
+
contentType: res.contentType ?? "application/pdf",
|
|
102
104
|
};
|
|
103
105
|
}
|
|
104
106
|
const ListSchema = z.object({ salesOrderId: z.string().min(1) });
|
|
@@ -107,75 +109,192 @@ export const listLogisticLabelsForOrder = createServerFn({ method: "POST" })
|
|
|
107
109
|
.inputValidator((d) => ListSchema.parse(d))
|
|
108
110
|
.handler(async ({ data, context }) => {
|
|
109
111
|
const supabase = context.supabase;
|
|
112
|
+
const { supabaseAdmin } = await import("../integrations/supabase/client.server");
|
|
113
|
+
// 1. Onze eigen order erbij zoeken (lokaal ordernummer koppelen).
|
|
114
|
+
let orderId = null;
|
|
115
|
+
let orderNumber = null;
|
|
116
|
+
try {
|
|
117
|
+
const row = await resolveOrderRow(supabase, data.salesOrderId);
|
|
118
|
+
orderId = row.id;
|
|
119
|
+
orderNumber = row.order_number;
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
/* order (nog) niet bekend — brief blijft dan zonder koppeling */
|
|
123
|
+
}
|
|
124
|
+
// 2. Al opgeslagen briefjes bij deze order.
|
|
125
|
+
const stored = new Map();
|
|
126
|
+
if (orderId) {
|
|
127
|
+
const { data: rows } = await supabase
|
|
128
|
+
.from("delivery_notes")
|
|
129
|
+
.select("*")
|
|
130
|
+
.eq("order_id", orderId);
|
|
131
|
+
for (const r of rows ?? []) {
|
|
132
|
+
stored.set(`${r.source}:${r.fulfillment_order_id ?? ""}:${r.label_code ?? ""}`, r);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// 3. Floriday-referenties bepalen en per fulfillment order één keer ophalen.
|
|
110
136
|
const refs = await collectRefsForOrder(supabase, data.salesOrderId);
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
.
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
137
|
+
const perFo = new Map();
|
|
138
|
+
for (const ref of refs) {
|
|
139
|
+
const key = `floriday:${ref.fulfillmentOrderId}:${ref.code}`;
|
|
140
|
+
const existing = stored.get(key);
|
|
141
|
+
if (existing?.storage_path)
|
|
142
|
+
continue; // al gecached
|
|
143
|
+
if (perFo.has(ref.fulfillmentOrderId))
|
|
144
|
+
continue; // deze order al geprobeerd
|
|
145
|
+
const res = await fetchPdfForFulfillmentOrder(supabase, ref.connectionId, ref.fulfillmentOrderId);
|
|
146
|
+
if (!res.ok || !res.bytes) {
|
|
147
|
+
perFo.set(ref.fulfillmentOrderId, { ok: false, status: res.status, error: res.error });
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
const path = `floriday/${ref.connectionId}/${ref.fulfillmentOrderId}.pdf`;
|
|
151
|
+
const { error: upErr } = await supabaseAdmin.storage.from(BUCKET).upload(path, res.bytes, {
|
|
152
|
+
contentType: res.contentType ?? "application/pdf",
|
|
153
|
+
upsert: true,
|
|
154
|
+
});
|
|
155
|
+
if (upErr) {
|
|
156
|
+
perFo.set(ref.fulfillmentOrderId, { ok: false, status: 0, error: `Opslaan van de PDF mislukt: ${upErr.message}` });
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
perFo.set(ref.fulfillmentOrderId, {
|
|
160
|
+
ok: true,
|
|
161
|
+
status: res.status,
|
|
162
|
+
storagePath: path,
|
|
163
|
+
contentType: res.contentType ?? "application/pdf",
|
|
164
|
+
byteSize: res.bytes.byteLength,
|
|
165
|
+
});
|
|
122
166
|
}
|
|
123
|
-
//
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
167
|
+
// 4. delivery_notes bijwerken per code (dus per afleverbrief-regel).
|
|
168
|
+
for (const ref of refs) {
|
|
169
|
+
const key = `floriday:${ref.fulfillmentOrderId}:${ref.code}`;
|
|
170
|
+
const fetched = perFo.get(ref.fulfillmentOrderId);
|
|
171
|
+
const existing = stored.get(key);
|
|
172
|
+
const row = {
|
|
173
|
+
order_id: orderId,
|
|
174
|
+
order_number: orderNumber,
|
|
175
|
+
source: "floriday",
|
|
176
|
+
connection_id: ref.connectionId,
|
|
177
|
+
fulfillment_order_id: ref.fulfillmentOrderId,
|
|
178
|
+
label_code: ref.code,
|
|
179
|
+
letter: ref.letter,
|
|
180
|
+
load_carrier_index: ref.loadCarrierIndex,
|
|
181
|
+
load_carrier_type: ref.loadCarrierType,
|
|
182
|
+
packages: ref.packages,
|
|
183
|
+
storage_bucket: BUCKET,
|
|
184
|
+
};
|
|
185
|
+
if (fetched?.ok) {
|
|
186
|
+
Object.assign(row, {
|
|
187
|
+
storage_path: fetched.storagePath,
|
|
188
|
+
content_type: fetched.contentType,
|
|
189
|
+
byte_size: fetched.byteSize,
|
|
190
|
+
status: "available",
|
|
191
|
+
http_status: fetched.status,
|
|
192
|
+
error_message: null,
|
|
147
193
|
fetched_at: new Date().toISOString(),
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
else if (fetched) {
|
|
197
|
+
Object.assign(row, {
|
|
198
|
+
storage_path: existing?.storage_path ?? null,
|
|
199
|
+
status: existing?.storage_path ? "available" : "error",
|
|
200
|
+
http_status: fetched.status,
|
|
201
|
+
error_message: fetched.error ?? null,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
else if (existing) {
|
|
205
|
+
Object.assign(row, {
|
|
206
|
+
storage_path: existing.storage_path,
|
|
207
|
+
content_type: existing.content_type,
|
|
208
|
+
byte_size: existing.byte_size,
|
|
209
|
+
status: "available",
|
|
210
|
+
});
|
|
153
211
|
}
|
|
212
|
+
const { data: saved } = await supabaseAdmin
|
|
213
|
+
.from("delivery_notes")
|
|
214
|
+
.upsert(row, { onConflict: "fulfillment_order_id,label_code" })
|
|
215
|
+
.select("*")
|
|
216
|
+
.maybeSingle();
|
|
217
|
+
stored.set(key, saved ?? { ...existing, ...row });
|
|
154
218
|
}
|
|
155
|
-
//
|
|
156
|
-
const { supabaseAdmin } = await import("../integrations/supabase/client.server");
|
|
219
|
+
// 5. Resultaat opbouwen (Floriday + engine-brieven van deze order).
|
|
157
220
|
const labels = [];
|
|
158
|
-
for (const
|
|
159
|
-
const cache = cacheMap.get(`${ref.fulfillmentOrderId}:${ref.code}`);
|
|
221
|
+
for (const r of stored.values()) {
|
|
160
222
|
let signedUrl = null;
|
|
161
|
-
if (
|
|
223
|
+
if (r.storage_path) {
|
|
162
224
|
const { data: signed } = await supabaseAdmin.storage
|
|
163
|
-
.from(BUCKET)
|
|
164
|
-
.createSignedUrl(
|
|
225
|
+
.from(r.storage_bucket ?? BUCKET)
|
|
226
|
+
.createSignedUrl(r.storage_path, 600);
|
|
165
227
|
signedUrl = signed?.signedUrl ?? null;
|
|
166
228
|
}
|
|
167
229
|
labels.push({
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
230
|
+
source: (r.source ?? "floriday"),
|
|
231
|
+
code: r.label_code ?? null,
|
|
232
|
+
letter: r.letter ?? null,
|
|
233
|
+
loadCarrierIndex: Number(r.load_carrier_index ?? 0),
|
|
234
|
+
loadCarrierType: r.load_carrier_type ?? null,
|
|
235
|
+
packages: Number(r.packages ?? 0),
|
|
236
|
+
fulfillmentOrderId: r.fulfillment_order_id ?? null,
|
|
237
|
+
orderNumber: r.order_number ?? orderNumber,
|
|
174
238
|
hasPdf: !!signedUrl,
|
|
175
239
|
signedUrl,
|
|
240
|
+
status: signedUrl ? "available" : (r.status ?? "pending"),
|
|
241
|
+
httpStatus: r.http_status ?? null,
|
|
242
|
+
errorMessage: signedUrl ? null : (r.error_message ?? null),
|
|
176
243
|
});
|
|
177
244
|
}
|
|
178
|
-
labels.sort((a, b) => a.loadCarrierIndex - b.loadCarrierIndex ||
|
|
179
|
-
|
|
180
|
-
|
|
245
|
+
labels.sort((a, b) => a.loadCarrierIndex - b.loadCarrierIndex || (a.letter ?? "").localeCompare(b.letter ?? ""));
|
|
246
|
+
return { labels, orderNumber };
|
|
247
|
+
});
|
|
248
|
+
/**
|
|
249
|
+
* Registreert een afleverbrief die buiten Floriday is gemaakt
|
|
250
|
+
* (HO/handmatige en MO/mail-bestellingen, gegenereerd door de logistieke engine).
|
|
251
|
+
* De PDF wordt in dezelfde bucket opgeslagen en aan ons ordernummer gekoppeld.
|
|
252
|
+
*/
|
|
253
|
+
const RegisterSchema = z.object({
|
|
254
|
+
orderId: z.string().min(1),
|
|
255
|
+
pdfBase64: z.string().min(1),
|
|
256
|
+
code: z.string().min(1).optional(),
|
|
257
|
+
letter: z.string().optional(),
|
|
258
|
+
loadCarrierIndex: z.number().int().optional(),
|
|
259
|
+
loadCarrierType: z.string().optional(),
|
|
260
|
+
packages: z.number().int().optional(),
|
|
261
|
+
});
|
|
262
|
+
export const registerDeliveryNote = createServerFn({ method: "POST" })
|
|
263
|
+
.middleware([requireSupabaseAuth])
|
|
264
|
+
.inputValidator((d) => RegisterSchema.parse(d))
|
|
265
|
+
.handler(async ({ data, context }) => {
|
|
266
|
+
const supabase = context.supabase;
|
|
267
|
+
const order = await resolveOrderRow(supabase, data.orderId);
|
|
268
|
+
const { supabaseAdmin } = await import("../integrations/supabase/client.server");
|
|
269
|
+
const binair = atob(data.pdfBase64);
|
|
270
|
+
const bytes = new Uint8Array(binair.length);
|
|
271
|
+
for (let i = 0; i < binair.length; i++)
|
|
272
|
+
bytes[i] = binair.charCodeAt(i);
|
|
273
|
+
const code = data.code ?? order.order_number ?? order.id;
|
|
274
|
+
const path = `engine/${order.id}/${code}.pdf`;
|
|
275
|
+
const { error: upErr } = await supabaseAdmin.storage.from(BUCKET).upload(path, bytes, {
|
|
276
|
+
contentType: "application/pdf",
|
|
277
|
+
upsert: true,
|
|
278
|
+
});
|
|
279
|
+
if (upErr)
|
|
280
|
+
throw new Error(`Opslaan van de afleverbrief mislukt: ${upErr.message}`);
|
|
281
|
+
const { error } = await supabaseAdmin.from("delivery_notes").insert({
|
|
282
|
+
order_id: order.id,
|
|
283
|
+
order_number: order.order_number,
|
|
284
|
+
source: "engine",
|
|
285
|
+
label_code: code,
|
|
286
|
+
letter: data.letter ?? null,
|
|
287
|
+
load_carrier_index: data.loadCarrierIndex ?? 0,
|
|
288
|
+
load_carrier_type: data.loadCarrierType ?? null,
|
|
289
|
+
packages: data.packages ?? 0,
|
|
290
|
+
storage_bucket: BUCKET,
|
|
291
|
+
storage_path: path,
|
|
292
|
+
content_type: "application/pdf",
|
|
293
|
+
byte_size: bytes.byteLength,
|
|
294
|
+
status: "available",
|
|
295
|
+
fetched_at: new Date().toISOString(),
|
|
296
|
+
});
|
|
297
|
+
if (error)
|
|
298
|
+
throw new Error(`Afleverbrief opslaan mislukt: ${error.message}`);
|
|
299
|
+
return { ok: true, orderNumber: order.order_number, storagePath: path };
|
|
181
300
|
});
|