@flowselections/floriday-afhandeling-module 1.0.50 → 1.0.54

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 (47) hide show
  1. package/dist-lib/components/afhandeling/ControlePage.js +1 -1
  2. package/dist-lib/components/afhandeling/DagDetailDialog.d.ts.map +1 -1
  3. package/dist-lib/components/afhandeling/DagDetailDialog.js +255 -89
  4. package/dist-lib/components/afhandeling/NuVersturenButton.d.ts +2 -2
  5. package/dist-lib/components/afhandeling/NuVersturenButton.d.ts.map +1 -1
  6. package/dist-lib/components/afhandeling/NuVersturenButton.js +22 -4
  7. package/dist-lib/components/afhandeling/ScanControleView.js +1 -1
  8. package/dist-lib/components/afhandeling/VervoerdersPage.js +1 -1
  9. package/dist-lib/components/afhandeling/VerzetOrderDialog.js +1 -1
  10. package/dist-lib/components/afhandeling/WeekAgendaView.d.ts.map +1 -1
  11. package/dist-lib/components/afhandeling/WeekAgendaView.js +4 -3
  12. package/dist-lib/components/afhandeling/WerkplekWaarschuwing.d.ts +9 -9
  13. package/dist-lib/components/afhandeling/WerkplekWaarschuwing.js +28 -28
  14. package/dist-lib/components/ui/responsive-dialog.js +1 -1
  15. package/dist-lib/hooks/useKnownOrders.d.ts +1 -0
  16. package/dist-lib/hooks/useKnownOrders.d.ts.map +1 -1
  17. package/dist-lib/hooks/useKnownOrders.js +20 -1
  18. package/dist-lib/hooks/useOrderBuffers.d.ts +6 -0
  19. package/dist-lib/hooks/useOrderBuffers.d.ts.map +1 -1
  20. package/dist-lib/hooks/useOrderBuffers.js +21 -0
  21. package/dist-lib/hooks/usePickAgenda.d.ts.map +1 -1
  22. package/dist-lib/hooks/usePickAgenda.js +7 -3
  23. package/dist-lib/hooks/usePickMode.d.ts +1 -1
  24. package/dist-lib/index.d.ts +0 -2
  25. package/dist-lib/index.d.ts.map +1 -1
  26. package/dist-lib/index.js +0 -2
  27. package/dist-lib/integrations/supabase/client.server.js +1 -1
  28. package/dist-lib/integrations/supabase/types.d.ts +14 -0
  29. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  30. package/dist-lib/lib/authGateway.server.d.ts.map +1 -1
  31. package/dist-lib/lib/authGateway.server.js +3 -2
  32. package/dist-lib/lib/cartAssignments.functions.d.ts +48 -0
  33. package/dist-lib/lib/cartAssignments.functions.d.ts.map +1 -1
  34. package/dist-lib/lib/cartAssignments.functions.js +111 -0
  35. package/dist-lib/lib/deliveryNotePrint.d.ts +33 -33
  36. package/dist-lib/lib/deliveryNotePrint.js +219 -219
  37. package/dist-lib/lib/floridayFulfillmentSend.server.d.ts +6 -1
  38. package/dist-lib/lib/floridayFulfillmentSend.server.d.ts.map +1 -1
  39. package/dist-lib/lib/floridayFulfillmentSend.server.js +23 -6
  40. package/dist-lib/lib/floridayLoading.functions.d.ts +2 -0
  41. package/dist-lib/lib/floridayLoading.functions.d.ts.map +1 -1
  42. package/dist-lib/lib/floridayLoading.functions.js +52 -24
  43. package/dist-lib/lib/logisticsEngine/capacity.js +1 -1
  44. package/dist-lib/lib/logisticsEngine/staffPlanning.js +1 -1
  45. package/dist-lib/lib/orderFulfilment.functions.d.ts.map +1 -1
  46. package/dist-lib/lib/orderFulfilment.functions.js +17 -0
  47. package/package.json +1 -1
