@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.
Files changed (89) hide show
  1. package/dist-lib/components/karindeling/AfmetingenTab.d.ts +6 -0
  2. package/dist-lib/components/karindeling/AfmetingenTab.d.ts.map +1 -0
  3. package/dist-lib/components/karindeling/AfmetingenTab.js +128 -0
  4. package/dist-lib/components/karindeling/KarindelingPage.d.ts +2 -0
  5. package/dist-lib/components/karindeling/KarindelingPage.d.ts.map +1 -0
  6. package/dist-lib/components/karindeling/KarindelingPage.js +102 -0
  7. package/dist-lib/components/verkoop/OrderControlStatusCard.d.ts +6 -0
  8. package/dist-lib/components/verkoop/OrderControlStatusCard.d.ts.map +1 -0
  9. package/dist-lib/components/verkoop/OrderControlStatusCard.js +41 -0
  10. package/dist-lib/components/verkoop/OrderKarindelingCard.d.ts.map +1 -1
  11. package/dist-lib/components/verkoop/OrderKarindelingCard.js +83 -37
  12. package/dist-lib/components/verkoop/SalesOrderDetailPage.d.ts.map +1 -1
  13. package/dist-lib/components/verkoop/SalesOrderDetailPage.js +74 -8
  14. package/dist-lib/components/verkoop/SalesOrderDetailView.d.ts +2 -1
  15. package/dist-lib/components/verkoop/SalesOrderDetailView.d.ts.map +1 -1
  16. package/dist-lib/components/verkoop/SalesOrderDetailView.js +3 -2
  17. package/dist-lib/components/verkoop/SalesOrdersTable.d.ts.map +1 -1
  18. package/dist-lib/components/verkoop/SalesOrdersTable.js +40 -5
  19. package/dist-lib/components/verkoop/VerkoopOrdersPage.d.ts.map +1 -1
  20. package/dist-lib/components/verkoop/VerkoopOrdersPage.js +19 -3
  21. package/dist-lib/index.d.ts +1 -0
  22. package/dist-lib/index.d.ts.map +1 -1
  23. package/dist-lib/index.js +12 -1
  24. package/dist-lib/integrations/supabase/auth-middleware.d.ts +1536 -581
  25. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
  26. package/dist-lib/integrations/supabase/client.d.ts +1536 -581
  27. package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
  28. package/dist-lib/integrations/supabase/client.js +24 -9
  29. package/dist-lib/integrations/supabase/client.server.d.ts +1536 -581
  30. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  31. package/dist-lib/integrations/supabase/types.d.ts +1543 -562
  32. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  33. package/dist-lib/integrations/supabase/types.js +3 -9
  34. package/dist-lib/lib/cart-lock.functions.d.ts +1536 -581
  35. package/dist-lib/lib/cart-lock.functions.d.ts.map +1 -1
  36. package/dist-lib/lib/cart-planner.d.ts +9 -1
  37. package/dist-lib/lib/cart-planner.d.ts.map +1 -1
  38. package/dist-lib/lib/cart-planner.js +21 -4
  39. package/dist-lib/lib/cart-planning-settings.functions.d.ts +140842 -0
  40. package/dist-lib/lib/cart-planning-settings.functions.d.ts.map +1 -0
  41. package/dist-lib/lib/cart-planning-settings.functions.js +375 -0
  42. package/dist-lib/lib/cart-replan.functions.d.ts +15811 -1082
  43. package/dist-lib/lib/cart-replan.functions.d.ts.map +1 -1
  44. package/dist-lib/lib/cart-replan.functions.js +85 -27
  45. package/dist-lib/lib/create-order.functions.d.ts +19021 -7561
  46. package/dist-lib/lib/create-order.functions.d.ts.map +1 -1
  47. package/dist-lib/lib/floriday-auto-fulfillment.functions.d.ts +4558 -1693
  48. package/dist-lib/lib/floriday-auto-fulfillment.functions.d.ts.map +1 -1
  49. package/dist-lib/lib/floriday-auto-fulfillment.server.js +1 -1
  50. package/dist-lib/lib/floriday-central-token.server.d.ts +12 -0
  51. package/dist-lib/lib/floriday-central-token.server.d.ts.map +1 -0
  52. package/dist-lib/lib/floriday-central-token.server.js +58 -0
  53. package/dist-lib/lib/floriday-gateway.server.d.ts +2 -2
  54. package/dist-lib/lib/floriday-gateway.server.d.ts.map +1 -1
  55. package/dist-lib/lib/floriday-gateway.server.js +10 -37
  56. package/dist-lib/lib/floriday-logistic-labels.functions.d.ts +1536 -581
  57. package/dist-lib/lib/floriday-logistic-labels.functions.d.ts.map +1 -1
  58. package/dist-lib/lib/floriday-logistic-labels.functions.js +14 -4
  59. package/dist-lib/lib/floriday-mirror.functions.d.ts +12806 -0
  60. package/dist-lib/lib/floriday-mirror.functions.d.ts.map +1 -0
  61. package/dist-lib/lib/floriday-mirror.functions.js +278 -0
  62. package/dist-lib/lib/floriday-public.functions.d.ts +10989 -4301
  63. package/dist-lib/lib/floriday-public.functions.d.ts.map +1 -1
  64. package/dist-lib/lib/floriday-public.functions.js +114 -38
  65. package/dist-lib/lib/floriday-sync.d.ts +0 -1
  66. package/dist-lib/lib/floriday-sync.d.ts.map +1 -1
  67. package/dist-lib/lib/floriday-sync.js +1 -1
  68. package/dist-lib/lib/floriday-writes.functions.d.ts +7772 -2997
  69. package/dist-lib/lib/floriday-writes.functions.d.ts.map +1 -1
  70. package/dist-lib/lib/order-buffers.functions.d.ts +38420 -0
  71. package/dist-lib/lib/order-buffers.functions.d.ts.map +1 -0
  72. package/dist-lib/lib/order-buffers.functions.js +244 -0
  73. package/dist-lib/lib/order-shipments.functions.d.ts +6165 -2345
  74. package/dist-lib/lib/order-shipments.functions.d.ts.map +1 -1
  75. package/dist-lib/lib/salesorders-mapping.d.ts +5 -0
  76. package/dist-lib/lib/salesorders-mapping.d.ts.map +1 -1
  77. package/dist-lib/lib/salesorders-mapping.js +8 -1
  78. package/dist-lib/lib/salesorders.functions.d.ts +30443 -1979
  79. package/dist-lib/lib/salesorders.functions.d.ts.map +1 -1
  80. package/dist-lib/lib/salesorders.functions.js +307 -0
  81. package/dist-lib/lib/tradeitems.functions.d.ts +1536 -581
  82. package/dist-lib/lib/tradeitems.functions.d.ts.map +1 -1
  83. package/dist-lib/lib/useSalesOrderDetailQuery.d.ts +2 -0
  84. package/dist-lib/lib/useSalesOrderDetailQuery.d.ts.map +1 -0
  85. package/dist-lib/lib/useSalesOrderDetailQuery.js +50 -0
  86. package/dist-lib/lib/useSalesOrdersQuery.d.ts +2 -2
  87. package/dist-lib/lib/useSalesOrdersQuery.d.ts.map +1 -1
  88. package/dist-lib/lib/useSalesOrdersQuery.js +139 -10
  89. 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
+ });