@flowselections/logistiek-engine 1.0.11 → 1.0.13

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 (25) hide show
  1. package/dist-lib/integrations/supabase/auth-middleware.d.ts +1134 -189
  2. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
  3. package/dist-lib/integrations/supabase/client.server.d.ts +1134 -189
  4. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  5. package/dist-lib/integrations/supabase/moduleClient.d.ts +1134 -189
  6. package/dist-lib/integrations/supabase/moduleClient.d.ts.map +1 -1
  7. package/dist-lib/integrations/supabase/types.d.ts +1161 -185
  8. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  9. package/dist-lib/lib/floridayDocuments.functions.d.ts +3162 -327
  10. package/dist-lib/lib/floridayDocuments.functions.d.ts.map +1 -1
  11. package/dist-lib/lib/floridayDocuments.server.d.ts +14 -1
  12. package/dist-lib/lib/floridayDocuments.server.d.ts.map +1 -1
  13. package/dist-lib/lib/floridayDocuments.server.js +1 -1
  14. package/dist-lib/lib/floridayPush.functions.d.ts +1134 -189
  15. package/dist-lib/lib/floridayPush.functions.d.ts.map +1 -1
  16. package/dist-lib/lib/floridayPush.server.d.ts +27 -21
  17. package/dist-lib/lib/floridayPush.server.d.ts.map +1 -1
  18. package/dist-lib/lib/floridayPush.server.js +160 -43
  19. package/dist-lib/lib/loadCarrierPlanning.functions.d.ts +5270 -545
  20. package/dist-lib/lib/loadCarrierPlanning.functions.d.ts.map +1 -1
  21. package/dist-lib/lib/logisticsRecalcJob.functions.d.ts +2108 -218
  22. package/dist-lib/lib/logisticsRecalcJob.functions.d.ts.map +1 -1
  23. package/dist-lib/lib/logisticsRecalculate.functions.d.ts +1134 -189
  24. package/dist-lib/lib/logisticsRecalculate.functions.d.ts.map +1 -1
  25. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"floridayPush.server.d.ts","sourceRoot":"","sources":["../../src/lib/floridayPush.server.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,eAAO,MAAM,mBAAmB,KAAK,CAAC;AACtC,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAc/C,mFAAmF;AACnF,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAUlD;AAMD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,KAAK,CAAC;QAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,KAAK,EAAE,KAAK,CAAC;YACX,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;YACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;YAC3B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;YACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;YACrB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;SAC/B,CAAC,CAAC;KACJ,CAAC,CAAC;CACJ;AAED,sEAAsE;AACtE,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,cAAc,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,OAAO,EAAE,mBAAmB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAkDhE;AAOD,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAW3F;AAED,wBAAsB,mBAAmB,CAAC,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhG;AAiBD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,cAAc,EAClB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GACjD,OAAO,CAAC,eAAe,CAAC,CAuF1B;AAQD,wBAAsB,wBAAwB,CAAC,EAAE,EAAE,cAAc,EAAE,IAAI,SAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAS3F"}
1
+ {"version":3,"file":"floridayPush.server.d.ts","sourceRoot":"","sources":["../../src/lib/floridayPush.server.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,eAAO,MAAM,mBAAmB,KAAK,CAAC;AACtC,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAc/C,mFAAmF;AACnF,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAUlD;AAcD,MAAM,WAAW,mBAAmB;IAClC,eAAe,EAAE,MAAM,CAAC;IACxB,qBAAqB,EAAE,MAAM,EAAE,CAAC;CACjC;AAED,MAAM,MAAM,WAAW,GACnB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,mBAAmB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACxD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC;AAUnE;;;;GAIG;AACH,wBAAsB,8BAA8B,CAClD,EAAE,EAAE,cAAc,EAClB,YAAY,EAAE,MAAM,GACnB,OAAO,CACN;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;IAAC,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACvF;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAC7C,CAqDA;AAED,8CAA8C;AAC9C,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,cAAc,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,WAAW,CAAC,CA+EtB;AAQD,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAW3F;AAED,wBAAsB,mBAAmB,CAAC,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhG;AA6BD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,cAAc,EAClB,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GACjD,OAAO,CAAC,eAAe,CAAC,CA0H1B;AAQD,wBAAsB,wBAAwB,CAAC,EAAE,EAAE,cAAc,EAAE,IAAI,SAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAS3F"}
@@ -36,51 +36,126 @@ export function hashPayload(value) {
36
36
  }
37
37
  return h1.toString(16).padStart(8, "0") + h2.toString(16).padStart(8, "0");
38
38
  }