@@ -40,18 +40,17 @@ async function buildLoading(supabase, orderRef) {
40
40
  throw new Error("Geen order opgegeven.");
41
41
  const blockers = [];
42
42
  const loadOrder = async (ref) => {
43
- const { data: row, error } = await supabase
44
- .from("orders")
45
- .select("id, order_number, order_source, custom_fields")
46
- .or(`order_number.eq."${ref.replace(/"/g, "")}"${/^[0-9a-f-]{36}$/i.test(ref) ? `,id.eq.${ref}` : ""}`)
47
- .maybeSingle();
43
+ const isUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(ref);
44
+ const q = supabase.from("orders").select("id, order_number, order_source, custom_fields, buffer_id").is("deleted_at", null);
45
+ const { data: row, error } = await (isUuid ? q.eq("id", ref) : q.eq("order_number", ref)).maybeSingle();
48
46
  if (error)
49
47
  throw new Error(error.message);
50
48
  return row;
51
49
  };
52
50
  const coverage = new Map();
53
51
  const queue = [orderRef];
54
- while (queue.length && coverage.size < 50) {
52
+ const bufferIds = new Set();
53
+ while (queue.length && coverage.size < 200) {
55
54
  const ref = queue.shift();
56
55
  const o = await loadOrder(ref);
57
56
  if (!o) {
@@ -66,13 +65,28 @@ async function buildLoading(supabase, orderRef) {
66
65
  const cf = o.custom_fields ?? {};
67
66
  const soId = typeof cf.floriday_sales_order_id === "string" ? cf.floriday_sales_order_id
68
67
  : typeof cf.salesOrderId === "string" ? cf.salesOrderId : null;
69
- coverage.set(o.id, { ref: o.order_number ?? o.id, source: o.order_source, salesOrderId: soId, cov: cov ?? {} });
70
- for (const k of arr(cov?.carts))
68
+ coverage.set(o.id, { ref: o.order_number ?? o.id, source: o.order_source, salesOrderId: soId, cov: cov ?? {}, bufferId: o.buffer_id });
69
+ // Andere orders op dezelfde (gedeelde) kar.
70
+ for (const k of arr(cov?.carts)) {
71
+ for (const id of arr(k?.orderIds))
72
+ if (typeof id === "string" && !coverage.has(id))
73
+ queue.push(id);
71
74
  for (const r of arr(k?.orderRefs)) {
72
75
  const s2 = String(r);
73
76
  if (![...coverage.values()].some((c) => c.ref === s2))
74
77
  queue.push(s2);
75
78
  }
79
+ }
80
+ // Alle orders van dezelfde buffer (koppeling op buffer-id van de Engine).
81
+ if (o.buffer_id && !bufferIds.has(o.buffer_id)) {
82
+ bufferIds.add(o.buffer_id);
83
+ const { data: sib, error: sErr } = await supabase.from("orders").select("id").eq("buffer_id", o.buffer_id).is("deleted_at", null);
84
+ if (sErr)
85
+ throw new Error(sErr.message);
86
+ for (const s of sib ?? [])
87
+ if (!coverage.has(s.id))
88
+ queue.push(s.id);
89
+ }
76
90
  }
77
91
  // Gecontroleerd = elke kar van de order is bij de controlebalie afgemeld (scan of "Controle uitvoeren").
78
92
  const orderIds = [...coverage.keys()].sort();
@@ -88,14 +102,21 @@ async function buildLoading(supabase, orderRef) {
88
102
  for (const r of sc ?? [])
89
103
  approvedCarts.add(r.cart_id);
90
104
  }
105
+ // Vaste sleutel voor de opdracht: één buffer → buffer-id, anders de gesorteerde order-id's.
106
+ // Deterministisch: dubbele klik of herhaling geeft dezelfde fulfillmentOrderId.
107
+ const bufs = [...new Set([...coverage.values()].map((c) => c.bufferId))];
108
+ const foKey = bufs.length === 1 && bufs[0] ? `buffer:${bufs[0]}` : orderIds.join("|");
109
+ const baseFo = orderIds.length ? (await ensureIds(supabase, "fulfillment_order", [foKey])).get(foKey) : null;
91
110
  // Statusoverzicht van Floriday-authenticatie: fulfillmentRequestId + deliveryOrderId per order.
92
111
  const soIds = [...coverage.values()].map((c) => c.salesOrderId).filter((x) => !!x);
93
112
  let status = new Map();
113
+ let statusFailed = false;
94
114
  try {
95
115
  const { fetchFulfillmentStatus } = await import("./floridayFulfillmentSend.server");
96
- status = await fetchFulfillmentStatus(soIds);
116
+ status = await fetchFulfillmentStatus(soIds, baseFo ? [baseFo] : []);
97
117
  }
98
118
  catch (e) {
119
+ statusFailed = true;
99
120
  blockers.push(e instanceof Error ? e.message : "Statusoverzicht ophalen mislukt.");
100
121
  }
101
122
  // Oude auto-verwerking: laatste logregel per order.
@@ -126,20 +147,22 @@ async function buildLoading(supabase, orderRef) {
126
147
  });
127
148
  if (!salesOrderId)
128
149
  blockers.push(`Order ${ref} heeft geen Floriday-verkooporder.`);
129
- if (cov.pickStatus !== "gepickt")
130
- blockers.push(`Order ${ref} is nog niet gepickt.`);
150
+ // "Gepickt" = alle karren goedgekeurd op de Scan-controle (logistics_control_scan.approved_at).
131
151
  if (!cartsTotal)
132
152
  blockers.push(`Order ${ref} heeft geen karindeling.`);
133
153
  else if (!controlled)
134
154
  blockers.push(`Order ${ref}: ${done} van ${cartsTotal} karren goedgekeurd op de Scan-controle.`);
135
- if (salesOrderId && !st)
136
- blockers.push(`Order ${ref} staat niet in het statusoverzicht van Floriday.`);
137
- if (st && !st.found)
138
- blockers.push(`Order ${ref} is niet gevonden in Floriday.`);
139
- if (st && st.found && fr.length !== 1)
140
- blockers.push(`Order ${ref}: ${fr.length === 0 ? "geen" : "meerdere"} fulfillmentRequest in het statusoverzicht.`);
141
- if (fr.length === 1 && !fr[0].deliveryOrderId)
142
- blockers.push(`Order ${ref}: nog geen levering (deliveryOrderId) in het statusoverzicht.`);
155
+ // Bij een mislukt statusoverzicht geen gevolgfouten per order tonen.
156
+ if (!statusFailed) {
157
+ if (salesOrderId && !st)
158
+ blockers.push(`Order ${ref} staat niet in het statusoverzicht van Floriday.`);
159
+ if (st && !st.found)
160
+ blockers.push(`Order ${ref} is niet gevonden in Floriday.`);
161
+ if (st && st.found && fr.length !== 1)
162
+ blockers.push(`Order ${ref}: ${fr.length === 0 ? "geen" : "meerdere"} fulfillmentRequest in het statusoverzicht.`);
163
+ if (fr.length === 1 && !fr[0].deliveryOrderId)
164
+ blockers.push(`Order ${ref}: nog geen levering (deliveryOrderId) in het statusoverzicht.`);
165
+ }
143
166
  if (auto && (AUTO_ALREADY_SENT.has(auto.status) || auto.fo))
144
167
  blockers.push(`Order ${ref} is al via de oude auto-verwerking verstuurd (${auto.status}); niet nogmaals versturen.`);
145
168
  }
@@ -170,8 +193,7 @@ async function buildLoading(supabase, orderRef) {
170
193
  if (new Set(c.lines.map((l) => l.dl ?? "")).size > 1)
171
194
  blockers.push(`Kar ${c.label} bevat orders van verschillende leveringen; één kar kan maar in één opdracht.`);
172
195
  }
173
- // Opdrachten per levering. Eén levering → sleutel = orders (ongewijzigd t.o.v. eerdere versie).
174
- const foKey = orderIds.join("|");
196
+ // Opdrachten per levering. Eén levering → de vaste sleutel van de order of buffer.
175
197
  const deliveries = [...new Set(orders.map((o) => o.deliveryOrderId ?? ""))];
176
198
  const shipKey = (dl) => (deliveries.length <= 1 ? foKey : `${foKey}|${dl}`);
177
199
  const [foIds, lcIds, itemIds] = await Promise.all([
@@ -183,6 +205,7 @@ async function buildLoading(supabase, orderRef) {
183
205
  loadCarrierReference: lcIds.get(ck),
184
206
  cartLabel: c.label,
185
207
  sortIndex: i + 1,
208
+ additionalLayers: c.layers,
186
209
  shared: c.shared || new Set(c.lines.map((l) => l.orderId)).size > 1,
187
210
  items: c.lines.map((l, j) => ({
188
211
  loadCarrierItemId: itemIds.get(`${ck}|${l.orderId}|${l.key}`),
@@ -210,8 +233,11 @@ async function buildLoading(supabase, orderRef) {
210
233
  })(),
211
234
  };
212
235
  }) : [];
213
- if (allLines.some((l) => !l.frId))
214
- blockers.push("Niet elke regel heeft een fulfillmentRequestId.");
236
+ if (!statusFailed) {
237
+ for (const ref of new Set(allLines.filter((l) => !l.frId).map((l) => l.ref))) {
238
+ blockers.push(`Order ${ref}: nog geen fulfillmentRequestId van Floriday.`);
239
+ }
240
+ }
215
241
  let lastAttempts = [];
216
242
  if (shipments.length) {
217
243
  const { data: at } = await supabase.from("floriday_loading_attempts")
@@ -273,6 +299,8 @@ export const sendFloridayLoading = createServerFn({ method: "POST" })
273
299
  loadCarriers: s.carriers.map((c) => ({
274
300
  loadCarrierReference: c.loadCarrierReference,
275
301
  sortIndex: c.sortIndex,
302
+ // Floriday 2026v1 AddLoadCarrierConfiguration: alleen meesturen als de Engine het kent.
303
+ ...(c.additionalLayers != null ? { numberOfAdditionalLayers: c.additionalLayers } : {}),
276
304
  items: c.items.map((it) => ({
277
305
  fulfillmentRequestId: it.fulfillmentRequestId,
278
306
  loadCarrierItemId: it.loadCarrierItemId,
@@ -298,7 +326,7 @@ export const sendFloridayLoading = createServerFn({ method: "POST" })
298
326
  const code = String(body?.code ?? (httpStatus && httpStatus < 400 ? "ok" : `http_${httpStatus}`));
299
327
  const accepted = httpStatus === 200 && body?.ok === true && ACCEPTED.has(code);
300
328
  const message = accepted ? (code === "created" ? "Belading verstuurd, verzendbrief volgt via de Engine." : "Belading was al verstuurd (niets dubbel aangemaakt), verzendbrief volgt via de Engine.")
301
- : arr(body?.errors).map((e) => (typeof e === "string" ? e : e?.message ?? JSON.stringify(e))).join("; ") || body?.message || code;
329
+ : [typeof body?.error === "string" ? body.error : null, ...arr(body?.errors).map((e) => (typeof e === "string" ? e : e?.message ?? JSON.stringify(e)))].filter(Boolean).join("; ") || body?.message || code;
302
330
  await log(s, {
303
331
  step: "send", http_status: httpStatus, code, message,
304
332
  warnings: arr(body?.warnings), skipped_requests: arr(body?.skippedRequests), request_summary: summary,
@@ -1,4 +1,4 @@
1
- import { supabase } from "../../integrations/supabase/moduleClient";
1
+ import { supabase } from "../../integrations/supabase/moduleClient.js";
2
2
  function num(v) {
3
3
  const n = typeof v === "string" ? Number(v) : typeof v === "number" ? v : NaN;
4
4
  return Number.isFinite(n) ? n : 0;
@@ -1,4 +1,4 @@
1
- import { supabase } from "../../integrations/supabase/moduleClient";
1
+ import { supabase } from "../../integrations/supabase/moduleClient.js";
2
2
  import { SOURCE_MODULE } from "./engine";
3
3
  export function toDateKey(d) {
4
4
  const m = String(d.getMonth() + 1).padStart(2, "0");
@@ -1 +1 @@
1
- {"version":3,"file":"orderFulfilment.functions.d.ts","sourceRoot":"","sources":["../../src/lib/orderFulfilment.functions.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,qBAAqB;IACpC,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB;;;;8CAEH,qBAAqB;;mCAsB3C,CAAC"}
1
+ {"version":3,"file":"orderFulfilment.functions.d.ts","sourceRoot":"","sources":["../../src/lib/orderFulfilment.functions.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,qBAAqB;IACpC,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB;;;;8CAEH,qBAAqB;;mCAoC3C,CAAC"}
@@ -17,6 +17,23 @@ export const markOrderShipped = createServerFn({ method: "POST" })
17
17
  })
18
18
  .handler(async ({ data, context }) => {
19
19
  const { supabase } = context;
20
+ // Floriday-orders: "Verzonden" pas nadat Floriday de belading heeft geaccepteerd.
21
+ const { data: ord, error: oErr } = await supabase
22
+ .from("orders").select("id, order_source").eq("order_number", data.orderRef).is("deleted_at", null).maybeSingle();
23
+ if (oErr)
24
+ throw new Error(oErr.message);
25
+ if (!ord)
26
+ throw new Error(`Bestelling ${data.orderRef} niet gevonden in de orderadministratie.`);
27
+ if (ord.order_source === "floriday") {
28
+ const { data: acc, error: aErr } = await supabase
29
+ .from("floriday_loading_attempts").select("id")
30
+ .contains("order_refs", [data.orderRef]).in("code", ["created", "already_fulfilled"]).limit(1);
31
+ if (aErr)
32
+ throw new Error(aErr.message);
33
+ if (!acc?.length) {
34
+ throw new Error(`${data.orderRef}: nog niet door Floriday geaccepteerd. Verstuur eerst de belading met "Nu versturen".`);
35
+ }
36
+ }
20
37
  const { data: rows, error } = await supabase
21
38
  .from("orders")
22
39
  .update({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowselections/floriday-afhandeling-module",
3
- "version": "1.0.50",
3
+ "version": "1.0.54",
4
4
  "private": false,
5
5
  "sideEffects": false,
6
6
  "type": "module",