@flowselections/logistiek-engine 1.0.202 → 1.0.206

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 (30) hide show
  1. package/db/schema/logistiek-engine.sql +885 -0
  2. package/dist-lib/components/BeladingIndelingCard.d.ts.map +1 -1
  3. package/dist-lib/components/BeladingIndelingCard.js +15 -3
  4. package/dist-lib/components/LadingdragersPage.d.ts.map +1 -1
  5. package/dist-lib/components/LadingdragersPage.js +1 -1
  6. package/dist-lib/integrations/supabase/types.d.ts +415 -0
  7. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  8. package/dist-lib/lib/extraPlaten.d.ts +9 -0
  9. package/dist-lib/lib/extraPlaten.d.ts.map +1 -1
  10. package/dist-lib/lib/extraPlaten.js +15 -0
  11. package/dist-lib/lib/floridayCartCarriers.d.ts +3 -0
  12. package/dist-lib/lib/floridayCartCarriers.d.ts.map +1 -1
  13. package/dist-lib/lib/floridayCartCarriers.js +6 -1
  14. package/dist-lib/lib/floridayPush.server.d.ts.map +1 -1
  15. package/dist-lib/lib/floridayPush.server.js +5 -3
  16. package/dist-lib/lib/loadCarrierPlanner.d.ts +68 -1
  17. package/dist-lib/lib/loadCarrierPlanner.d.ts.map +1 -1
  18. package/dist-lib/lib/loadCarrierPlanner.js +293 -280
  19. package/dist-lib/lib/loadCarrierPlanning.server.d.ts.map +1 -1
  20. package/dist-lib/lib/loadCarrierPlanning.server.js +16 -3
  21. package/dist-lib/lib/moduleVersion.d.ts +1 -1
  22. package/dist-lib/lib/moduleVersion.js +1 -1
  23. package/dist-lib/lib/quarantaine.d.ts +9 -0
  24. package/dist-lib/lib/quarantaine.d.ts.map +1 -0
  25. package/dist-lib/lib/quarantaine.js +13 -0
  26. package/dist-lib/lib/shippingNoteQueue.server.d.ts.map +1 -1
  27. package/dist-lib/lib/shippingNoteQueue.server.js +11 -0
  28. package/dist-lib/lib/stickerQueue.server.d.ts.map +1 -1
  29. package/dist-lib/lib/stickerQueue.server.js +13 -0
  30. package/package.json +1 -1
@@ -5,8 +5,9 @@
5
5
  // draait de pure planner per ladingdragertype en schrijft het resultaat weg
6
6
  // naar order_carts / order_cart_items.
7
7
  // ============================================================================
8
- import { planLoadUnits, LOAD_CARRIER_PLANNER_VERSION, } from "./loadCarrierPlanner.js";
8
+ import { planLoadUnits, LOAD_CARRIER_PLANNER_VERSION, bepaalLaagMenging, } from "./loadCarrierPlanner.js";
9
9
  import { traceBatch } from "./trace.server.js";
10
+ import { zonderQuarantaine } from "./quarantaine.js";
10
11
  import { MODULE_VERSION } from "./moduleVersion.js";
11
12
  import { fallbackCarrierProfile } from "./loadCarrierTypes.js";
12
13
  import { WAAR_INVULLEN, gewichtOnbekendTekst, ladingdragerNietInBeheerTekst } from "./invoerTeksten.js";
@@ -639,6 +640,7 @@ export function applyRulesToProfile(profile, rules) {
639
640
  layers_per_carrier: rules.maxLayers != null
640
641
  ? Math.max(1, Math.min(profile.layers_per_carrier || 1, rules.maxLayers))
641
642
  : profile.layers_per_carrier,
643
+ werkwijze_max_lagen: rules.maxLayers ?? null,
642
644
  max_boxes: rules.maxBoxes != null
643
645
  ? Math.min(profile.max_boxes ?? Number.MAX_SAFE_INTEGER, rules.maxBoxes)
644
646
  : profile.max_boxes ?? null,
@@ -1150,14 +1152,16 @@ async function replanBufferUnlocked(sb, bufferId, options = {}) {
1150
1152
  }
1151
1153
  }
1152
1154
  const idList = orderIds.length > 0 ? orderIds : ["00000000-0000-0000-0000-000000000000"];
1153
- const { data: rawItems } = await sb
1155
+ const { data: rawItemsDb } = await sb
1154
1156
  .from("order_items")
1155
1157
  .select("id, order_id, product_id, product_name, quantity, unit, plants_per_crate, crates_per_layer, layers_per_cart, " +
1156
- "packing_locked_at, packing_locked_by, source_line_key, load_carrier_type, " +
1158
+ "packing_locked_at, packing_locked_by, source_line_key, load_carrier_type, quarantined_at, " +
1157
1159
  "products(plants_per_crate, crates_per_layer, layers_per_cart, weight, floriday_trade_item_id, fust_type_id)")
1158
1160
  .in("order_id", idList)
1159
1161
  // Regels in quarantaine (Verkoop-herstel) nooit inplannen.
1160
1162
  .is("quarantined_at", null);
