@flowselections/floriday-afhandeling-module 1.0.40 → 1.0.42

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 (40) hide show
  1. package/dist-lib/components/afhandeling/ControlePage.d.ts.map +1 -1
  2. package/dist-lib/components/afhandeling/ControlePage.js +86 -10
  3. package/dist-lib/components/afhandeling/DagDetailDialog.d.ts.map +1 -1
  4. package/dist-lib/components/afhandeling/DagDetailDialog.js +4 -3
  5. package/dist-lib/components/afhandeling/VervoerdersPage.js +1 -1
  6. package/dist-lib/components/afhandeling/VerzetOrderDialog.js +1 -1
  7. package/dist-lib/components/afhandeling/WeekAgendaView.d.ts.map +1 -1
  8. package/dist-lib/components/afhandeling/WeekAgendaView.js +38 -45
  9. package/dist-lib/hooks/useCartIndex.d.ts +11 -0
  10. package/dist-lib/hooks/useCartIndex.d.ts.map +1 -0
  11. package/dist-lib/hooks/useCartIndex.js +56 -0
  12. package/dist-lib/hooks/useConsistencyCheck.d.ts +8 -0
  13. package/dist-lib/hooks/useConsistencyCheck.d.ts.map +1 -0
  14. package/dist-lib/hooks/useConsistencyCheck.js +22 -0
  15. package/dist-lib/hooks/useOrderPlanning.d.ts.map +1 -1
  16. package/dist-lib/hooks/useOrderPlanning.js +6 -2
  17. package/dist-lib/hooks/usePickAgenda.d.ts +32 -0
  18. package/dist-lib/hooks/usePickAgenda.d.ts.map +1 -0
  19. package/dist-lib/hooks/usePickAgenda.js +75 -0
  20. package/dist-lib/integrations/supabase/auth-middleware.d.ts +1342 -747
  21. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
  22. package/dist-lib/integrations/supabase/client.server.d.ts +1342 -747
  23. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  24. package/dist-lib/integrations/supabase/client.server.js +1 -1
  25. package/dist-lib/integrations/supabase/moduleClient.d.ts +1342 -747
  26. package/dist-lib/integrations/supabase/moduleClient.d.ts.map +1 -1
  27. package/dist-lib/integrations/supabase/types.d.ts +1354 -775
  28. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  29. package/dist-lib/lib/afhandelingSettings.functions.d.ts +2501 -1307
  30. package/dist-lib/lib/afhandelingSettings.functions.d.ts.map +1 -1
  31. package/dist-lib/lib/carriers.functions.d.ts +6356 -3381
  32. package/dist-lib/lib/carriers.functions.d.ts.map +1 -1
  33. package/dist-lib/lib/cartAssignments.functions.d.ts +6356 -3381
  34. package/dist-lib/lib/cartAssignments.functions.d.ts.map +1 -1
  35. package/dist-lib/lib/cartControl.functions.d.ts +12821 -6902
  36. package/dist-lib/lib/cartControl.functions.d.ts.map +1 -1
  37. package/dist-lib/lib/cartControl.functions.js +92 -127
  38. package/dist-lib/lib/floriday.functions.d.ts +1345 -748
  39. package/dist-lib/lib/floriday.functions.d.ts.map +1 -1
  40. package/package.json +1 -1
@@ -7,7 +7,6 @@ function toIso(d) {
7
7
  const day = String(d.getDate()).padStart(2, "0");
8
8
  return `${y}-${m}-${day}`;
9
9
  }
