@flowselections/logistiek-engine 1.0.25 → 1.0.27

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 (57) hide show
  1. package/README.md +24 -24
  2. package/dist-lib/components/ConsistentieCard.d.ts +2 -0
  3. package/dist-lib/components/ConsistentieCard.d.ts.map +1 -0
  4. package/dist-lib/components/ConsistentieCard.js +38 -0
  5. package/dist-lib/components/ModulePromptsPage.d.ts.map +1 -1
  6. package/dist-lib/components/ModulePromptsPage.js +11 -3
  7. package/dist-lib/components/RegiePage.d.ts.map +1 -1
  8. package/dist-lib/components/RegiePage.js +2 -1
  9. package/dist-lib/index.d.ts +1 -0
  10. package/dist-lib/index.d.ts.map +1 -1
  11. package/dist-lib/index.js +1 -0
  12. package/dist-lib/integrations/supabase/auth-middleware.d.ts +1048 -715
  13. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
  14. package/dist-lib/integrations/supabase/client.server.d.ts +1048 -715
  15. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  16. package/dist-lib/integrations/supabase/client.server.js +1 -1
  17. package/dist-lib/integrations/supabase/moduleClient.d.ts +1048 -715
  18. package/dist-lib/integrations/supabase/moduleClient.d.ts.map +1 -1
  19. package/dist-lib/integrations/supabase/types.d.ts +1081 -768
  20. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  21. package/dist-lib/lib/dimensionData.server.d.ts +27 -0
  22. package/dist-lib/lib/dimensionData.server.d.ts.map +1 -0
  23. package/dist-lib/lib/dimensionData.server.js +157 -0
  24. package/dist-lib/lib/dimensionPlanner.d.ts +70 -0
  25. package/dist-lib/lib/dimensionPlanner.d.ts.map +1 -0
  26. package/dist-lib/lib/dimensionPlanner.js +217 -0
  27. package/dist-lib/lib/floridayDocuments.functions.d.ts +3054 -2055
  28. package/dist-lib/lib/floridayDocuments.functions.d.ts.map +1 -1
  29. package/dist-lib/lib/floridayPush.functions.d.ts +1048 -715
  30. package/dist-lib/lib/floridayPush.functions.d.ts.map +1 -1
  31. package/dist-lib/lib/loadCarrierPlanner.d.ts +3 -0
  32. package/dist-lib/lib/loadCarrierPlanner.d.ts.map +1 -1
  33. package/dist-lib/lib/loadCarrierPlanning.functions.d.ts +5105 -3465
  34. package/dist-lib/lib/loadCarrierPlanning.functions.d.ts.map +1 -1
  35. package/dist-lib/lib/loadCarrierPlanning.server.d.ts +4 -0
  36. package/dist-lib/lib/loadCarrierPlanning.server.d.ts.map +1 -1
  37. package/dist-lib/lib/loadCarrierPlanning.server.js +113 -3
  38. package/dist-lib/lib/logisticsPlanner.d.ts.map +1 -1
  39. package/dist-lib/lib/logisticsPlanner.js +35 -13
  40. package/dist-lib/lib/logisticsRecalcJob.functions.d.ts +1983 -1317
  41. package/dist-lib/lib/logisticsRecalcJob.functions.d.ts.map +1 -1
  42. package/dist-lib/lib/logisticsRecalculate.functions.d.ts +1048 -715
  43. package/dist-lib/lib/logisticsRecalculate.functions.d.ts.map +1 -1
  44. package/dist-lib/lib/modulePrompts.d.ts +19 -3
  45. package/dist-lib/lib/modulePrompts.d.ts.map +1 -1
  46. package/dist-lib/lib/modulePrompts.js +1666 -1298
  47. package/dist-lib/lib/ruleEngineSchema.d.ts.map +1 -1
  48. package/dist-lib/lib/ruleEngineSchema.js +32 -4
  49. package/dist-lib/lib/ruleEngineWizard.d.ts.map +1 -1
  50. package/dist-lib/lib/ruleEngineWizard.js +4 -1
  51. package/package.json +1 -1
  52. package/dist-lib/components/rule-engine/FloridayConnectionBanner.d.ts +0 -2
  53. package/dist-lib/components/rule-engine/FloridayConnectionBanner.d.ts.map +0 -1
  54. package/dist-lib/components/rule-engine/FloridayConnectionBanner.js +0 -41
  55. package/dist-lib/integrations/supabase/client.d.ts +0 -20293
  56. package/dist-lib/integrations/supabase/client.d.ts.map +0 -1
  57. package/dist-lib/integrations/supabase/client.js +0 -13
