@flowselections/floriday-verkoop-module 1.0.20 → 1.0.24
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/karindeling/AfmetingenTab.d.ts +6 -0
- package/dist-lib/components/karindeling/AfmetingenTab.d.ts.map +1 -0
- package/dist-lib/components/karindeling/AfmetingenTab.js +128 -0
- package/dist-lib/components/karindeling/KarindelingPage.d.ts +2 -0
- package/dist-lib/components/karindeling/KarindelingPage.d.ts.map +1 -0
- package/dist-lib/components/karindeling/KarindelingPage.js +102 -0
- package/dist-lib/components/verkoop/OrderControlStatusCard.d.ts +6 -0
- package/dist-lib/components/verkoop/OrderControlStatusCard.d.ts.map +1 -0
- package/dist-lib/components/verkoop/OrderControlStatusCard.js +41 -0
- package/dist-lib/components/verkoop/OrderKarindelingCard.d.ts.map +1 -1
- package/dist-lib/components/verkoop/OrderKarindelingCard.js +83 -37
- package/dist-lib/components/verkoop/SalesOrderDetailPage.d.ts.map +1 -1
- package/dist-lib/components/verkoop/SalesOrderDetailPage.js +74 -8
- package/dist-lib/components/verkoop/SalesOrderDetailView.d.ts +2 -1
- package/dist-lib/components/verkoop/SalesOrderDetailView.d.ts.map +1 -1
- package/dist-lib/components/verkoop/SalesOrderDetailView.js +3 -2
- package/dist-lib/components/verkoop/SalesOrdersTable.d.ts.map +1 -1
- package/dist-lib/components/verkoop/SalesOrdersTable.js +40 -5
- package/dist-lib/components/verkoop/VerkoopOrdersPage.d.ts.map +1 -1
- package/dist-lib/components/verkoop/VerkoopOrdersPage.js +19 -3
- package/dist-lib/index.d.ts +1 -0
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +12 -1
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +1536 -581
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.d.ts +1536 -581
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.js +24 -9
- package/dist-lib/integrations/supabase/client.server.d.ts +1536 -581
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +1543 -562
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.js +3 -9
- package/dist-lib/lib/cart-lock.functions.d.ts +1536 -581
- package/dist-lib/lib/cart-lock.functions.d.ts.map +1 -1
- package/dist-lib/lib/cart-planner.d.ts +9 -1
- package/dist-lib/lib/cart-planner.d.ts.map +1 -1
- package/dist-lib/lib/cart-planner.js +21 -4
- package/dist-lib/lib/cart-planning-settings.functions.d.ts +140842 -0
- package/dist-lib/lib/cart-planning-settings.functions.d.ts.map +1 -0
- package/dist-lib/lib/cart-planning-settings.functions.js +375 -0
- package/dist-lib/lib/cart-replan.functions.d.ts +15811 -1082
- package/dist-lib/lib/cart-replan.functions.d.ts.map +1 -1
- package/dist-lib/lib/cart-replan.functions.js +85 -27
- package/dist-lib/lib/create-order.functions.d.ts +19021 -7561
- package/dist-lib/lib/create-order.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-auto-fulfillment.functions.d.ts +4558 -1693
- package/dist-lib/lib/floriday-auto-fulfillment.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-auto-fulfillment.server.js +1 -1
- package/dist-lib/lib/floriday-central-token.server.d.ts +12 -0
- package/dist-lib/lib/floriday-central-token.server.d.ts.map +1 -0
- package/dist-lib/lib/floriday-central-token.server.js +58 -0
- package/dist-lib/lib/floriday-gateway.server.d.ts +2 -2
- package/dist-lib/lib/floriday-gateway.server.d.ts.map +1 -1
- package/dist-lib/lib/floriday-gateway.server.js +10 -37
- package/dist-lib/lib/floriday-logistic-labels.functions.d.ts +1536 -581
- package/dist-lib/lib/floriday-logistic-labels.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-logistic-labels.functions.js +14 -4
- package/dist-lib/lib/floriday-mirror.functions.d.ts +12806 -0
- package/dist-lib/lib/floriday-mirror.functions.d.ts.map +1 -0
- package/dist-lib/lib/floriday-mirror.functions.js +278 -0
- package/dist-lib/lib/floriday-public.functions.d.ts +10989 -4301
- package/dist-lib/lib/floriday-public.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-public.functions.js +114 -38
- package/dist-lib/lib/floriday-sync.d.ts +0 -1
- package/dist-lib/lib/floriday-sync.d.ts.map +1 -1
- package/dist-lib/lib/floriday-sync.js +1 -1
- package/dist-lib/lib/floriday-writes.functions.d.ts +7772 -2997
- package/dist-lib/lib/floriday-writes.functions.d.ts.map +1 -1
- package/dist-lib/lib/order-buffers.functions.d.ts +38420 -0
- package/dist-lib/lib/order-buffers.functions.d.ts.map +1 -0
- package/dist-lib/lib/order-buffers.functions.js +244 -0
- package/dist-lib/lib/order-shipments.functions.d.ts +6165 -2345
- package/dist-lib/lib/order-shipments.functions.d.ts.map +1 -1
- package/dist-lib/lib/salesorders-mapping.d.ts +5 -0
- package/dist-lib/lib/salesorders-mapping.d.ts.map +1 -1
- package/dist-lib/lib/salesorders-mapping.js +8 -1
- package/dist-lib/lib/salesorders.functions.d.ts +30443 -1979
- package/dist-lib/lib/salesorders.functions.d.ts.map +1 -1
- package/dist-lib/lib/salesorders.functions.js +307 -0
- package/dist-lib/lib/tradeitems.functions.d.ts +1536 -581
- package/dist-lib/lib/tradeitems.functions.d.ts.map +1 -1
- package/dist-lib/lib/useSalesOrderDetailQuery.d.ts +2 -0
- package/dist-lib/lib/useSalesOrderDetailQuery.d.ts.map +1 -0
- package/dist-lib/lib/useSalesOrderDetailQuery.js +50 -0
- package/dist-lib/lib/useSalesOrdersQuery.d.ts +2 -2
- package/dist-lib/lib/useSalesOrdersQuery.d.ts.map +1 -1
- package/dist-lib/lib/useSalesOrdersQuery.js +139 -10
- package/package.json +5 -5
|
@@ -3,11 +3,34 @@
|
|
|
3
3
|
import { createServerFn } from "@tanstack/react-start";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { requireSupabaseAuth } from "../integrations/supabase/auth-middleware";
|
|
6
|
+
import { mapJsonbToSalesOrderDTO, } from "./salesorders-mapping";
|
|
6
7
|
import { loadActiveConnections, syncBySequence, } from "./floriday-sync";
|
|
7
8
|
const ENTITY_TYPE = "salesorders";
|
|
8
9
|
const MAX_ENDPOINT = "/sales-orders/current-max-sequence";
|
|
9
10
|
const SYNC_ENDPOINT_BASE = "/sales-orders/sync";
|
|
10
11
|
const CACHE_TABLE = "floriday_salesorders_cache";
|
|
12
|
+
function pickString(v) {
|
|
13
|
+
if (v == null)
|
|
14
|
+
return null;
|
|
15
|
+
if (typeof v === "string")
|
|
16
|
+
return v;
|
|
17
|
+
if (typeof v === "number")
|
|
18
|
+
return String(v);
|
|
19
|
+
if (Array.isArray(v)) {
|
|
20
|
+
for (const item of v) {
|
|
21
|
+
const s = pickString(item?.text ?? item?.value ?? item);
|
|
22
|
+
if (s)
|
|
23
|
+
return s;
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
if (typeof v === "object") {
|
|
28
|
+
return (v.nl ?? v.NL ?? v.en ?? v.EN ?? v.text ?? v.value ??
|
|
29
|
+
Object.values(v).find((x) => typeof x === "string") ??
|
|
30
|
+
null);
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
11
34
|
function mapSalesOrderRow(record, connectionId) {
|
|
12
35
|
return {
|
|
13
36
|
connection_id: connectionId,
|
|
@@ -61,6 +84,15 @@ async function runSalesOrdersSyncInternal() {
|
|
|
61
84
|
});
|
|
62
85
|
}
|
|
63
86
|
}
|
|
87
|
+
// Spiegel recent gewijzigde FO's naar de lokale orders-tabel zodat
|
|
88
|
+
// buffergroepering en gedeelde karren werken.
|
|
89
|
+
try {
|
|
90
|
+
const { mirrorFloridayOrdersFromCron } = await import("./floriday-mirror.functions");
|
|
91
|
+
await mirrorFloridayOrdersFromCron(500);
|
|
92
|
+
}
|
|
93
|
+
catch (mirrorErr) {
|
|
94
|
+
console.error("[floriday-mirror] failed", mirrorErr);
|
|
95
|
+
}
|
|
64
96
|
return { ok: results.every((r) => r.ok), results };
|
|
65
97
|
}
|
|
66
98
|
export async function runSalesOrdersSyncFromCron() {
|
|
@@ -180,3 +212,278 @@ export const diagnoseFloridayConnection = createServerFn({ method: "POST" })
|
|
|
180
212
|
syncState: state ?? null,
|
|
181
213
|
};
|
|
182
214
|
});
|
|
215
|
+
// ─── Detail read (bulletproof, per-order fetch) ───────────────────────────
|
|
216
|
+
// Vervangt de zware lijst-query op de detailpagina. Doet ~4 gerichte
|
|
217
|
+
// queries op geïndexeerde kolommen; elke neventabel-fetch is best-effort
|
|
218
|
+
// (try/catch) zodat één falende bron de detailweergave niet blokkeert.
|
|
219
|
+
const DetailInputSchema = z.object({ id: z.string().min(1) });
|
|
220
|
+
export const getSalesOrderDetail = createServerFn({ method: "POST" })
|
|
221
|
+
.middleware([requireSupabaseAuth])
|
|
222
|
+
.inputValidator((d) => DetailInputSchema.parse(d))
|
|
223
|
+
.handler(async ({ data, context }) => {
|
|
224
|
+
const supabase = context.supabase;
|
|
225
|
+
// 1) Actieve environment + connectie.
|
|
226
|
+
const envRes = await supabase
|
|
227
|
+
.from("floriday_settings")
|
|
228
|
+
.select("active_environment")
|
|
229
|
+
.eq("id", 1)
|
|
230
|
+
.maybeSingle();
|
|
231
|
+
const rawEnv = String(envRes.data?.active_environment ?? "staging");
|
|
232
|
+
const environment = rawEnv === "production" || rawEnv === "prod" || rawEnv === "live" ? "live" : "staging";
|
|
233
|
+
const connRes = await supabase
|
|
234
|
+
.from("floriday_connections")
|
|
235
|
+
.select("id, organization_name, label")
|
|
236
|
+
.eq("is_active", true)
|
|
237
|
+
.eq("environment", environment)
|
|
238
|
+
.limit(1);
|
|
239
|
+
const conn = (connRes.data ?? [])[0];
|
|
240
|
+
const sellerFallback = conn?.organization_name ?? conn?.label ?? null;
|
|
241
|
+
if (!conn?.id) {
|
|
242
|
+
return { order: null, sellerFallback, environment, bufferId: null, bufferSiblings: [] };
|
|
243
|
+
}
|
|
244
|
+
// 2) De order zelf uit de cache (gerichte lookup op indexed kolom).
|
|
245
|
+
const orderRes = await supabase
|
|
246
|
+
.from("floriday_salesorders_cache")
|
|
247
|
+
.select("floriday_id, data, controlled_at")
|
|
248
|
+
.eq("connection_id", conn.id)
|
|
249
|
+
.eq("floriday_id", data.id)
|
|
250
|
+
.maybeSingle();
|
|
251
|
+
if (orderRes.error) {
|
|
252
|
+
throw new Error(`Order ophalen faalde: ${orderRes.error.message}`);
|
|
253
|
+
}
|
|
254
|
+
const row = orderRes.data;
|
|
255
|
+
if (!row?.data) {
|
|
256
|
+
return { order: null, sellerFallback, environment, bufferId: null, bufferSiblings: [] };
|
|
257
|
+
}
|
|
258
|
+
const orderData = row.data;
|
|
259
|
+
const customerOrgId = String(orderData?.customerOrganizationId ?? "");
|
|
260
|
+
const tradeItemId = String(orderData?.tradeItemId ?? "");
|
|
261
|
+
// 3) Neventabellen in parallel — allemaal best-effort.
|
|
262
|
+
const [customerLocalRes, customerCacheRes, tradeItemRes, orderNumberRes] = await Promise.all([
|
|
263
|
+
customerOrgId
|
|
264
|
+
? supabase
|
|
265
|
+
.from("customers")
|
|
266
|
+
.select("id, company_name, commercial_name, city, postal_code, logo_url, floriday_organization_id, phone, phone_number, contact_person, custom_fields, gln, street, country")
|
|
267
|
+
.eq("floriday_organization_id", customerOrgId)
|
|
268
|
+
.limit(1)
|
|
269
|
+
.then((r) => r)
|
|
270
|
+
.catch((e) => ({ data: null, error: e }))
|
|
271
|
+
: Promise.resolve({ data: null, error: null }),
|
|
272
|
+
customerOrgId
|
|
273
|
+
? supabase
|
|
274
|
+
.from("floriday_customers_cache")
|
|
275
|
+
.select("organization_id, data")
|
|
276
|
+
.eq("organization_id", customerOrgId)
|
|
277
|
+
.maybeSingle()
|
|
278
|
+
.then((r) => r)
|
|
279
|
+
.catch((e) => ({ data: null, error: e }))
|
|
280
|
+
: Promise.resolve({ data: null, error: null }),
|
|
281
|
+
tradeItemId
|
|
282
|
+
? supabase
|
|
283
|
+
.from("floriday_trade_items_cache")
|
|
284
|
+
.select("floriday_id, data")
|
|
285
|
+
.eq("floriday_id", tradeItemId)
|
|
286
|
+
.maybeSingle()
|
|
287
|
+
.then((r) => r)
|
|
288
|
+
.catch((e) => ({ data: null, error: e }))
|
|
289
|
+
: Promise.resolve({ data: null, error: null }),
|
|
290
|
+
supabase
|
|
291
|
+
.from("floriday_order_number_map")
|
|
292
|
+
.select("floriday_id, order_number")
|
|
293
|
+
.eq("floriday_id", data.id)
|
|
294
|
+
.maybeSingle()
|
|
295
|
+
.then((r) => r)
|
|
296
|
+
.catch((e) => ({ data: null, error: e })),
|
|
297
|
+
]);
|
|
298
|
+
// 4) Bouw lookups met precies één klant en één trade-item.
|
|
299
|
+
const customerLookup = new Map();
|
|
300
|
+
const localC = (customerLocalRes?.data ?? null);
|
|
301
|
+
if (localC) {
|
|
302
|
+
customerLookup.set(customerOrgId, {
|
|
303
|
+
name: localC.commercial_name ?? localC.company_name ?? "Onbekende klant",
|
|
304
|
+
postalCode: localC.postal_code ?? "",
|
|
305
|
+
city: localC.city ?? "",
|
|
306
|
+
logoUrl: localC.logo_url ?? null,
|
|
307
|
+
raw: localC,
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
const cacheRow = (customerCacheRes?.data ?? null);
|
|
312
|
+
const d = cacheRow?.data ?? {};
|
|
313
|
+
if (cacheRow && customerOrgId) {
|
|
314
|
+
const addr = d.physicalAddress ?? d.mailingAddress ?? {};
|
|
315
|
+
customerLookup.set(customerOrgId, {
|
|
316
|
+
name: d.commercialName ?? d.name ?? "Onbekende klant",
|
|
317
|
+
postalCode: addr.postalCode ?? "",
|
|
318
|
+
city: addr.city ?? "",
|
|
319
|
+
logoUrl: d.logoUrl ?? null,
|
|
320
|
+
raw: d,
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
const tradeItemLookup = new Map();
|
|
325
|
+
const tiRow = (tradeItemRes?.data ?? null);
|
|
326
|
+
if (tiRow?.data && tradeItemId) {
|
|
327
|
+
const d = tiRow.data;
|
|
328
|
+
const photos = d.photos ?? d.images ?? d.tradeItemPhotos ?? [];
|
|
329
|
+
const firstPhotoRaw = Array.isArray(photos) && photos.length > 0
|
|
330
|
+
? (photos[0]?.url ?? photos[0]?.imageUrl ?? photos[0]?.href ?? photos[0])
|
|
331
|
+
: null;
|
|
332
|
+
tradeItemLookup.set(tradeItemId, {
|
|
333
|
+
name: pickString(d.name) ??
|
|
334
|
+
pickString(d.productName) ??
|
|
335
|
+
pickString(d.tradeItemName) ??
|
|
336
|
+
pickString(d.tradeItemTexts) ??
|
|
337
|
+
"Onbekend artikel",
|
|
338
|
+
imageUrl: pickString(firstPhotoRaw),
|
|
339
|
+
sku: pickString(d.vbnProductCode) ??
|
|
340
|
+
pickString(d.gtin) ??
|
|
341
|
+
pickString(d.articleCode),
|
|
342
|
+
raw: d,
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
// 5) Verrijk met order_number + controle-status zodat de mapping alles heeft.
|
|
346
|
+
const onRow = (orderNumberRes?.data ?? null);
|
|
347
|
+
const controlledAt = row.controlled_at ?? null;
|
|
348
|
+
const enrichedOrder = {
|
|
349
|
+
...orderData,
|
|
350
|
+
...(onRow?.order_number ? { orderNumber: String(onRow.order_number) } : {}),
|
|
351
|
+
__controlledAt: controlledAt,
|
|
352
|
+
};
|
|
353
|
+
const dto = mapJsonbToSalesOrderDTO(enrichedOrder, customerLookup, tradeItemLookup);
|
|
354
|
+
// 6) Buffer-siblings: zoek buffer_id via orders-tabel en verzamel alle
|
|
355
|
+
// verwante Floriday-orders. Zo werkt de detailweergave onafhankelijk
|
|
356
|
+
// van de (soms trage of gefilterde) lijst-query.
|
|
357
|
+
let bufferId = null;
|
|
358
|
+
const bufferSiblings = [];
|
|
359
|
+
try {
|
|
360
|
+
const ownRes = await supabase
|
|
361
|
+
.from("orders")
|
|
362
|
+
.select("buffer_id")
|
|
363
|
+
.eq("floriday_sales_order_id", data.id)
|
|
364
|
+
.maybeSingle();
|
|
365
|
+
bufferId = ownRes.data?.buffer_id ?? null;
|
|
366
|
+
if (bufferId) {
|
|
367
|
+
dto.bufferId = bufferId;
|
|
368
|
+
const sibRes = await supabase
|
|
369
|
+
.from("orders")
|
|
370
|
+
.select("floriday_sales_order_id")
|
|
371
|
+
.eq("buffer_id", bufferId)
|
|
372
|
+
.not("floriday_sales_order_id", "is", null);
|
|
373
|
+
const sibFoIds = (sibRes.data ?? [])
|
|
374
|
+
.map((r) => String(r.floriday_sales_order_id))
|
|
375
|
+
.filter((id) => id && id !== data.id);
|
|
376
|
+
if (sibFoIds.length > 0) {
|
|
377
|
+
const sibCacheRes = await supabase
|
|
378
|
+
.from("floriday_salesorders_cache")
|
|
379
|
+
.select("floriday_id, data, controlled_at")
|
|
380
|
+
.eq("connection_id", conn.id)
|
|
381
|
+
.in("floriday_id", sibFoIds);
|
|
382
|
+
const sibRows = (sibCacheRes.data ?? []);
|
|
383
|
+
// Verzamel extra klant/trade-item lookups voor de siblings.
|
|
384
|
+
const extraOrgIds = Array.from(new Set(sibRows
|
|
385
|
+
.map((r) => String(r?.data?.customerOrganizationId ?? ""))
|
|
386
|
+
.filter((id) => id && !customerLookup.has(id))));
|
|
387
|
+
const extraTiIds = Array.from(new Set(sibRows
|
|
388
|
+
.map((r) => String(r?.data?.tradeItemId ?? ""))
|
|
389
|
+
.filter((id) => id && !tradeItemLookup.has(id))));
|
|
390
|
+
const [extraCustLocal, extraCustCache, extraTi] = await Promise.all([
|
|
391
|
+
extraOrgIds.length
|
|
392
|
+
? supabase
|
|
393
|
+
.from("customers")
|
|
394
|
+
.select("id, company_name, commercial_name, city, postal_code, logo_url, floriday_organization_id")
|
|
395
|
+
.in("floriday_organization_id", extraOrgIds)
|
|
396
|
+
: Promise.resolve({ data: [] }),
|
|
397
|
+
extraOrgIds.length
|
|
398
|
+
? supabase
|
|
399
|
+
.from("floriday_customers_cache")
|
|
400
|
+
.select("organization_id, data")
|
|
401
|
+
.in("organization_id", extraOrgIds)
|
|
402
|
+
: Promise.resolve({ data: [] }),
|
|
403
|
+
extraTiIds.length
|
|
404
|
+
? supabase
|
|
405
|
+
.from("floriday_trade_items_cache")
|
|
406
|
+
.select("floriday_id, data")
|
|
407
|
+
.in("floriday_id", extraTiIds)
|
|
408
|
+
: Promise.resolve({ data: [] }),
|
|
409
|
+
]);
|
|
410
|
+
const localByOrg = new Map();
|
|
411
|
+
for (const c of (extraCustLocal.data ?? [])) {
|
|
412
|
+
localByOrg.set(String(c.floriday_organization_id), c);
|
|
413
|
+
}
|
|
414
|
+
for (const orgId of extraOrgIds) {
|
|
415
|
+
const localC = localByOrg.get(orgId);
|
|
416
|
+
if (localC) {
|
|
417
|
+
customerLookup.set(orgId, {
|
|
418
|
+
name: localC.commercial_name ?? localC.company_name ?? "Onbekende klant",
|
|
419
|
+
postalCode: localC.postal_code ?? "",
|
|
420
|
+
city: localC.city ?? "",
|
|
421
|
+
logoUrl: localC.logo_url ?? null,
|
|
422
|
+
raw: localC,
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
for (const c of (extraCustCache.data ?? [])) {
|
|
427
|
+
const orgId = String(c.organization_id);
|
|
428
|
+
if (customerLookup.has(orgId))
|
|
429
|
+
continue;
|
|
430
|
+
const d = c.data ?? {};
|
|
431
|
+
const addr = d.physicalAddress ?? d.mailingAddress ?? {};
|
|
432
|
+
customerLookup.set(orgId, {
|
|
433
|
+
name: d.commercialName ?? d.name ?? "Onbekende klant",
|
|
434
|
+
postalCode: addr.postalCode ?? "",
|
|
435
|
+
city: addr.city ?? "",
|
|
436
|
+
logoUrl: d.logoUrl ?? null,
|
|
437
|
+
raw: d,
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
for (const t of (extraTi.data ?? [])) {
|
|
441
|
+
const tid = String(t.floriday_id);
|
|
442
|
+
const d = t.data ?? {};
|
|
443
|
+
const photos = d.photos ?? d.images ?? d.tradeItemPhotos ?? [];
|
|
444
|
+
const firstPhotoRaw = Array.isArray(photos) && photos.length > 0
|
|
445
|
+
? (photos[0]?.url ?? photos[0]?.imageUrl ?? photos[0]?.href ?? photos[0])
|
|
446
|
+
: null;
|
|
447
|
+
tradeItemLookup.set(tid, {
|
|
448
|
+
name: pickString(d.name) ??
|
|
449
|
+
pickString(d.productName) ??
|
|
450
|
+
pickString(d.tradeItemName) ??
|
|
451
|
+
pickString(d.tradeItemTexts) ??
|
|
452
|
+
"Onbekend artikel",
|
|
453
|
+
imageUrl: pickString(firstPhotoRaw),
|
|
454
|
+
sku: pickString(d.vbnProductCode) ??
|
|
455
|
+
pickString(d.gtin) ??
|
|
456
|
+
pickString(d.articleCode),
|
|
457
|
+
raw: d,
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
for (const sr of sibRows) {
|
|
461
|
+
const sDto = mapJsonbToSalesOrderDTO({ ...sr.data, __controlledAt: sr.controlled_at ?? null }, customerLookup, tradeItemLookup);
|
|
462
|
+
sDto.bufferId = bufferId;
|
|
463
|
+
bufferSiblings.push(sDto);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
catch (err) {
|
|
469
|
+
console.warn("[getSalesOrderDetail] buffer-siblings lookup faalde:", err.message);
|
|
470
|
+
}
|
|
471
|
+
return { order: dto, sellerFallback, environment, bufferId, bufferSiblings };
|
|
472
|
+
});
|
|
473
|
+
// ─── Handmatige controle na orderpicken ───────────────────────────────────
|
|
474
|
+
const ControlInputSchema = z.object({
|
|
475
|
+
floridayId: z.string().min(1),
|
|
476
|
+
controlled: z.boolean(),
|
|
477
|
+
});
|
|
478
|
+
export const setSalesOrderControlled = createServerFn({ method: "POST" })
|
|
479
|
+
.middleware([requireSupabaseAuth])
|
|
480
|
+
.inputValidator((d) => ControlInputSchema.parse(d))
|
|
481
|
+
.handler(async ({ data, context }) => {
|
|
482
|
+
const { error } = await context.supabase.rpc("mark_salesorder_controlled", {
|
|
483
|
+
p_floriday_id: data.floridayId,
|
|
484
|
+
p_controlled: data.controlled,
|
|
485
|
+
});
|
|
486
|
+
if (error)
|
|
487
|
+
throw new Error(error.message);
|
|
488
|
+
return { ok: true };
|
|
489
|
+
});
|