1163
+ // 1.0.205: dubbele bescherming — ook na het lezen nooit regels in quarantaine plannen.
1164
+ const rawItems = zonderQuarantaine((rawItemsDb ?? []));
1161
1165
  // 1.0.166: regels die in Floriday zijn afgehandeld nooit inplannen. Onleesbaar = niet plannen (fail closed).
1162
1166
  const { data: extern, error: externError } = await sb
1163
1167
  .from("logistics_external_fulfillment")
@@ -1819,7 +1823,16 @@ async function replanBufferUnlocked(sb, bufferId, options = {}) {
1819
1823
  }
1820
1824
  for (const [code, list] of groups) {
1821
1825
  const profile = applyRulesToProfile(profileFor(profiles, code), rules);
1826
+ const maxBelPerLaag = rules && !rules.optimalFill ? 1 : (settings?.max_beladingen_per_layer ?? 2);
1827
+ const mengregels = bepaalLaagMenging({
1828
+ optimalFill: rules?.optimalFill ?? null,
1829
+ maxBeladingenPerLayer: maxBelPerLaag,
1830
+ maxCustomersPerLayer: rules?.maxCustomersPerLayer ?? null,
1831
+ oneCustomerPerLayer: Boolean(settings?.max_one_customer_per_layer),
1832
+ });
1822
1833
  const result = planLoadUnits(list, {
1834
+ laagMenging: mengregels.menging,
1835
+ laagGroepen: mengregels.groepen,
1823
1836
  carrier: profile,
1824
1837
  maxPartySharePerLayerPct: settings?.max_party_share_per_layer_pct ?? 50,
1825
1838
  // Zonder optimale vulling wordt er niet bijgemengd in een laag.
@@ -1,2 +1,2 @@
1
- export declare const MODULE_VERSION = "1.0.202";
1
+ export declare const MODULE_VERSION = "1.0.206";
2
2
  //# sourceMappingURL=moduleVersion.d.ts.map
@@ -1,2 +1,2 @@
1
1
  // Automatisch gegenereerd door prebuild:lib; niet handmatig aanpassen.
2
- export const MODULE_VERSION = "1.0.202";
2
+ export const MODULE_VERSION = "1.0.206";
@@ -0,0 +1,9 @@
1
+ /** Is deze orderregel in quarantaine? */
2
+ export declare function inQuarantaine(row: {
3
+ quarantined_at?: unknown;
4
+ } | null | undefined): boolean;
5
+ /** Alleen regels die niet in quarantaine staan. */
6
+ export declare function zonderQuarantaine<T extends {
7
+ quarantined_at?: unknown;
8
+ }>(rows: T[] | null | undefined): T[];
9
+ //# sourceMappingURL=quarantaine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quarantaine.d.ts","sourceRoot":"","sources":["../../src/lib/quarantaine.ts"],"names":[],"mappings":"AAKA,yCAAyC;AACzC,wBAAgB,aAAa,CAAC,GAAG,EAAE;IAAE,cAAc,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAG3F;AAED,mDAAmD;AACnD,wBAAgB,iBAAiB,CAAC,CAAC,SAAS;IAAE,cAAc,CAAC,EAAE,OAAO,CAAA;CAAE,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,IAAI,GAAG,SAAS,GAAG,CAAC,EAAE,CAE3G"}
@@ -0,0 +1,13 @@
1
+ // 1.0.205: orderregels in quarantaine (Verkoop-herstel, order_items.quarantined_at gevuld)
2
+ // worden nergens in de Engine ingedeeld, geteld of verstuurd. Eén regel voor alle plekken:
3
+ // planner, dekking, pakbonplan en Floriday-belading (SQL-kant: logistics_active.order_items
4
+ // en filters op oi.quarantined_at IS NULL).
5
+ /** Is deze orderregel in quarantaine? */
6
+ export function inQuarantaine(row) {
7
+ const v = row?.quarantined_at;
8
+ return v !== null && v !== undefined && String(v).trim() !== "";
9
+ }
10
+ /** Alleen regels die niet in quarantaine staan. */
11
+ export function zonderQuarantaine(rows) {
12
+ return (Array.isArray(rows) ? rows : []).filter((r) => !inQuarantaine(r));
13
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"shippingNoteQueue.server.d.ts","sourceRoot":"","sources":["../../src/lib/shippingNoteQueue.server.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAS5D,MAAM,WAAW,eAAe;IAC9B,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAoCD,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,cAAc,EAClB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,OAAO,CAAC,eAAe,CAAC,CA8f1B;AAMD,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,aAAa,GAAG,IAAI,CAAC;AAElE,qGAAqG;AACrG,wBAAsB,uBAAuB,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAQ9F;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,mBAAmB,CAG5E;AAED,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,mBAAmB,GAAG,MAAM,CAI3E"}
1
+ {"version":3,"file":"shippingNoteQueue.server.d.ts","sourceRoot":"","sources":["../../src/lib/shippingNoteQueue.server.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAS5D,MAAM,WAAW,eAAe;IAC9B,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAoCD,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,cAAc,EAClB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,OAAO,CAAC,eAAe,CAAC,CA0gB1B;AAMD,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,aAAa,GAAG,IAAI,CAAC;AAElE,qGAAqG;AACrG,wBAAsB,uBAAuB,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAQ9F;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,mBAAmB,CAG5E;AAED,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,mBAAmB,GAAG,MAAM,CAI3E"}
@@ -376,6 +376,17 @@ export async function runShippingNoteQueue(sb, options = {}) {
376
376
  const slipPayload = slipRow["payload"] ?? {};
377
377
  const printPlekId = String(slipPayload["print_plek_id"] ?? "").trim() || null;
378
378
  const cartId = slipPayload["cart_id"] ?? row.cart_id;
379
+ // 1.0.201: een te hoge kar krijgt geen verzendbrief (fail-closed, wacht zonder poging).
380
+ if (cartId) {
381
+ const { data: hoog, error: hoogFout } = await sb.rpc("logistics_cart_te_hoog", { p_cart_id: cartId });
382
+ const tekst = hoogFout
383
+ ? `Kon niet controleren of de kar te hoog is: ${hoogFout.message}`
384
+ : hoog?.blokkade?.tekst;
385
+ if (tekst) {
386
+ await houdVast(tekst);
387
+ continue;
388
+ }
389
+ }
379
390
  // Layout op id: de actieve Floriday-afleverbrief (bij meerdere de standaard).
380
391
  const layout = await floridayLayout(sb, "afleverbrief", row.order_id);
381
392
  if (!layout.layoutId) {
@@ -1 +1 @@
1
- {"version":3,"file":"stickerQueue.server.d.ts","sourceRoot":"","sources":["../../src/lib/stickerQueue.server.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAuB5D,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,wEAAwE;IACxE,UAAU,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpE;AAED,UAAU,GAAG;IACX,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,SAAS,GAAG,aAAa,GAAG,eAAe,GAAG,mBAAmB,CAAC;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC;AAKD,6EAA6E;AAC7E,eAAO,MAAM,oBAAoB,sBAAsB,CAAC;AAExD,sGAAsG;AACtG,eAAO,MAAM,sBAAsB,UAA0F,CAAC;AAE9H,oDAAoD;AACpD,wBAAgB,aAAa,CAAC,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,MAAM,CAEzD;AAaD,wBAAsB,eAAe,CAAC,EAAE,EAAE,cAAc,EAAE,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CA4b5G;AAoGD,kFAAkF;AAClF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAGzD;AAwGD;;;;GAIG;AACH,wBAAsB,wBAAwB,CAC5C,EAAE,EAAE,cAAc,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAatD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEtF"}
1
+ {"version":3,"file":"stickerQueue.server.d.ts","sourceRoot":"","sources":["../../src/lib/stickerQueue.server.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAuB5D,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,wEAAwE;IACxE,UAAU,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpE;AAED,UAAU,GAAG;IACX,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,SAAS,GAAG,aAAa,GAAG,eAAe,GAAG,mBAAmB,CAAC;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC;AAKD,6EAA6E;AAC7E,eAAO,MAAM,oBAAoB,sBAAsB,CAAC;AAExD,sGAAsG;AACtG,eAAO,MAAM,sBAAsB,UAA0F,CAAC;AAE9H,oDAAoD;AACpD,wBAAgB,aAAa,CAAC,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,MAAM,CAEzD;AAaD,wBAAsB,eAAe,CAAC,EAAE,EAAE,cAAc,EAAE,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAyc5G;AAoGD,kFAAkF;AAClF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAGzD;AAwGD;;;;GAIG;AACH,wBAAsB,wBAAwB,CAC5C,EAAE,EAAE,cAAc,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAatD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEtF"}
@@ -248,6 +248,19 @@ export async function runStickerQueue(sb, opts = {}) {
248
248
  run.blocked++;
249
249
  await trace(sb, { ...basis, step: `${label} niet geprint`, status: "waarschuwing", reason: reden });
250
250
  };
251
+ // 1.0.201: een kar die hoger is dan de ladingdrager toestaat krijgt geen stickers (fail-closed).
252
+ if (r.cart_id) {
253
+ const { data: hoog, error: hoogFout } = await sb.rpc("logistics_cart_te_hoog", { p_cart_id: r.cart_id });
254
+ if (hoogFout) {
255
+ await blokkeer(`Kon niet controleren of kar ${r.cart_id} te hoog is: ${hoogFout.message}`);
256
+ continue;
257
+ }
258
+ const tekst = hoog?.blokkade?.tekst;
259
+ if (tekst) {
260
+ await blokkeer(tekst);
261
+ continue;
262
+ }
263
+ }
251
264
  const later = async (reden) => {
252
265
  if (isHerprint) {
253
266
  await trace(sb, { ...basis, step: `${label}: herprint opnieuw proberen`, status: "wachtend", reason: reden });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowselections/logistiek-engine",
3
- "version": "1.0.202",
3
+ "version": "1.0.206",
4
4
  "flowselections": {
5
5
  "moduleId": "logistiek-engine",
6
6
  "pages": [