@flowselections/logistiek-engine 1.0.15 → 1.0.16

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.
@@ -45,6 +45,12 @@ export interface BeladingRules {
45
45
  export declare function loadBeladingRules(sb: SupabaseClient): Promise<BeladingRules | null>;
46
46
  /** Past de grenzen uit de werkwijze toe op het capaciteitsprofiel van een ladingdrager. */
47
47
  export declare function applyRulesToProfile(profile: CarrierProfile, rules: BeladingRules | null): CarrierProfile;
48
+ /**
49
+ * Verdeelt de planten over ladingdragers volgens de Floriday-verhouding:
50
+ * planten per kar = pieces_per_package x packages_per_layer x layers_per_load_carrier.
51
+ * Geen optimalisatie, geen mengregels, geen laagherverdeling — alleen vullen.
52
+ */
53
+ export declare function planByFloridayPacking(inputs: PlannerInputItem[], profile: CarrierProfile, packing: Belading): PlannedLoadUnit[];
48
54
  export interface ReplanResult {
49
55
  ok: boolean;
50
56
  bufferId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"loadCarrierPlanning.server.d.ts","sourceRoot":"","sources":["../../src/lib/loadCarrierPlanning.server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"loadCarrierPlanning.server.d.ts","sourceRoot":"","sources":["../../src/lib/loadCarrierPlanning.server.ts"],"names":[],"mappings":"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"}
@@ -342,6 +342,75 @@ export function applyRulesToProfile(profile, rules) {
342
342
  };
343
343
  }
344
344
  // ---------------------------------------------------------------------------
345
+ // Overname-pad: de beladingverhouding van Floriday letterlijk volgen
346
+ // ---------------------------------------------------------------------------
347
+ /**
348
+ * Verdeelt de planten over ladingdragers volgens de Floriday-verhouding:
349
+ * planten per kar = pieces_per_package x packages_per_layer x layers_per_load_carrier.
350
+ * Geen optimalisatie, geen mengregels, geen laagherverdeling — alleen vullen.
351
+ */
352
+ export function planByFloridayPacking(inputs, profile, packing) {
353
+ const ppc = Math.max(1, packing.plants_per_crate);
354
+ const cpl = Math.max(1, packing.crates_per_layer);
355
+ const lpc = Math.max(1, packing.layers_per_cart);
356
+ const perCart = ppc * cpl * lpc;
357
+ const carts = [];
358
+ let current = null;
359
+ let currentPlants = 0;
360
+ const openCart = () => {
361
+ current = {
362
+ cart_number: carts.length + 1,
363
+ carrier_type: profile.code,
364
+ carrier_type_id: profile.id ?? null,
365
+ source: "auto",
366
+ is_complete: false,
367
+ occupancy_pct: 0,
368
+ total_layers_used: 0,
369
+ max_layers: lpc,
370
+ weight_kg: null,
371
+ items: [],
372
+ };
373
+ currentPlants = 0;
374
+ carts.push(current);
375
+ };
376
+ for (const input of inputs) {
377
+ let left = Math.max(0, Math.round(input.plants));
378
+ while (left > 0) {
379
+ if (!current || currentPlants >= perCart)
380
+ openCart();
381
+ const cart = current;
382
+ const take = Math.min(left, perCart - currentPlants);
383
+ const crates = Math.max(1, Math.ceil(take / ppc));
384
+ const layerFraction = crates / cpl;
385
+ const item = {
386
+ order_item_id: input.order_item_id,
387
+ order_id: input.order_id ?? null,
388
+ product_id: input.product_id,
389
+ product_name: input.product_name,
390
+ crates,
391
+ plants: take,
392
+ boxes: crates,
393
+ weight_kg: input.weight_per_crate != null ? Number((input.weight_per_crate * crates).toFixed(2)) : null,
394
+ plants_per_crate: ppc,
395
+ crates_per_layer: cpl,
396
+ layers_per_cart: lpc,
397
+ layer_fraction: Number(layerFraction.toFixed(3)),
398
+ layer_share_pct: Number(((100 * layerFraction) / lpc).toFixed(2)),
399
+ };
400
+ cart.items.push(item);
401
+ currentPlants += take;
402
+ left -= take;
403
+ cart.total_layers_used = Number(cart.items.reduce((s, i) => s + i.layer_fraction, 0).toFixed(2));
404
+ cart.occupancy_pct = Number(((100 * currentPlants) / perCart).toFixed(1));
405
+ cart.is_complete = currentPlants >= perCart;
406
+ cart.weight_kg = cart.items.some((i) => i.weight_kg != null)
407
+ ? Number(cart.items.reduce((s, i) => s + (i.weight_kg ?? 0), 0).toFixed(2))
408
+ : null;
409
+ }
410
+ }
411
+ return carts;
412
+ }
413
+ // ---------------------------------------------------------------------------
345
414
  // Herplannen van een buffer
346
415
  // ---------------------------------------------------------------------------
347
416
  /** Maximaal aantal ladingdragers dat één orderbuffer mag opleveren. */
@@ -447,25 +516,22 @@ export async function replanBufferInternal(sb, bufferId, options = {}) {
447
516
  }
448
517
  let plannedCarts = [];
449
518
  let usedFloridayPacking = false;
519
+ // Overname-pad: één order in de buffer én een volledige Floriday-verpakking.
520
+ // Dan neemt de engine de verhouding van Floriday over en optimaliseert niet.
521
+ // (De oude tak eiste `floriday_packing.carts` als array; Floriday stuurt zo'n
522
+ // kant-en-klare karrenlijst nergens mee, die tak is nooit genomen en is
523
+ // daarom verwijderd.)
450
524
  const solo = orderRows.length === 1 ? orderRows[0] : null;
451
- const floridayPacking = solo?.custom_fields?.floriday_packing ?? null;
452
- const isFo = solo && (solo.custom_fields?.source === "floriday" || floridayPacking?.pieces_per_package);
453
- if (isFo && floridayPacking && Array.isArray(floridayPacking.carts)) {
525
+ const soloPacking = solo ? beladingFromFloridayPacking(solo.custom_fields?.floriday_packing) : null;
526
+ const takeoverProfile = profileFor(profiles, options.carrierType ?? defaultProfile.code);
527
+ const takeoverAllowed = takeoverProfile.capacity_model === "layered" || takeoverProfile.capacity_model === "stacked";
528
+ if (solo && soloPacking && takeoverAllowed) {
454
529
  usedFloridayPacking = true;
455
- const code = options.carrierType ?? floridayPacking.carrier_type ?? defaultProfile.code;
456
- const profile = profileFor(profiles, code);
457
- plannedCarts = floridayPacking.carts.map((c, idx) => ({
458
- cart_number: idx + 1,
459
- carrier_type: profile.code,
460
- carrier_type_id: profile.id ?? null,
461
- source: "auto",
462
- is_complete: Boolean(c.is_complete),
463
- occupancy_pct: Number(c.occupancy_pct ?? 100),
464
- total_layers_used: Number(c.total_layers_used ?? profile.layers_per_carrier),
465
- max_layers: profile.layers_per_carrier,
466
- weight_kg: null,
467
- items: Array.isArray(c.items) ? c.items : [],
468
- }));
530
+ plannedCarts = planByFloridayPacking(inputs, takeoverProfile, soloPacking);
531
+ console.log(`[logistiek-engine] buffer ${bufferId}: overname Floriday-verpakking ` +
532
+ `(${soloPacking.plants_per_crate}x${soloPacking.crates_per_layer}x${soloPacking.layers_per_cart} = ` +
533
+ `${soloPacking.plants_per_crate * soloPacking.crates_per_layer * soloPacking.layers_per_cart} planten/kar) ` +
534
+ `-> ${plannedCarts.length} ladingdragers`);
469
535
  }
470
536
  else {
471
537
  // Ladingdrager per orderregel bepalen en per type een ronde draaien.