39
- /** Bouwt de gewenste stand voor één order. null = niets te pushen. */
39
+ /**
40
+ * Zoekt de delivery-order die bij een sales-order hoort. De koppeling ligt op
41
+ * de delivery-order: data->'fulfillmentRequests'[]->>'salesOrderId'.
42
+ * Bij meerdere treffers wint de meest recent opgehaalde rij (fetched_at desc).
43
+ */
44
+ export async function findDeliveryOrderForSalesOrder(sb, salesOrderId) {
45
+ const { data, error } = await sb
46
+ .from("floriday_delivery_orders_cache")
47
+ .select("floriday_id, data, fetched_at")
48
+ .contains("data", { fulfillmentRequests: [{ salesOrderId }] })
49
+ .order("fetched_at", { ascending: false })
50
+ .limit(10);
51
+ if (error) {
52
+ return { ok: false, code: "db_error_delivery_orders", error: `Delivery-ordercache niet leesbaar: ${error.message}` };
53
+ }
54
+ const rows = Array.isArray(data) ? data : [];
55
+ if (rows.length === 0) {
56
+ return {
57
+ ok: false,
58
+ code: "delivery_order_not_found_local",
59
+ error: `Nog geen delivery-order in de cache voor sales-order ${salesOrderId}. De push wacht tot de synchronisatie hem binnenhaalt.`,
60
+ };
61
+ }
62
+ if (rows.length > 1) {
63
+ console.info(`[floridayPush] ${rows.length} delivery-orders gevonden voor sales-order ${salesOrderId}; meest recent gefetchte gekozen.`);
64
+ }
65
+ const row = rows[0];
66
+ const payloadData = (row["data"] ?? {});
67
+ const requests = Array.isArray(payloadData["fulfillmentRequests"])
68
+ ? payloadData["fulfillmentRequests"]
69
+ : [];
70
+ const fulfillmentRequestIds = requests
71
+ .filter((r) => String(r["salesOrderId"] ?? "") === salesOrderId)
72
+ .map((r) => String(r["fulfillmentRequestId"] ?? r["id"] ?? ""))
73
+ .filter((s) => s.length > 0)
74
+ .sort();
75
+ if (fulfillmentRequestIds.length === 0) {
76
+ return {
77
+ ok: false,
78
+ code: "delivery_order_without_requests",
79
+ error: `Delivery-order ${String(row["floriday_id"] ?? "")} bevat geen fulfillmentRequests voor sales-order ${salesOrderId}.`,
80
+ };
81
+ }
82
+ return {
83
+ ok: true,
84
+ deliveryOrderId: String(row["floriday_id"] ?? ""),
85
+ fulfillmentRequestIds,
86
+ matches: rows.length,
87
+ };
88
+ }
89
+ /** Bouwt de gewenste stand voor één order. */
40
90
  export async function buildFloridayPayload(sb, orderRef) {
41
- const { data: order } = await sb
91
+ const { data: order, error: orderError } = await sb
42
92
  .from("orders")
43
93
  .select("id, order_number, floriday_sales_order_id")
44
94
  .eq("order_number", orderRef)
45
95
  .maybeSingle();
46
- if (!order)
47
- return null;
96
+ if (orderError) {
97
+ return {
98
+ ok: false,
99
+ code: "db_error_orders",
100
+ error: `Order niet leesbaar: ${orderError.message}`,
101
+ permanent: false,
102
+ };
103
+ }
104
+ if (!order) {
105
+ return { ok: false, code: "order_missing", error: "Order niet gevonden in de Engine.", permanent: true };
106
+ }
48
107
  const row = order;
49
- const { data: carts } = await sb
108
+ const salesOrderId = row["floriday_sales_order_id"] ?? null;
109
+ if (!salesOrderId) {
110
+ return {
111
+ ok: false,
112
+ code: "sales_order_missing",
113
+ error: "Order heeft geen Floriday sales-order; er valt niets te pushen.",
114
+ permanent: true,
115
+ };
116
+ }
117
+ const found = await findDeliveryOrderForSalesOrder(sb, salesOrderId);
118
+ if (!found.ok) {
119
+ // Wachttoestand, geen mislukking: de delivery-order kan later binnenkomen.
120
+ return { ok: false, code: found.code, error: found.error, permanent: false };
121
+ }
122
+ const { data: carts, error: cartsError } = await sb
50
123
  .from("order_carts")
51
124
  .select("id, cart_number, carrier_type, total_layers_used, max_layers, occupancy_pct, weight_kg, order_cart_items(product_id, product_name, crates, boxes, plants_per_crate)")
52
125
  .eq("order_id", row["id"])
53
126
  .order("cart_number", { ascending: true });
54
- const safeCarts = Array.isArray(carts) ? carts : [];
127
+ if (cartsError) {
128
+ return {
129
+ ok: false,
130
+ code: "db_error_carts",
131
+ error: `Karindeling niet leesbaar: ${cartsError.message}`,
132
+ permanent: false,
133
+ };
134
+ }
135
+ const indeling = (Array.isArray(carts) ? carts : []).map((c) => {
136
+ const cart = c;
137
+ const items = Array.isArray(cart["order_cart_items"])
138
+ ? cart["order_cart_items"]
139
+ : [];
140
+ return {
141
+ cartNumber: cart["cart_number"] ?? null,
142
+ carrierType: cart["carrier_type"] ?? null,
143
+ layersUsed: cart["total_layers_used"] ?? null,
144
+ items: items
145
+ .map((i) => ({
146
+ productId: i["product_id"] ?? null,
147
+ crates: i["crates"] ?? null,
148
+ boxes: i["boxes"] ?? null,
149
+ }))
150
+ .sort((a, b) => String(a.productId).localeCompare(String(b.productId))),
151
+ };
152
+ });
55
153
  const payload = {
56
- orderRef,
57
- fulfillmentOrderId: null,
58
- salesOrderId: row["floriday_sales_order_id"] ?? null,
59
- loadCarriers: safeCarts.map((c) => {
60
- const cart = c;
61
- const items = Array.isArray(cart["order_cart_items"])
62
- ? cart["order_cart_items"]
63
- : [];
64
- return {
65
- cartNumber: cart["cart_number"] ?? null,
66
- carrierType: cart["carrier_type"] ?? null,
67
- layersUsed: cart["total_layers_used"] ?? null,
68
- maxLayers: cart["max_layers"] ?? null,
69
- occupancyPct: cart["occupancy_pct"] ?? null,
70
- weightKg: cart["weight_kg"] ?? null,
71
- items: items
72
- .map((i) => ({
73
- productId: i["product_id"] ?? null,
74
- productName: i["product_name"] ?? null,
75
- crates: i["crates"] ?? null,
76
- boxes: i["boxes"] ?? null,
77
- plantsPerCrate: i["plants_per_crate"] ?? null,
78
- }))
79
- .sort((a, b) => String(a.productId).localeCompare(String(b.productId))),
80
- };
81
- }),
154
+ deliveryOrderId: found.deliveryOrderId,
155
+ fulfillmentRequestIds: found.fulfillmentRequestIds,
82
156
  };
83
- return { payload, hash: hashPayload(payload) };
157
+ // De hash bewaakt ook de karindeling, zodat een herindeling opnieuw pusht.
158
+ return { ok: true, payload, hash: hashPayload({ payload, indeling }) };
84
159
  }
