@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
@@ -7,19 +7,21 @@ import { createServerFn } from "@tanstack/react-start";
7
7
  import { z } from "zod";
8
8
  import { requireSupabaseAuth } from "../integrations/supabase/auth-middleware";
9
9
  import { CART_PLANNER_VERSION, planCarts, } from "./cart-planner";
10
- async function replanOrderInternal(orderId) {
10
+ import { resolveBufferForOrderInternal } from "./order-buffers.functions";
11
+ export async function replanBufferInternal(bufferId) {
11
12
  const { supabaseAdmin } = await import("../integrations/supabase/client.server");
12
- // Order-metadata ophalen (voor FO-detectie / packingConfiguration fallback).
13
- const { data: orderRow } = await supabaseAdmin
13
+ const { data: orders } = await supabaseAdmin
14
14
  .from("orders")
15
15
  .select("id, custom_fields, plan_locked_at")
16
- .eq("id", orderId)
17
- .maybeSingle();
18
- // Als de order al vergrendeld is (eerste pakbon geprint), niets doen.
19
- if (orderRow?.plan_locked_at) {
16
+ .eq("buffer_id", bufferId)
17
+ .is("deleted_at", null);
18
+ const orderRows = (orders ?? []);
19
+ const orderIds = orderRows.map((o) => o.id);
20
+ if (orderRows.some((o) => o.plan_locked_at)) {
20
21
  return {
21
22
  ok: true,
22
- orderId,
23
+ bufferId,
24
+ orderIds,
23
25
  cartsCreated: 0,
24
26
  replacedManualCount: 0,
25
27
  usedFloridayPacking: false,
@@ -27,13 +29,11 @@ async function replanOrderInternal(orderId) {
27
29
  skipped: "locked",
28
30
  };
29
31
  }
30
- const custom = orderRow?.custom_fields ?? {};
31
- const floridayPacking = custom?.floriday_packing ?? null;
32
- // Items + belading uit products-tabel.
32
+ // Items van alle orders in de buffer.
33
33
  const { data: items, error: itErr } = await supabaseAdmin
34
34
  .from("order_items")
35
- .select("id, product_id, product_name, quantity, products(plants_per_crate, crates_per_layer, layers_per_cart)")
36
- .eq("order_id", orderId);
35
+ .select("id, order_id, product_id, product_name, quantity, products(plants_per_crate, crates_per_layer, layers_per_cart)")
36
+ .in("order_id", orderIds.length > 0 ? orderIds : ["00000000-0000-0000-0000-000000000000"]);
37
37
  if (itErr)
38
38
  throw new Error(itErr.message);
39
39
  const inputs = (items ?? []).map((it) => {
@@ -48,26 +48,33 @@ async function replanOrderInternal(orderId) {
48
48
  layers_per_cart: Math.max(1, Number(prod.layers_per_cart ?? 1)),
49
49
  };
50
50
  });
51
- // Bestaande karren tellen voordat we alles wissen (voor waarschuwing).
51
+ // Item → order-map voor het toewijzen van cart.order_id bij homogene karren.
52
+ const itemToOrder = new Map();
53
+ for (const it of items ?? []) {
54
+ itemToOrder.set(it.id, it.order_id);
55
+ }
56
+ // Bestaande karren in de buffer tellen (voor waarschuwing) en wissen.
52
57
  const { data: existingCarts } = await supabaseAdmin
53
58
  .from("order_carts")
54
59
  .select("id, source")
55
- .eq("order_id", orderId);
60
+ .eq("buffer_id", bufferId);
56
61
  const replacedManualCount = (existingCarts ?? []).filter((c) => c.source === "manual").length;
57
- // Alles wegvegen — cascade wist order_cart_items.
58
62
  const { error: delErr } = await supabaseAdmin
59
63
  .from("order_carts")
60
64
  .delete()
61
- .eq("order_id", orderId);
65
+ .eq("buffer_id", bufferId);
62
66
  if (delErr)
63
67
  throw new Error(delErr.message);
64
- // FO-fallback: gebruik Floriday packingConfiguration wanneer volledig aanwezig.
68
+ // Floriday-packingConfiguration-fallback: alleen als de buffer precies één
69
+ // order bevat én die order een volledig Floriday-packingConfiguration heeft.
65
70
  let usedFloridayPacking = false;
66
71
  let plannedCarts = [];
67
72
  const warnings = [];
68
- const isFo = custom?.source === "floriday" || floridayPacking?.pieces_per_package;
73
+ const solo = orderRows.length === 1 ? orderRows[0] : null;
74
+ const soloCustom = solo?.custom_fields ?? {};
75
+ const floridayPacking = soloCustom?.floriday_packing ?? null;
76
+ const isFo = solo && (soloCustom?.source === "floriday" || floridayPacking?.pieces_per_package);
69
77
  if (isFo && floridayPacking && Array.isArray(floridayPacking.carts)) {
70
- // Verwacht formaat: { carts: [{ items: [{ order_item_id, crates, plants_per_crate, crates_per_layer, layers_per_cart }] }] }
71
78
  usedFloridayPacking = true;
72
79
  plannedCarts = floridayPacking.carts.map((c, idx) => {
73
80
  const cItems = (c.items ?? []).map((i) => ({
@@ -93,17 +100,36 @@ async function replanOrderInternal(orderId) {
93
100
  });
94
101
  }
95
102
  else {
96
- const result = planCarts(inputs);
103
+ const [{ data: settings }, { data: overrides }] = await Promise.all([
104
+ supabaseAdmin.from("cart_planning_settings").select("*").eq("id", 1).maybeSingle(),
105
+ supabaseAdmin.from("cart_planning_product_overrides").select("product_id, never_mix"),
106
+ ]);
107
+ const neverMix = new Set((overrides ?? [])
108
+ .filter((o) => o.never_mix && o.product_id)
109
+ .map((o) => o.product_id));
110
+ const result = planCarts(inputs, {
111
+ maxPartySharePerLayerPct: settings?.max_party_share_per_layer_pct ?? 50,
112
+ maxBeladingenPerLayer: settings?.max_beladingen_per_layer ?? 2,
113
+ neverMixProductIds: neverMix,
114
+ });
97
115
  plannedCarts = result.carts;
98
116
  warnings.push(...result.warnings);
99
117
  }
100
- // Wegschrijven.
101
118
  let cartsCreated = 0;
102
119
  for (const cart of plannedCarts) {
120
+ // Bepaal cart.order_id: null bij mix van orders, anders die ene order.
121
+ const orderIdsOnCart = new Set();
122
+ for (const i of cart.items) {
123
+ const oid = itemToOrder.get(i.order_item_id);
124
+ if (oid)
125
+ orderIdsOnCart.add(oid);
126
+ }
127
+ const singleOrderId = orderIdsOnCart.size === 1 ? [...orderIdsOnCart][0] : null;
103
128
  const { data: inserted, error: cErr } = await supabaseAdmin
104
129
  .from("order_carts")
105
130
  .insert({
106
- order_id: orderId,
131
+ order_id: singleOrderId,
132
+ buffer_id: bufferId,
107
133
  cart_number: cart.cart_number,
108
134
  is_auto: true,
109
135
  is_complete: cart.is_complete,
@@ -139,13 +165,28 @@ async function replanOrderInternal(orderId) {
139
165
  }
140
166
  return {
141
167
  ok: true,
142
- orderId,
168
+ bufferId,
169
+ orderIds,
143
170
  cartsCreated,
144
171
  replacedManualCount,
145
172
  usedFloridayPacking,
146
173
  warnings,
147
174
  };
148
175
  }
176
+ async function replanOrderInternal(orderId) {
177
+ // Resolve (of maak) de buffer voor de order en plan de hele buffer opnieuw.
178
+ const bufferId = await resolveBufferForOrderInternal(orderId);
179
+ const res = await replanBufferInternal(bufferId);
180
+ return {
181
+ ok: res.ok,
182
+ orderId,
183
+ cartsCreated: res.cartsCreated,
184
+ replacedManualCount: res.replacedManualCount,
185
+ usedFloridayPacking: res.usedFloridayPacking,
186
+ warnings: res.warnings,
187
+ skipped: res.skipped,
188
+ };
189
+ }
149
190
  export async function replanOrderCartsFromCron(orderId) {
150
191
  return replanOrderInternal(orderId);
151
192
  }
@@ -190,14 +231,31 @@ export async function drainCartReplanQueue(limit = 50) {
190
231
  return { ok: failed === 0, processed, failed, results };
191
232
  }
192
233
  // ─── Lezen — voor de UI ─────────────────────────────────────────────────────
234
+ // Retourneert alle karren van de buffer waarin de order valt, zodat karren
235
+ // die items van meerdere orders bevatten volledig zichtbaar zijn.
193
236
  export const listOrderCarts = createServerFn({ method: "GET" })
194
237
  .middleware([requireSupabaseAuth])
195
238
  .inputValidator((input) => z.object({ orderId: z.string().uuid() }).parse(input))
196
239
  .handler(async ({ data, context }) => {
240
+ const { data: order } = await context.supabase
241
+ .from("orders")
242
+ .select("buffer_id")
243
+ .eq("id", data.orderId)
244
+ .maybeSingle();
245
+ const bufferId = order?.buffer_id;
246
+ if (!bufferId)
247
+ return { carts: [], bufferId: null };
197
248
  const { data: carts } = await context.supabase
198
249
  .from("order_carts")
199
- .select("id, cart_number, source, is_complete, occupancy_pct, total_layers_used, algorithm_version, notes, order_cart_items(id, order_item_id, product_id, product_name, crates, plants_per_crate, crates_per_layer, layers_per_cart, layer_fraction, layer_share_pct)")
200
- .eq("order_id", data.orderId)
250
+ .select("id, order_id, buffer_id, cart_number, source, is_complete, occupancy_pct, total_layers_used, algorithm_version, notes, order_cart_items(id, order_item_id, product_id, product_name, crates, plants_per_crate, crates_per_layer, layers_per_cart, layer_fraction, layer_share_pct)")
251
+ .eq("buffer_id", bufferId)
201
252
  .order("cart_number");
202
- return { carts: carts ?? [] };
253
+ return { carts: carts ?? [], bufferId };
254
+ });
255
+ export const replanBufferForOrder = createServerFn({ method: "POST" })
256
+ .middleware([requireSupabaseAuth])
257
+ .inputValidator((input) => z.object({ orderId: z.string().uuid() }).parse(input))
258
+ .handler(async ({ data }) => {
259
+ const bufferId = await resolveBufferForOrderInternal(data.orderId);
260
+ return replanBufferInternal(bufferId);
203
261
  });