@@ -1,6 +1,7 @@
1
1
  import type { SupabaseClient } from "@supabase/supabase-js";
2
2
  import { type CarrierProfile, type PlannedLoadUnit, type PlannerInputItem } from "./loadCarrierPlanner";
3
3
  import { type LoadCarrierTypeRow } from "./loadCarrierTypes";
4
+ import { type DimensionCart } from "./dimensionPlanner";
4
5
  export declare function buildBufferKey(order: {
5
6
  id: string;
6
7
  customer_id?: string | null;
@@ -40,6 +41,8 @@ export interface BeladingRules {
40
41
  maxLayers: number | null;
41
42
  maxBoxes: number | null;
42
43
  optimalFill: boolean;
44
+ /** Globale methode voor de karrenindeling. */
45
+ layoutMethod: "belading" | "afmetingen";
43
46
  }
44
47
  /** Leest de actieve werkwijze en vertaalt "2. Beladingindeling" naar plannergrenzen. */
45
48
  export declare function loadBeladingRules(sb: SupabaseClient): Promise<BeladingRules | null>;
@@ -51,6 +54,7 @@ export declare function applyRulesToProfile(profile: CarrierProfile, rules: Bela
51
54
  * Geen optimalisatie, geen mengregels, geen laagherverdeling — alleen vullen.
52
55
  */
53
56
  export declare function planByFloridayPacking(inputs: PlannerInputItem[], profile: CarrierProfile, packing: Belading): PlannedLoadUnit[];
57
+ export declare function dimensionCartsToPlannedUnits(carts: DimensionCart[]): PlannedLoadUnit[];
54
58
  export interface ReplanResult {
55
59
  ok: boolean;
56
60
  bufferId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"loadCarrierPlanning.server.d.ts","sourceRoot":"","sources":["../../src/lib/loadCarrierPlanning.server.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,eAAe,EAEpB,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAA0B,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAiCrF,wBAAgB,cAAc,CAC5B,KAAK,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,aAAa,CAAC,EAAE,GAAG,CAAA;CAAE,EACtG,IAAI,EAAE,MAAM,GACX;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAqCvD;AAID,wBAAsB,6BAA6B,CAAC,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAmE/G;AAMD,UAAU,QAAQ;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,wDAAwD;AACxD,MAAM,MAAM,cAAc,GAAG,kBAAkB,GAAG,aAAa,GAAG,SAAS,GAAG,MAAM,CAAC;AAOrF;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAQ7E;AAiCD,MAAM,WAAW,aAAa;IAC5B,oEAAoE;IACpE,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACvC,iEAAiE;IACjE,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CACvC;AAED,wBAAsB,0BAA0B,CAC9C,EAAE,EAAE,cAAc,EAClB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,EAChC,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAmI7B;AAMD,wBAAsB,mBAAmB,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAO3F;AAUD,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,OAAO,CAAC;CACtB;AAOD,wFAAwF;AACxF,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAsBzF;AAED,2FAA2F;AAC3F,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI,GAAG,cAAc,CAaxG;AAMD;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,gBAAgB,EAAE,EAC1B,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,QAAQ,GAChB,eAAe,EAAE,CAkEnB;AAaD,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC/B,mDAAmD;IACnD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,KAAK,CAAC,EAAE,eAAe,EAAE,CAAC;CAC3B;AAGD,MAAM,WAAW,aAAa;IAC5B,4CAA4C;IAC5C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,cAAc,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,YAAY,CAAC,CAyUvB;AAGD,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,cAAc,EAClB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAI9B"}
1
+ {"version":3,"file":"loadCarrierPlanning.server.d.ts","sourceRoot":"","sources":["../../src/lib/loadCarrierPlanning.server.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,8 @@
7
7
  // ============================================================================
8
8
  import { planLoadUnits, LOAD_CARRIER_PLANNER_VERSION, } from "./loadCarrierPlanner";
9
9
  import { fallbackCarrierProfile } from "./loadCarrierTypes";
10
+ import { planByDimensions, DIMENSION_PLANNER_VERSION } from "./dimensionPlanner";
11
+ import { buildDimensionItems, carrierDimensions } from "./dimensionData.server";
10
12
  // ---------------------------------------------------------------------------
11
13
  // Buffer
12
14
  // ---------------------------------------------------------------------------
@@ -328,6 +330,7 @@ export async function loadBeladingRules(sb) {
328
330
  maxLayers: k.fill_layers_as_much_as_fits ? null : numOrNull(k.max_layers),
329
331
  maxBoxes: k.fill_boxes_as_much_as_fits ? null : numOrNull(k.max_boxes_per_pallet),
330
332
  optimalFill: k.optimal_fill !== false,
333
+ layoutMethod: k.cart_layout_method === "afmetingen" ? "afmetingen" : "belading",
331
334
  };
332
335
  }
333
336
  /** Past de grenzen uit de werkwijze toe op het capaciteitsprofiel van een ladingdrager. */
@@ -414,6 +417,50 @@ export function planByFloridayPacking(inputs, profile, packing) {
414
417
  return carts;
415
418
  }
416
419
  // ---------------------------------------------------------------------------
420
+ // Indeling op afmetingen omzetten naar het bestaande opslagmodel
421
+ // ---------------------------------------------------------------------------
422
+ export function dimensionCartsToPlannedUnits(carts) {
423
+ return carts.map((cart) => {
424
+ const layerCount = cart.layers.length || 1;
425
+ const items = [];
426
+ for (const layer of cart.layers) {
427
+ const cratesInLayer = layer.placements.reduce((s, p) => s + p.crates, 0) || 1;
428
+ for (const p of layer.placements) {
429
+ const fraction = p.crates / cratesInLayer;
430
+ items.push({
431
+ order_item_id: p.order_item_id,
432
+ order_id: p.order_id,
433
+ product_id: p.product_id,
434
+ product_name: p.product_name,
435
+ crates: p.crates,
436
+ plants: p.plants,
437
+ boxes: p.crates,
438
+ weight_kg: p.weight_kg,
439
+ plants_per_crate: p.plants_per_crate,
440
+ crates_per_layer: cratesInLayer,
441
+ layers_per_cart: layerCount,
442
+ layer_fraction: Number(fraction.toFixed(3)),
443
+ layer_share_pct: Number(((100 * fraction) / layerCount).toFixed(2)),
444
+ layer_index: layer.layer_index,
445
+ crates_in_layer: p.crates,
446
+ });
447
+ }
448
+ }
449
+ return {
450
+ cart_number: cart.cart_number,
451
+ carrier_type: cart.carrier_code,
452
+ carrier_type_id: cart.carrier_id,
453
+ source: "auto",
454
+ is_complete: cart.is_complete,
455
+ occupancy_pct: cart.occupancy_pct,
456
+ total_layers_used: layerCount,
457
+ max_layers: layerCount,
458
+ weight_kg: cart.weight_kg,
459
+ items,
460
+ };
461
+ });
462
+ }
463
+ // ---------------------------------------------------------------------------
417
464
  // Herplannen van een buffer
418
465
  // ---------------------------------------------------------------------------
419
466
  /** Maximaal aantal ladingdragers dat één orderbuffer mag opleveren. */
@@ -487,7 +534,8 @@ export async function replanBufferInternal(sb, bufferId, options = {}) {
487
534
  const guardProfile = profileFor(profiles, options.carrierType ?? defaultProfile.code);
488
535
  const needsBelading = guardProfile.capacity_model !== "single" && guardProfile.capacity_model !== "none";
489
536
  const unknownItems = inputs.filter((i) => sources.get(i.order_item_id) === "geen" && i.plants > 0);
490
- if (needsBelading && unknownItems.length > 0 && !options.dryRun) {
537
+ const useDimensions = rules?.layoutMethod === "afmetingen";
538
+ if (!useDimensions && needsBelading && unknownItems.length > 0 && !options.dryRun) {
491
539
  const reason = `Belading onbekend voor ${unknownItems.length} orderregel(s): geen Floriday-verpakking, ` +
492
540
  `geen waarden op de orderregel en geen productinstelling. Er is niets ingedeeld.`;
493
541
  console.error(`[logistiek-engine] buffer ${bufferId} geblokkeerd: ${reason}`);
@@ -528,7 +576,66 @@ export async function replanBufferInternal(sb, bufferId, options = {}) {
528
576
  const soloPacking = solo ? beladingFromFloridayPacking(solo.custom_fields?.floriday_packing) : null;
529
577
  const takeoverProfile = profileFor(profiles, options.carrierType ?? defaultProfile.code);
530
578
  const takeoverAllowed = takeoverProfile.capacity_model === "layered" || takeoverProfile.capacity_model === "stacked";
531
- if (solo && soloPacking && takeoverAllowed) {
579
+ if (useDimensions) {
580
+ // Globale methode: indelen op basis van fysieke afmetingen.
581
+ const carrierRow = profiles.find((p) => p.code === (options.carrierType ?? defaultProfile.code)) ?? null;
582
+ const { carrier, missing: carrierMissing } = carrierDimensions(carrierRow);
583
+ const { items: dimItems, missing: itemMissing } = await buildDimensionItems(sb, inputs);
584
+ const missing = [...carrierMissing, ...itemMissing];
585
+ let planError = null;
586
+ if (missing.length === 0 && carrier) {
587
+ const result = planByDimensions(dimItems, carrier);
588
+ if (result.error)
589
+ planError = result.error;
590
+ else {
591
+ plannedCarts = dimensionCartsToPlannedUnits(result.carts);
592
+ warnings.push(...result.warnings);
593
+ }
594
+ }
595
+ if (missing.length > 0 || planError) {
596
+ const reason = planError ?? `Afmetingen onbekend: ${missing.map((m) => m.message).join(" ")}`;
597
+ if (options.dryRun) {
598
+ return {
599
+ ok: false,
600
+ bufferId,
601
+ orderIds,
602
+ cartsCreated: 0,
603
+ replacedManualCount: 0,
604
+ usedFloridayPacking: false,
605
+ warnings: [...warnings, reason],
606
+ skipped: "blocked",
607
+ blockedReason: reason,
608
+ beladingSources,
609
+ };
610
+ }
611
+ console.error(`[logistiek-engine] buffer ${bufferId} geblokkeerd (afmetingen): ${reason}`);
612
+ const { error: blockError } = await sb.rpc("logistics_plan_block", {
613
+ p_order_ids: orderIds,
614
+ p_reason: reason,
615
+ p_details: {
616
+ bufferId,
617
+ path: "afmetingen",
618
+ carrier: carrierRow?.code ?? null,
619
+ missing: missing.slice(0, 20),
620
+ },
621
+ });
622
+ if (blockError)
623
+ warnings.push(`Blokkade kon niet worden vastgelegd: ${blockError.message}`);
624
+ return {
625
+ ok: false,
626
+ bufferId,
627
+ orderIds,
628
+ cartsCreated: 0,
629
+ replacedManualCount: 0,
630
+ usedFloridayPacking: false,
631
+ warnings: [...warnings, reason],
632
+ skipped: "blocked",
633
+ blockedReason: reason,
634
+ beladingSources,
635
+ };
636
+ }
637
+ }
638
+ else if (solo && soloPacking && takeoverAllowed) {
532
639
  usedFloridayPacking = true;
533
640
  plannedCarts = planByFloridayPacking(inputs, takeoverProfile, soloPacking);
534
641
  console.log(`[logistiek-engine] buffer ${bufferId}: overname Floriday-verpakking ` +
@@ -639,7 +746,8 @@ export async function replanBufferInternal(sb, bufferId, options = {}) {
639
746
  carrier_type_id: cart.carrier_type_id,
640
747
  max_layers: cart.max_layers,
641
748
  weight_kg: cart.weight_kg,
642
- algorithm_version: LOAD_CARRIER_PLANNER_VERSION,
749
+ algorithm_version: useDimensions ? DIMENSION_PLANNER_VERSION : LOAD_CARRIER_PLANNER_VERSION,
750
+ layout_method: useDimensions ? "afmetingen" : "belading",
643
751
  };
644
752
  });
645
753
  const { data: insertedCarts, error } = await sb
@@ -674,6 +782,8 @@ export async function replanBufferInternal(sb, bufferId, options = {}) {
674
782
  layers_per_cart: i.layers_per_cart,
675
783
  layer_fraction: i.layer_fraction,
676
784
  layer_share_pct: i.layer_share_pct,
785
+ layer_index: i.layer_index ?? null,
786
+ crates_in_layer: i.crates_in_layer ?? null,
677
787
  });
678
788
  }
679
789
  }
@@ -1 +1 @@
1
- {"version":3,"file":"logisticsPlanner.d.ts","sourceRoot":"","sources":["../../src/lib/logisticsPlanner.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAc,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAO/F,MAAM,MAAM,eAAe,GACvB,SAAS,GACT,kBAAkB,GAClB,mBAAmB,GACnB,QAAQ,GACR,aAAa,GACb,OAAO,CAAC;AAEZ,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,eAAe,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,kBAAkB,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,wFAAwF;IACxF,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,WAAW,EAAE,kBAAkB,CAAC;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,+EAA+E;IAC/E,QAAQ,EAAE;QACR,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;QAC7B,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,cAAc,EAAE,MAAM,CAAC;QACvB,KAAK,EAAE,MAAM,CAAC;QACd,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;KAChC,CAAC;IACF,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAgDD,0FAA0F;AAC1F,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,kBAAkB,EAAE,EAC9B,QAAQ,EAAE,kBAAkB,GAC3B;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CASpC;AAMD,wBAAgB,SAAS,CACvB,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,GAAE,cAAmB,GAC3B,aAAa,CAwQf"}
1
+ {"version":3,"file":"logisticsPlanner.d.ts","sourceRoot":"","sources":["../../src/lib/logisticsPlanner.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAc,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAO/F,MAAM,MAAM,eAAe,GACvB,SAAS,GACT,kBAAkB,GAClB,mBAAmB,GACnB,QAAQ,GACR,aAAa,GACb,OAAO,CAAC;AAEZ,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,eAAe,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,kBAAkB,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,wFAAwF;IACxF,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,WAAW,EAAE,kBAAkB,CAAC;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,+EAA+E;IAC/E,QAAQ,EAAE;QACR,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;QAC7B,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,cAAc,EAAE,MAAM,CAAC;QACvB,KAAK,EAAE,MAAM,CAAC;QACd,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;KAChC,CAAC;IACF,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAgDD,0FAA0F;AAC1F,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,kBAAkB,EAAE,EAC9B,QAAQ,EAAE,kBAAkB,GAC3B;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CASpC;AAMD,wBAAgB,SAAS,CACvB,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,GAAE,cAAmB,GAC3B,aAAa,CAqSf"}
@@ -154,14 +154,21 @@ export function planOrder(order, settings, context = {}) {
154
154
  loadCarriers: carriers,
155
155
  fillMode: "generated",
156
156
  });
157
+ // Aantal ladingdragers bepaalt bij "kleinste telt" of de opdracht per order
158
+ // of per kar gaat: past de order binnen één kar, dan is de order de eenheid.
159
+ const totalCarriers = carriers.reduce((sum, c) => sum + Math.max(0, num(c.count, 0)), 0);
160
+ const configuredPickMode = str(pickStep.pick_mode, "cart");
161
+ const pickUnit = configuredPickMode === "smallest" ? (totalCarriers <= 1 ? "order" : "cart") : configuredPickMode;
157
162
  add("pick.execute", pickStartAt, pickEndAt, {
158
- pickMode: str(pickStep.pick_mode, "cart"),
163
+ pickMode: configuredPickMode,
164
+ pickUnit,
159
165
  pickStartMode,
160
166
  pickMinutes,
161
167
  staff,
162
168
  reserveMinutes,
163
169
  scanner: str(pickStep.scanner, "required"),
164
170
  loadCarriers: carriers,
171
+ totalCarriers,
165
172
  pickWindowShifted,
166
173
  pickWindowOriginalStart: pickWindowShifted ? pickStartRaw : null,
167
174
  });
@@ -205,18 +212,33 @@ export function planOrder(order, settings, context = {}) {
205
212
  };
206
213
  const packingRelease = str(docStep.packing_slip_release, "with_pick_release");
207
214
  const packingAt = docRelease(packingRelease, num(docStep.packing_slip_hours_before, 2));
208
- const pickMode = str(pickStep.pick_mode, "cart");
209
- const groupIdenticalCarts = pickMode === "cart" && bool(docStep.packing_slip_group_identical_carts, true);
210
- add("print.packing_slip", packingAt, packingAt, {
211
- documentType: "pakbon",
212
- release: packingRelease,
213
- pickStationId: str(docStep.packing_slip_station, "") || null,
214
- requiresApproval: false,
215
- pickMode,
216
- groupIdenticalCarts,
217
- cartsPerPrint: groupIdenticalCarts ? Math.max(1, num(docStep.packing_slip_carts_per_print, 1)) : null,
218
- splitIdenticalGroups: false,
219
- });
215
+ const pickMode = configuredPickMode;
216
+ const groupIdenticalCarts = (pickMode === "cart" || pickMode === "smallest") &&
217
+ bool(docStep.packing_slip_group_identical_carts, true);
218
+ const barcodeEnabled = bool(docStep.packing_slip_barcode, true);
219
+ // Eén pakbon per kar. De laatste (of enige) kar van een order is de deelkar en
220
+ // krijgt daarom de deelorder-layout; alle voorgaande karren zijn volle karren.
221
+ const cartTotal = Math.max(1, totalCarriers);
222
+ for (let cartIndex = 1; cartIndex <= cartTotal; cartIndex++) {
223
+ const isFullCart = cartIndex < cartTotal;
224
+ add("print.packing_slip", packingAt, packingAt, {
225
+ documentType: "pakbon",
226
+ release: packingRelease,
227
+ pickStationId: str(docStep.packing_slip_station, "") || null,
228
+ requiresApproval: false,
229
+ pickMode,
230
+ pickUnit,
231
+ cartIndex,
232
+ cartTotal,
233
+ cartLabel: `Kar ${cartIndex} van ${cartTotal}`,
234
+ isFullCart,
235
+ slipVariant: isFullCart ? "full_cart" : "partial_order",
236
+ barcodeEnabled,
237
+ groupIdenticalCarts,
238
+ cartsPerPrint: groupIdenticalCarts ? Math.max(1, num(docStep.packing_slip_carts_per_print, 1)) : null,
239
+ splitIdenticalGroups: false,
240
+ });
241
+ }
220
242
  const stickerRelease = str(docStep.sticker_release, "with_pick_release");
221
243
  const stickerAt = docRelease(stickerRelease, num(docStep.sticker_hours_before, 2));
222
244
  add("print.sticker", stickerAt, stickerAt, {