85
160
  // ---------------------------------------------------------------------------
86
161
  // In de wachtrij zetten — snel, zonder netwerk, veilig overal aan te roepen
@@ -116,6 +191,21 @@ function isPermanent(status, message) {
116
191
  return true;
117
192
  return /validat|ongeldig|invalid|schema|not found|bestaat niet/i.test(message);
118
193
  }
194
+ /** Korte, stabiele foutcode om later op te kunnen filteren. */
195
+ function gatewayErrorCode(status, payloadOk) {
196
+ if (status === null)
197
+ return "unknown";
198
+ if (status >= 200 && status < 300)
199
+ return payloadOk === true ? "unknown" : "gateway_ok_unreadable";
200
+ if (status >= 500)
201
+ return "gateway_5xx";
202
+ if (status === 400 || status === 401 || status === 404 || status === 429) {
203
+ return `gateway_${status}`;
204
+ }
205
+ if (status >= 400)
206
+ return "gateway_4xx";
207
+ return "unknown";
208
+ }
119
209
  export async function runFloridayPushQueue(sb, opts = {}) {
120
210
  const limit = opts.limit ?? FLORIDAY_PUSH_BATCH;
121
211
  const deadlineAt = opts.deadlineAt ?? Date.now() + 10000;
@@ -148,13 +238,18 @@ export async function runFloridayPushQueue(sb, opts = {}) {
148
238
  let error = null;
149
239
  let sentHash = null;
150
240
  let fulfillmentOrderId = null;
241
+ let gatewayStatus = null;
242
+ let errorCode = null;
243
+ let response = null;
151
244
  try {
152
245
  const built = await buildFloridayPayload(sb, orderRef);
153
- if (!built) {
154
- // Order bestaat niet (meer): niets te pushen, geen eindeloze retry.
246
+ if (!built.ok) {
247
+ // Wachttoestand (delivery-order nog niet gesynchroniseerd) of een
248
+ // databasefout; permanent alleen als de order zelf niet kan bestaan.
155
249
  ok = false;
156
- permanent = true;
157
- error = "Order niet gevonden in de Engine.";
250
+ permanent = built.permanent;
251
+ error = built.error;
252
+ errorCode = built.code;
158
253
  }
159
254
  else if (built.hash === lastSentHash) {
160
255
  // Identieke stand: niets versturen, wel als geslaagd afronden.
@@ -163,22 +258,41 @@ export async function runFloridayPushQueue(sb, opts = {}) {
163
258
  out.skipped++;
164
259
  }
165
260
  else {
166
- const res = (await sendFlorydayFulfillmentOrder(sb, built.payload));
167
- ok = res?.ok === true;
261
+ const res = await sendFlorydayFulfillmentOrder(sb, built.payload);
262
+ gatewayStatus = typeof res?.status === "number" ? res.status : null;
263
+ // Nieuw contract: { status, payload: { ok, error, fulfillmentOrderId } }.
264
+ // Defensief: een oudere gatewayversie gaf ok/error op het hoogste niveau.
265
+ const payload = (res?.payload ?? null);
266
+ if (!payload && res && ("ok" in res || "error" in res)) {
267
+ console.warn("[floridayPush] gateway gaf de oude responsvorm terug (ok/error op hoofdniveau)");
268
+ }
269
+ const payloadOk = payload?.ok ?? res?.ok;
270
+ const payloadError = payload?.error ?? res?.error;
271
+ ok = payloadOk === true;
168
272
  sentHash = built.hash;
169
- fulfillmentOrderId = built.payload.fulfillmentOrderId;
273
+ fulfillmentOrderId = payload?.fulfillmentOrderId ?? null;
274
+ response = {
275
+ ok: payloadOk ?? null,
276
+ error: payloadError ?? null,
277
+ fulfillmentOrderId: payload?.fulfillmentOrderId ?? null,
278
+ };
170
279
  if (!ok) {
171
- error = res?.error ?? "Floriday gaf geen bevestiging.";
172
- permanent = isPermanent(res?.status ?? null, error);
280
+ error =
281
+ payloadError && String(payloadError).length > 0
282
+ ? String(payloadError)
283
+ : `Floriday gaf geen bevestiging. (gatewaystatus ${gatewayStatus ?? "onbekend"})`;
284
+ errorCode = gatewayErrorCode(gatewayStatus, payloadOk);
285
+ permanent = isPermanent(gatewayStatus, error);
173
286
  }
174
287
  }
175
288
  }
176
289
  catch (e) {
177
290
  error = String(e?.message ?? e);
291
+ errorCode = errorCode ?? "unknown";
178
292
  permanent = isPermanent(null, error);
179
293
  }
180
294
  try {
181
- const { data: outcome } = await sb.rpc("logistics_floriday_finish_push", {
295
+ const { data: outcome } = await sb.rpc("logistics_floriday_finish_push_v2", {
182
296
  _id: id,
183
297
  _revision: revision,
184
298
  _ok: ok,
@@ -186,6 +300,9 @@ export async function runFloridayPushQueue(sb, opts = {}) {
186
300
  _fulfillment_order_id: fulfillmentOrderId,
187
301
  _sent_hash: sentHash,
188
302
  _permanent: permanent,
303
+ _gateway_status: gatewayStatus,
304
+ _error_code: errorCode,
305
+ _response: response,
189
306
  });
190
307
  const status = String(outcome ?? "");
191
308
  if (status === "sent")