10
- const APPROVED_STATUSES = new Set(["ready", "shipped", "delivered"]);
11
10
  async function loadControlPlanningSettings(supabase, userId) {
12
11
  const { data: settings } = await supabase
13
12
  .from("afhandeling_settings")
@@ -20,126 +19,101 @@ async function loadControlPlanningSettings(supabase, userId) {
20
19
  const minWorkdays = Math.max(0, Number(settings?.pick_days_before_transport ?? 1));
21
20
  return { pickWeekdays, minWorkdays };
22
21
  }
23
- /**
24
- * Karren van vandaag volgens de Logistics Engine.
25
- *
26
- * De Engine is leidend: alleen orders met een `load.compose`-taak waarvan
27
- * `planned_start` vandaag (Europe/Amsterdam) valt, staan op de controlelijst,
28
- * en het aantal karren komt uit `payload.loadCarriers` — nooit meer uit de
29
- * eigen stuks/fust-berekening.
30
- */
31
- function amsterdamDay(iso) {
32
- if (!iso)
33
- return null;
34
- const d = new Date(iso);
35
- if (Number.isNaN(d.getTime()))
36
- return null;
37
- return new Intl.DateTimeFormat("en-CA", {
38
- timeZone: "Europe/Amsterdam",
39
- year: "numeric",
40
- month: "2-digit",
41
- day: "2-digit",
42
- }).format(d);
22
+ export function controlCartKey(cart) {
23
+ return cart.cartNumberId ?? `${cart.orderSource}#${cart.orderId}#${cart.cartIndex}`;
43
24
  }
44
- async function loadEngineCartsForToday(supabase) {
45
- const today = amsterdamDay(new Date().toISOString());
46
- const { data, error } = await supabase
47
- .from("logistics_tasks")
48
- .select("order_ref, payload, planned_start, sequence, status")
49
- .eq("owner_module", "afhandeling")
50
- .eq("task_type", "load.compose")
51
- .in("status", ["planned", "ready", "in_progress"])
52
- .limit(1000);
25
+ async function loadControlCarts(supabase) {
26
+ const { data, error } = await supabase.rpc("control_get_todays_carts");
53
27
  if (error)
54
28
  throw new Error(error.message);
55
- const map = new Map();
56
- for (const row of (data ?? [])) {
57
- const day = amsterdamDay(row.planned_start);
58
- if (!day || day !== today)
59
- continue;
60
- const carriers = Array.isArray(row.payload?.loadCarriers)
61
- ? row.payload.loadCarriers
62
- : [];
63
- const cartCount = carriers.length;
64
- const cartOrderRefs = carriers.map((c) => Array.isArray(c?.orderRefs) ? c.orderRefs.filter((r) => typeof r === "string") : []);
65
- const existing = map.get(row.order_ref);
66
- if (!existing || cartCount > existing.cartCount) {
67
- map.set(row.order_ref, {
68
- cartCount: Math.max(1, cartCount),
69
- pickDate: day,
70
- cartOrderRefs,
29
+ const rows = (data ?? []);
30
+ if (rows.length === 0)
31
+ return [];
32
+ // --- Verrijking 1: ordergegevens ---
33
+ const orderIds = Array.from(new Set(rows.map((r) => r.order_id).filter(Boolean)));
34
+ const orderMap = new Map();
35
+ if (orderIds.length > 0) {
36
+ const { data: orderRows } = await supabase
37
+ .from("orders")
38
+ .select("id, order_number, customer_name, delivery_date")
39
+ .in("id", orderIds);
40
+ for (const o of (orderRows ?? [])) {
41
+ orderMap.set(o.id, {
42
+ orderNumber: o.order_number ?? "",
43
+ customerName: o.customer_name ?? "",
44
+ deliveryDate: o.delivery_date ?? null,
71
45
  });
72
46
  }
73
47
  }
74
- return map;
75
- }
76
- /** Alle nog niet goedgekeurde karren van vandaag, gefilterd op de Engine. */
77
- async function loadPendingControlOrders(supabase) {
78
- const { loadTodaysPickstationOrders } = await import("./pickstationOrders.server");
79
- const [orders, engine] = await Promise.all([
80
- loadTodaysPickstationOrders(),
81
- loadEngineCartsForToday(supabase),
82
- ]);
83
- const pending = orders.filter((o) => !APPROVED_STATUSES.has(o.status));
84
- const result = [];
85
- const seenSharedCarts = new Set();
86
- for (const o of pending) {
87
- const info = (o.orderNumber ? engine.get(o.orderNumber) : undefined) ?? engine.get(o.orderId);
88
- const refs = info?.cartOrderRefs[o.cartIndex - 1] ?? [];
89
- const orderNumbers = Array.from(new Set([o.orderNumber, ...refs].filter((v) => Boolean(v))));
90
- if (orderNumbers.length > 1) {
91
- // Kar met meerdere orders: maar één regel tonen.
92
- const key = `${[...orderNumbers].sort().join("|")}#${o.cartIndex}`;
93
- if (seenSharedCarts.has(key))
94
- continue;
95
- seenSharedCarts.add(key);
48
+ const extras = new Map();
49
+ try {
50
+ const { loadTodaysPickstationOrders } = await import("./pickstationOrders.server");
51
+ const psOrders = await loadTodaysPickstationOrders();
52
+ for (const o of psOrders) {
53
+ extras.set(`${o.orderId}#${o.cartIndex - 1}`, {
54
+ cartNumber: o.cartNumber,
55
+ carrierName: o.carrierName,
56
+ pickupDate: o.pickupDate,
57
+ pickupTime: o.pickupTime,
58
+ country: o.country,
59
+ cratesOnCart: o.cratesOnCart,
60
+ printedCount: o.printedCount,
61
+ orderNumbers: o.orderNumber ? [o.orderNumber] : [],
62
+ });
96
63
  }
97
- result.push({
98
- orderId: o.orderId,
99
- orderSource: o.orderSource,
100
- cartIndex: o.cartIndex,
101
- cartNumber: o.cartNumber,
102
- orderNumber: o.orderNumber,
64
+ }
65
+ catch {
66
+ // Verrijking is optioneel: zonder deze gegevens blijft de kar zichtbaar.
67
+ }
68
+ const carts = [];
69
+ const seen = new Set();
70
+ for (const r of rows) {
71
+ const orderSource = (r.order_source ?? "manual");
72
+ const cartNumberId = r.cart_number_id ?? null;
73
+ const key = controlCartKey({
74
+ cartNumberId,
75
+ orderSource,
76
+ orderId: r.order_id,
77
+ cartIndex: r.cart_index,
78
+ });
79
+ if (seen.has(key))
80
+ continue;
81
+ seen.add(key);
82
+ const order = orderMap.get(r.order_id);
83
+ const extra = extras.get(`${r.order_id}#${r.cart_index}`) ??
84
+ extras.get(`${r.order_id}#${r.cart_index - 1}`);
85
+ const orderNumber = order?.orderNumber ?? "";
86
+ const orderNumbers = Array.from(new Set([orderNumber, ...(extra?.orderNumbers ?? [])].filter(Boolean)));
87
+ carts.push({
88
+ cartNumberId,
89
+ cartNumber: r.cart_number ?? extra?.cartNumber ?? null,
90
+ orderId: r.order_id,
91
+ orderSource,
92
+ cartIndex: r.cart_index,
93
+ orderNumber,
103
94
  orderNumbers,
104
- customerName: o.customerName,
105
- carrierName: o.carrierName,
106
- deliveryDate: o.deliveryDate,
107
- pickupDate: o.pickupDate,
108
- pickupTime: o.pickupTime,
109
- country: o.country,
110
- cratesOnCart: o.cratesOnCart,
111
- pickDate: info?.pickDate ?? amsterdamDay(new Date().toISOString()),
112
- printedCount: o.printedCount,
113
- status: o.status,
95
+ customerName: order?.customerName ?? "",
96
+ carrierName: extra?.carrierName ?? null,
97
+ deliveryDate: order?.deliveryDate ?? null,
98
+ pickupDate: extra?.pickupDate ?? null,
99
+ pickupTime: extra?.pickupTime ?? null,
100
+ country: extra?.country ?? null,
101
+ cratesOnCart: extra?.cratesOnCart ?? null,
102
+ pickDate: r.pick_date,
103
+ printedCount: r.printed_today ? Math.max(1, extra?.printedCount ?? 1) : 0,
104
+ printedToday: Boolean(r.printed_today),
105
+ printedAt: r.printed_at ?? null,
106
+ status: r.status ?? "pending",
114
107
  });
115
108
  }
116
- return result;
109
+ return carts;
117
110
  }
118
- /** Haal alle karren op die vandaag gepickt / klaargezet hadden moeten worden. */
111
+ /** Haal alle karren op die vandaag gecontroleerd moeten worden (RPC is leidend). */
119
112
  export const getTodaysControlCarts = createServerFn({ method: "GET" })
120
113
  .middleware([requireSupabaseAuth])
121
114
  .handler(async ({ context }) => {
122
115
  const supabase = context.supabase;
123
- const orders = await loadPendingControlOrders(supabase);
124
- const carts = orders.map((o) => ({
125
- cartNumberId: null, // will be resolved below via cart_numbers lookup
126
- cartNumber: o.cartNumber,
127
- orderId: o.orderId,
128
- orderSource: o.orderSource,
129
- cartIndex: o.cartIndex - 1, // pickstation uses 1-based, DB is 0-based
130
- orderNumber: o.orderNumber,
131
- orderNumbers: o.orderNumbers,
132
- customerName: o.customerName,
133
- carrierName: o.carrierName,
134
- deliveryDate: o.deliveryDate,
135
- pickupDate: o.pickupDate,
136
- pickupTime: o.pickupTime,
137
- country: o.country,
138
- cratesOnCart: o.cratesOnCart,
139
- pickDate: o.pickDate,
140
- printedCount: o.printedCount,
141
- status: o.status,
142
- }));
116
+ const carts = await loadControlCarts(supabase);
143
117
  return { carts };
144
118
  });
145
119
  export const getControlRescheduleProposals = createServerFn({ method: "POST" })
@@ -147,13 +121,13 @@ export const getControlRescheduleProposals = createServerFn({ method: "POST" })
147
121
  .inputValidator((d) => d)
148
122
  .handler(async ({ data, context }) => {
149
123
  const supabase = context.supabase;
150
- const pendingOrders = await loadPendingControlOrders(supabase);
124
+ const pendingOrders = await loadControlCarts(supabase);
151
125
  const { pickWeekdays, minWorkdays } = await loadControlPlanningSettings(supabase, context.userId);
152
126
  const checkedSet = new Set(data.checkedCartKeys);
153
127
  const proposals = [];
154
128
  const blocked = [];
155
129
  for (const o of pendingOrders) {
156
- const key = `${o.orderSource}#${o.orderId}#${o.cartIndex - 1}`;
130
+ const key = controlCartKey(o);
157
131
  if (checkedSet.has(key))
158
132
  continue;
159
133
  const currentIso = o.pickDate || toIso(new Date());
@@ -181,11 +155,11 @@ export const getControlRescheduleProposals = createServerFn({ method: "POST" })
181
155
  }
182
156
  else {
183
157
  blocked.push({
184
- cartNumberId: null,
158
+ cartNumberId: o.cartNumberId,
185
159
  cartNumber: o.cartNumber,
186
160
  orderId: o.orderId,
187
161
  orderSource: o.orderSource,
188
- cartIndex: o.cartIndex - 1,
162
+ cartIndex: o.cartIndex,
189
163
  orderNumber: o.orderNumber,
190
164
  customerName: o.customerName,
191
165
  carrierName: o.carrierName,
@@ -202,8 +176,8 @@ export const submitControlSession = createServerFn({ method: "POST" })
202
176
  .inputValidator((d) => d)
203
177
  .handler(async ({ data, context }) => {
204
178
  const supabase = context.supabase;
205
- // 1) Laad alle karren van vandaag (Engine is leidend) + instellingen
206
- const pendingOrders = await loadPendingControlOrders(supabase);
179
+ // 1) Laad exact dezelfde karren als het scherm toont (RPC is leidend)
180
+ const pendingOrders = await loadControlCarts(supabase);
207
181
  const { pickWeekdays, minWorkdays } = await loadControlPlanningSettings(supabase, context.userId);
208
182
  // 2) Maak sessie aan
209
183
  const { data: session, error: sessErr } = await supabase
@@ -224,25 +198,16 @@ export const submitControlSession = createServerFn({ method: "POST" })
224
198
  const rescheduled = [];
225
199
  const blocked = [];
226
200
  let checkedCount = 0;
227
- // Lookup cart_numbers row ids
228
- const { data: cnRows } = await supabase
229
- .from("cart_numbers")
230
- .select("id, order_source, order_id, cart_index")
231
- .in("order_id", Array.from(new Set(pendingOrders.map((o) => o.orderId))));
232
- const cnMap = new Map();
233
- for (const r of (cnRows ?? [])) {
234
- cnMap.set(`${r.order_source}#${r.order_id}#${r.cart_index}`, r.id);
235
- }
236
201
  for (const o of pendingOrders) {
237
- const key = `${o.orderSource}#${o.orderId}#${o.cartIndex - 1}`;
238
- const cartNumberId = cnMap.get(key) ?? null;
202
+ const key = controlCartKey(o);
203
+ const cartNumberId = o.cartNumberId;
239
204
  const baseFields = {
240
205
  session_id: session.id,
241
206
  cart_number_id: cartNumberId,
242
207
  cart_number_label: o.cartNumber,
243
208
  order_id: o.orderId,
244
209
  order_source: o.orderSource,
245
- cart_index: o.cartIndex - 1,
210
+ cart_index: o.cartIndex,
246
211
  order_number: o.orderNumber,
247
212
  customer_name: o.customerName,
248
213
  carrier_name: o.carrierName,
@@ -254,7 +219,7 @@ export const submitControlSession = createServerFn({ method: "POST" })
254
219
  await supabase.rpc("pickstation_set_cart_status", {
255
220
  p_order_source: o.orderSource,
256
221
  p_order_id: o.orderId,
257
- p_cart_index: o.cartIndex - 1,
222
+ p_cart_index: o.cartIndex,
258
223
  p_status: "ready",
259
224
  });
260
225
  items.push({ ...baseFields, action: "checked" });
@@ -278,7 +243,7 @@ export const submitControlSession = createServerFn({ method: "POST" })
278
243
  .upsert({
279
244
  order_id: o.orderId,
280
245
  order_source: o.orderSource,
281
- cart_index: o.cartIndex - 1,
246
+ cart_index: o.cartIndex,
282
247
  pick_date: newIso,
283
248
  moved_from_date: toIso(new Date()),
284
249
  }, { onConflict: "order_id,order_source,cart_index" });
@@ -309,7 +274,7 @@ export const submitControlSession = createServerFn({ method: "POST" })
309
274
  cartNumber: o.cartNumber,
310
275
  orderId: o.orderId,
311
276
  orderSource: o.orderSource,
312
- cartIndex: o.cartIndex - 1,
277
+ cartIndex: o.cartIndex,
313
278
  orderNumber: o.orderNumber,
314
279
  customerName: o.customerName,
315
280
  carrierName: o.carrierName,