@flowselections/logistiek-engine 1.0.212 → 1.0.216
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.
- package/db/schema/logistiek-engine.sql +463 -0
- package/dist-lib/components/BeheerPage.d.ts.map +1 -1
- package/dist-lib/components/BeheerPage.js +2 -1
- package/dist-lib/components/DataGereedheidCard.d.ts.map +1 -1
- package/dist-lib/components/DataGereedheidCard.js +24 -5
- package/dist-lib/components/ProefindelingPage.d.ts +4 -0
- package/dist-lib/components/ProefindelingPage.d.ts.map +1 -0
- package/dist-lib/components/ProefindelingPage.js +102 -0
- package/dist-lib/index.d.ts +4 -0
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +4 -0
- package/dist-lib/integrations/supabase/types.d.ts +892 -0
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/loadCarrierPlanner.d.ts +13 -0
- package/dist-lib/lib/loadCarrierPlanner.d.ts.map +1 -1
- package/dist-lib/lib/loadCarrierPlanner.js +25 -7
- package/dist-lib/lib/loadCarrierPlanning.server.d.ts.map +1 -1
- package/dist-lib/lib/loadCarrierPlanning.server.js +69 -83
- package/dist-lib/lib/moduleVersion.d.ts +1 -1
- package/dist-lib/lib/moduleVersion.js +1 -1
- package/dist-lib/lib/planPreview.d.ts +39 -0
- package/dist-lib/lib/planPreview.d.ts.map +1 -0
- package/dist-lib/lib/planPreview.functions.d.ts +13 -0
- package/dist-lib/lib/planPreview.functions.d.ts.map +1 -0
- package/dist-lib/lib/planPreview.functions.js +34 -0
- package/dist-lib/lib/planPreview.js +87 -0
- package/package.json +7 -1
|
@@ -31,6 +31,12 @@ export interface PlannerInputItem {
|
|
|
31
31
|
* Afknijpen op layers_per_carrier zou kunstmatig extra karren opleveren.
|
|
32
32
|
*/
|
|
33
33
|
packing_authoritative?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* 1.0.213: fysiek maximum aantal lagen op de gekozen ladingdrager =
|
|
36
|
+
* floor(hoogte ladingdrager ÷ max(fusthoogte, planthoogte incl. pot)). Alleen gezet
|
|
37
|
+
* als al die maten bekend zijn; nooit een standaardwaarde.
|
|
38
|
+
*/
|
|
39
|
+
fysiek_max_lagen?: number | null;
|
|
34
40
|
}
|
|
35
41
|
export interface PlannerOptions {
|
|
36
42
|
carrier: CarrierProfile;
|
|
@@ -160,5 +166,12 @@ export declare function karCapaciteit(productLagen: Array<number | null | undefi
|
|
|
160
166
|
};
|
|
161
167
|
/** Vulgraad in procenten (heel getal), of null als de capaciteit onbekend is. */
|
|
162
168
|
export declare function karVulgraad(lagen: number, capaciteit: number | null): number | null;
|
|
169
|
+
/**
|
|
170
|
+
* 1.0.213: fysiek maximum aantal lagen = floor(hoogte ladingdrager ÷ laaghoogte),
|
|
171
|
+
* alleen als beide maten bekend zijn (nooit een standaardwaarde). null = niet te controleren.
|
|
172
|
+
*/
|
|
173
|
+
export declare function fysiekeMaxLagen(item: PlannerInputItem, _carrier?: CarrierProfile): number | null;
|
|
174
|
+
/** Fysiek maximum lagen uit hoogte ladingdrager en laaghoogte; null als een maat ontbreekt. */
|
|
175
|
+
export declare function berekenFysiekMaxLagen(dragerHoogteCm: number | null | undefined, fustHoogteCm: number | null | undefined, plantHoogteCm: number | null | undefined): number | null;
|
|
163
176
|
export declare function planLoadUnits(inputs: PlannerInputItem[], options: PlannerOptions): PlannerOutput;
|
|
164
177
|
//# sourceMappingURL=loadCarrierPlanner.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadCarrierPlanner.d.ts","sourceRoot":"","sources":["../../src/lib/loadCarrierPlanner.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAE9C,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEtE,MAAM,WAAW,cAAc;IAC7B,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,aAAa,CAAC;IAC9B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,YAAY,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC9B,8FAA8F;IAC9F,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"loadCarrierPlanner.d.ts","sourceRoot":"","sources":["../../src/lib/loadCarrierPlanner.ts"],"names":[],"mappings":"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"}
|
|
@@ -210,6 +210,21 @@ export function karVulgraad(lagen, capaciteit) {
|
|
|
210
210
|
return null;
|
|
211
211
|
return Math.round((100 * lagen) / capaciteit);
|
|
212
212
|
}
|
|
213
|
+
/**
|
|
214
|
+
* 1.0.213: fysiek maximum aantal lagen = floor(hoogte ladingdrager ÷ laaghoogte),
|
|
215
|
+
* alleen als beide maten bekend zijn (nooit een standaardwaarde). null = niet te controleren.
|
|
216
|
+
*/
|
|
217
|
+
export function fysiekeMaxLagen(item, _carrier) {
|
|
218
|
+
const n = Number(item.fysiek_max_lagen ?? 0);
|
|
219
|
+
return n >= 1 ? Math.floor(n) : null;
|
|
220
|
+
}
|
|
221
|
+
/** Fysiek maximum lagen uit hoogte ladingdrager en laaghoogte; null als een maat ontbreekt. */
|
|
222
|
+
export function berekenFysiekMaxLagen(dragerHoogteCm, fustHoogteCm, plantHoogteCm) {
|
|
223
|
+
const h = Number(dragerHoogteCm ?? 0), f = Number(fustHoogteCm ?? 0), p = Number(plantHoogteCm ?? 0);
|
|
224
|
+
if (!(h > 0) || !(f > 0) || !(p > 0))
|
|
225
|
+
return null;
|
|
226
|
+
return Math.max(1, Math.floor(h / Math.max(f, p) + 1e-9));
|
|
227
|
+
}
|
|
213
228
|
function productLagen(item, carrier) {
|
|
214
229
|
if (carrier.capacity_model === "single")
|
|
215
230
|
return 1;
|
|
@@ -217,6 +232,9 @@ function productLagen(item, carrier) {
|
|
|
217
232
|
const grens = carrier.werkwijze_max_lagen;
|
|
218
233
|
if (typeof grens === "number" && grens > 0 && !item.packing_authoritative)
|
|
219
234
|
l = Math.min(l, Math.round(grens));
|
|
235
|
+
const fys = fysiekeMaxLagen(item, carrier);
|
|
236
|
+
if (fys != null)
|
|
237
|
+
l = Math.min(l, fys);
|
|
220
238
|
return l;
|
|
221
239
|
}
|
|
222
240
|
function accepteert(kar, rest, crates, r) {
|
|
@@ -397,11 +415,9 @@ export function planLoadUnits(inputs, options) {
|
|
|
397
415
|
}))
|
|
398
416
|
.filter((i) => i.plants > 0), r.opts.sortOrder);
|
|
399
417
|
if (carrier.capacity_model === "none") {
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
carts.push(fullCart(it, crates, crates, 1, ++n, r));
|
|
404
|
-
}
|
|
418
|
+
// 1.0.213: zonder ladingdrager kan niets op een kar; geen indeling.
|
|
419
|
+
if (items.length > 0)
|
|
420
|
+
warnings.push("ladingdrager ontbreekt");
|
|
405
421
|
return { carts, warnings };
|
|
406
422
|
}
|
|
407
423
|
// STAP A: volle karren per product (capaciteit = lagen per kar van dat product).
|
|
@@ -468,6 +484,8 @@ export function planLoadUnits(inputs, options) {
|
|
|
468
484
|
}
|
|
469
485
|
for (const kar of open)
|
|
470
486
|
carts.push(samenvatten(kar, rests, carts.length + 1, r));
|
|
471
|
-
|
|
472
|
-
|
|
487
|
+
// 1.0.213: een kar zonder fusten bestaat niet.
|
|
488
|
+
const gevuld = carts.filter((c) => (Array.isArray(c.items) ? c.items : []).some((x) => Number(x?.crates ?? 0) > 0));
|
|
489
|
+
gevuld.forEach((c, i) => { c.cart_number = i + 1; });
|
|
490
|
+
return { carts: gevuld, warnings };
|
|
473
491
|
}
|
|
@@ -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,
|
|
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,EAGtB,MAAM,sBAAsB,CAAC;AAK9B,OAAO,EAA0B,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAErF,OAAO,EAAiE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGvH,OAAO,EAWL,KAAK,YAAY,EACjB,KAAK,YAAY,EAClB,MAAM,kBAAkB,CAAC;AAY1B,wBAAsB,6BAA6B,CAAC,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwB/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,GACtB,WAAW,GACX,eAAe,GACf,kBAAkB,GAClB,aAAa,GACb,SAAS,GACT,MAAM,CAAC;AAgBX;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAQ7E;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,OAAO,GAAG,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAazF;AAaD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,cAAc,CAAC;IACvB,wGAAwG;IACxG,UAAU,EAAE,YAAY,EAAE,CAAC;IAC3B,gEAAgE;IAChE,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACxB,OAAO,EAAE,QAAQ,GAAG,IAAI,EACxB,WAAW,GAAE,YAAY,GAAG,IAAW,GACtC,gBAAgB,CA+BlB;AAGD,MAAM,WAAW,aAAa;IAC5B,mFAAmF;IACnF,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACvC,sFAAsF;IACtF,kBAAkB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IAC5D,kEAAkE;IAClE,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;IACzC,iHAAiH;IACjH,gBAAgB,CAAC,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3F,qEAAqE;IACrE,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5C;;;OAGG;IACH,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,iEAAiE;IACjE,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACtC,gGAAgG;IAChG,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,YAAY,EAAE,CAAA;KAAE,CAAC,CAAC;IAC1E,kFAAkF;IAClF,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjF;AAED,iFAAiF;AACjF,MAAM,WAAW,YAAY;IAC3B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,GAAG,EAAE,MAAM,CAAC;CACb;AAED,6FAA6F;AAC7F,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,SAAS,GAAG,KAAK,GAAG,WAAW,GAAG,aAAa,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;IAC1F,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,6EAA6E;AAC7E,wBAAgB,eAAe,CAC7B,KAAK,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,YAAY,EAAE,CAAA;CAAE,GAAG,SAAS,EAClE,YAAY,EAAE,MAAM,GACnB,YAAY,EAAE,GAAG,IAAI,CAmBvB;AAaD;;;;;;;;;GASG;AACH,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,CAsK7B;AA0ID,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AA6BD,oGAAoG;AACpG,wBAAgB,eAAe,CAAC,MAAM,EAAE,gBAAgB,EAAE,EAAE,KAAK,EAAE,eAAe,EAAE,GAAG,MAAM,EAAE,CAQ9F;AAMD,wBAAsB,mBAAmB,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAO3F;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAcxD,CAAC;AAEF,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI,CAMnG;AAqDD,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,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,WAAW,EAAE,OAAO,CAAC;IACrB,8CAA8C;IAC9C,YAAY,EAAE,UAAU,GAAG,YAAY,CAAC;IACxC,sGAAsG;IACtG,wBAAwB,EAAE,OAAO,CAAC;IAClC,4FAA4F;IAC5F,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAOD,wFAAwF;AACxF,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CA0BzF;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,cAAc,GACjB,OAAO,CAAC,UAAU,GAAG,oBAAoB,CAAC,CAW5C;AAED,2FAA2F;AAC3F,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI,GAAG,cAAc,CAcxG;AAMD;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,gBAAgB,EAAE,EAC1B,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,QAAQ,GAChB,eAAe,EAAE,CAkEnB;AAUD,oFAAoF;AACpF,eAAO,MAAM,qBAAqB,uBAAuB,CAAC;AAK1D;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,aAAa,GAClB,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA4BhC;AAyCD,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,eAAe,EAAE,CAwCtF;AAwED,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,2GAA2G;IAC3G,OAAO,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;IACxC,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,0GAA0G;IAC1G,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAGD,UAAU,qBAAqB;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,uEAAuE;IACvE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,eAAe,EAAE,EACxB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,eAAe,GAAE,mBAAwB,GACxC,qBAAqB,EAAE,CAoCzB;AAqBD;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAC5C,EAAE,EAAE,cAAc,EAClB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,MAAM,EAAE,CAAC,CAoCnB;AAID;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,cAAc,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,YAAY,CAAC,CAyCvB;AAED,qFAAqF;AACrF,eAAO,MAAM,mBAAmB,gFAC+C,CAAC;AAgiDhF,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,cAAc,EAClB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAI9B"}
|
|
@@ -5,7 +5,7 @@
|
|
|
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, bepaalLaagMenging, } from "./loadCarrierPlanner.js";
|
|
8
|
+
import { planLoadUnits, LOAD_CARRIER_PLANNER_VERSION, bepaalLaagMenging, berekenFysiekMaxLagen, } from "./loadCarrierPlanner.js";
|
|
9
9
|
import { traceBatch } from "./trace.server.js";
|
|
10
10
|
import { zonderQuarantaine } from "./quarantaine.js";
|
|
11
11
|
import { zonderStandaardBelading } from "./hoofdverpakking.js";
|
|
@@ -431,6 +431,8 @@ async function beladingOnwaarschijnlijk(sb, inputs, rawRows, profile, profielPer
|
|
|
431
431
|
max_crates_per_layer: d?.maxPerLaag ?? (prof.max_crates_per_layer ?? null),
|
|
432
432
|
standaard_lagen: prof.layers_per_carrier,
|
|
433
433
|
});
|
|
434
|
+
// 1.0.213: fysieke grens aan de lagen per kar voor de planner (alleen met bekende maten).
|
|
435
|
+
i.fysiek_max_lagen = berekenFysiekMaxLagen(d?.h ?? null, mt?.height_mm ? mt.height_mm / 10 : null, mt?.plant ?? null);
|
|
434
436
|
for (const w of fysiek.waarschuwen) {
|
|
435
437
|
waarschuwingen.push({ order_id: i.order_id ?? null, sleutel: `fysiek:${verpakkingSleutel(i.product_id, i)}`, tekst: w });
|
|
436
438
|
}
|
|
@@ -524,82 +526,40 @@ export function ladingdragerUitVerpakking(waarde, actieveCodes) {
|
|
|
524
526
|
return c && actieveCodes.has(c) ? c : null;
|
|
525
527
|
}
|
|
526
528
|
/**
|
|
527
|
-
*
|
|
528
|
-
*
|
|
529
|
+
* 1.0.215: ladingdrager per planregel via de gedeelde databasefunctie
|
|
530
|
+
* logistics_ladingdrager_kies (zelfde keuze als het productoordeel):
|
|
531
|
+
* handmatige keuze → orderregel → artikel → gekoppeld voorraadartikel
|
|
532
|
+
* (products.floriday_trade_item_id) → Floriday-verpakking → werkwijze (met waarschuwing).
|
|
533
|
+
* Fail-closed: lukt de keuze niet, dan blijft de regel leeg (blokkeren).
|
|
529
534
|
*/
|
|
530
|
-
async function bepaalLadingdragers(sb, inputs, rawRows, profiles, handmatig, standaardGebruikt,
|
|
535
|
+
async function bepaalLadingdragers(sb, inputs, rawRows, profiles, handmatig, standaardGebruikt, _standaardCode) {
|
|
531
536
|
const codes = new Set(profiles.map((p) => String(p.code)));
|
|
532
537
|
const uit = new Map();
|
|
533
|
-
const
|
|
538
|
+
const handmatigeCode = handmatig && codes.has(handmatig) ? handmatig : null;
|
|
539
|
+
const regelCode = new Map();
|
|
534
540
|
for (const r of rawRows)
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
.from("product_packings")
|
|
541
|
-
.select("product_id, load_carrier, is_primary, sort_order")
|
|
542
|
-
.in("product_id", productIds);
|
|
543
|
-
if (error)
|
|
544
|
-
throw new Error(`Verpakkingen konden niet worden gelezen: ${error.message}`);
|
|
545
|
-
const rijen = (Array.isArray(data) ? data : []).sort((a, b) => Number(Boolean(b.is_primary)) - Number(Boolean(a.is_primary)) || Number(a.sort_order ?? 0) - Number(b.sort_order ?? 0));
|
|
546
|
-
for (const r of rijen) {
|
|
547
|
-
const pid = String(r.product_id);
|
|
548
|
-
if (perProduct.get(pid))
|
|
549
|
-
continue;
|
|
550
|
-
perProduct.set(pid, ladingdragerUitVerpakking(r.load_carrier, codes));
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
// 1.0.190: eerst de Floriday-verpakking van het artikel
|
|
554
|
-
// (floriday_trade_items_cache.data.packingConfigurations[].loadCarrier, primaire eerst).
|
|
555
|
-
const perFloriday = new Map();
|
|
556
|
-
if (productIds.length > 0) {
|
|
557
|
-
const { data: prods } = await sb
|
|
558
|
-
.from("products")
|
|
559
|
-
.select("id, floriday_trade_item_id")
|
|
560
|
-
.in("id", productIds);
|
|
561
|
-
const tiPerProduct = new Map();
|
|
562
|
-
for (const p of (Array.isArray(prods) ? prods : [])) {
|
|
563
|
-
if (p?.floriday_trade_item_id)
|
|
564
|
-
tiPerProduct.set(String(p.id), String(p.floriday_trade_item_id));
|
|
565
|
-
}
|
|
566
|
-
const tiIds = Array.from(new Set(tiPerProduct.values()));
|
|
567
|
-
if (tiIds.length > 0) {
|
|
568
|
-
const { data: tis } = await sb
|
|
569
|
-
.from("floriday_trade_items_cache")
|
|
570
|
-
.select("floriday_id, data, is_deleted")
|
|
571
|
-
.in("floriday_id", tiIds);
|
|
572
|
-
const lcPerTi = new Map();
|
|
573
|
-
for (const t of (Array.isArray(tis) ? tis : [])) {
|
|
574
|
-
if (t?.is_deleted)
|
|
575
|
-
continue;
|
|
576
|
-
const confs = Array.isArray(t?.data?.packingConfigurations) ? t.data.packingConfigurations : [];
|
|
577
|
-
const sorted = [...confs].sort((a, b) => Number(Boolean(b?.primary)) - Number(Boolean(a?.primary)));
|
|
578
|
-
let code = null;
|
|
579
|
-
for (const c of sorted) {
|
|
580
|
-
code = ladingdragerUitVerpakking(c?.loadCarrier, codes);
|
|
581
|
-
if (code)
|
|
582
|
-
break;
|
|
583
|
-
}
|
|
584
|
-
lcPerTi.set(String(t.floriday_id), code);
|
|
585
|
-
}
|
|
586
|
-
for (const [pid, ti] of tiPerProduct)
|
|
587
|
-
perFloriday.set(pid, lcPerTi.get(ti) ?? null);
|
|
588
|
-
}
|
|
541
|
+
regelCode.set(String(r.id), r.load_carrier_type == null ? null : String(r.load_carrier_type));
|
|
542
|
+
if (handmatigeCode) {
|
|
543
|
+
for (const i of inputs)
|
|
544
|
+
uit.set(i.order_item_id, handmatigeCode);
|
|
545
|
+
return uit;
|
|
589
546
|
}
|
|
590
|
-
const
|
|
591
|
-
const terugval = standaardCode && codes.has(standaardCode) ? standaardCode : null;
|
|
592
|
-
for (const i of inputs) {
|
|
547
|
+
const regels = inputs.map((i) => {
|
|
593
548
|
const base = i.order_item_id.includes("::") ? i.order_item_id.split("::")[0] : i.order_item_id;
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
if (
|
|
599
|
-
|
|
600
|
-
|
|
549
|
+
return { key: i.order_item_id, regel_code: regelCode.get(base) ?? null, product_id: i.product_id ?? null };
|
|
550
|
+
});
|
|
551
|
+
for (let s = 0; s < regels.length; s += 1000) {
|
|
552
|
+
const { data, error } = await sb.rpc("logistics_ladingdrager_kies", { p_regels: regels.slice(s, s + 1000) });
|
|
553
|
+
if (error)
|
|
554
|
+
throw new Error(`Ladingdrager kon niet worden bepaald: ${error.message}`);
|
|
555
|
+
const map = (data && typeof data === "object" ? data : {});
|
|
556
|
+
for (const r of regels.slice(s, s + 1000)) {
|
|
557
|
+
const k = map[r.key];
|
|
558
|
+
const code = k?.code && codes.has(String(k.code)) ? String(k.code) : null;
|
|
559
|
+
if (code && k?.bron === "werkwijze")
|
|
560
|
+
standaardGebruikt?.add(r.key);
|
|
561
|
+
uit.set(r.key, code);
|
|
601
562
|
}
|
|
602
|
-
uit.set(i.order_item_id, code);
|
|
603
563
|
}
|
|
604
564
|
return uit;
|
|
605
565
|
}
|
|
@@ -1318,7 +1278,7 @@ async function replanBufferUnlocked(sb, bufferId, options = {}) {
|
|
|
1318
1278
|
beladingWaarschuwingen.push({
|
|
1319
1279
|
order_id: oid || null,
|
|
1320
1280
|
sleutel: "ladingdrager_standaard",
|
|
1321
|
-
tekst: `Ladingdrager niet
|
|
1281
|
+
tekst: `Ladingdrager uit de werkwijze, niet uit het artikel (${namen.slice(0, 5).join(", ")}).`,
|
|
1322
1282
|
});
|
|
1323
1283
|
}
|
|
1324
1284
|
}
|
|
@@ -1368,7 +1328,7 @@ async function replanBufferUnlocked(sb, bufferId, options = {}) {
|
|
|
1368
1328
|
}
|
|
1369
1329
|
// Groepsregel naast ledenregels: niet ingedeeld, wel zichtbaar gemeld bij de order.
|
|
1370
1330
|
for (const n of expandNotes) {
|
|
1371
|
-
if (!n.order_id)
|
|
1331
|
+
if (!n.order_id || options.dryRun)
|
|
1372
1332
|
continue;
|
|
1373
1333
|
const { error: noteError } = await sb.rpc("logistics_trace_order_step", {
|
|
1374
1334
|
p_order_id: n.order_id,
|
|
@@ -1533,9 +1493,9 @@ async function replanBufferUnlocked(sb, bufferId, options = {}) {
|
|
|
1533
1493
|
}
|
|
1534
1494
|
if (options.carrierType && !bekendeCodes.has(options.carrierType))
|
|
1535
1495
|
nietInBeheer.set(options.carrierType, []);
|
|
1536
|
-
if (nietInBeheer.size > 0
|
|
1496
|
+
if (nietInBeheer.size > 0) {
|
|
1537
1497
|
const reason = ladingdragerNietInBeheerTekst(nietInBeheer);
|
|
1538
|
-
const { error: blockError } = await sb.rpc("logistics_plan_block", {
|
|
1498
|
+
const { error: blockError } = options.dryRun ? { error: null } : await sb.rpc("logistics_plan_block", {
|
|
1539
1499
|
p_order_ids: orderIds,
|
|
1540
1500
|
p_reason: reason,
|
|
1541
1501
|
p_details: {
|
|
@@ -1599,9 +1559,9 @@ async function replanBufferUnlocked(sb, bufferId, options = {}) {
|
|
|
1599
1559
|
// 1.0.198: gewicht alleen relevant als de ladingdrager een kg-grens heeft.
|
|
1600
1560
|
const heeftKgGrens = Number(guardProfile.max_weight_kg) > 0;
|
|
1601
1561
|
const zonderGewicht = heeftKgGrens ? inputs.filter((i) => !(Number(i.weight_per_crate) > 0) && i.plants > 0) : [];
|
|
1602
|
-
if (zonderGewicht.length > 0 && rules?.gewichtVerplicht === true
|
|
1562
|
+
if (zonderGewicht.length > 0 && rules?.gewichtVerplicht === true) {
|
|
1603
1563
|
const reason = gewichtOnbekendTekst(zonderGewicht.map((i) => i.product_name));
|
|
1604
|
-
const { error: blockError } = await sb.rpc("logistics_plan_block", {
|
|
1564
|
+
const { error: blockError } = options.dryRun ? { error: null } : await sb.rpc("logistics_plan_block", {
|
|
1605
1565
|
p_order_ids: orderIds,
|
|
1606
1566
|
p_reason: reason,
|
|
1607
1567
|
p_details: { reason_code: "gewicht_onbekend", bufferId, path: "typescript",
|
|
@@ -1629,7 +1589,7 @@ async function replanBufferUnlocked(sb, bufferId, options = {}) {
|
|
|
1629
1589
|
}
|
|
1630
1590
|
// Planten per fust is altijd nodig (ook zonder lagenmodel): fusten = planten / planten per fust.
|
|
1631
1591
|
const blokkeerOnvolledig = onvolledig.filter((o) => o.velden.includes("plants_per_crate") || (needsBelading && !useDimensions));
|
|
1632
|
-
if ((blokkeerOnvolledig.length > 0 || onbekendePlanten.length > 0)
|
|
1592
|
+
if ((blokkeerOnvolledig.length > 0 || onbekendePlanten.length > 0)) {
|
|
1633
1593
|
const delen = [
|
|
1634
1594
|
...blokkeerOnvolledig.slice(0, 10).map((o) => `${o.item.product_name}: ${o.velden.map((v) => VELD_NAAM[v]).join(", ")} onbekend`),
|
|
1635
1595
|
...onbekendePlanten.slice(0, 10).map((o) => `${o.naam}: eenheid fust zonder planten per fust`),
|
|
@@ -1637,7 +1597,7 @@ async function replanBufferUnlocked(sb, bufferId, options = {}) {
|
|
|
1637
1597
|
const reason = `Belading onvolledig voor ${blokkeerOnvolledig.length + onbekendePlanten.length} orderregel(s): ${delen.join("; ")}. ` +
|
|
1638
1598
|
WAAR_INVULLEN;
|
|
1639
1599
|
console.error(`[logistiek-engine] buffer ${bufferId} geblokkeerd: ${reason}`);
|
|
1640
|
-
const { error: blockError } = await sb.rpc("logistics_plan_block", {
|
|
1600
|
+
const { error: blockError } = options.dryRun ? { error: null } : await sb.rpc("logistics_plan_block", {
|
|
1641
1601
|
p_order_ids: orderIds,
|
|
1642
1602
|
p_reason: reason,
|
|
1643
1603
|
p_details: {
|
|
@@ -1668,16 +1628,18 @@ async function replanBufferUnlocked(sb, bufferId, options = {}) {
|
|
|
1668
1628
|
};
|
|
1669
1629
|
}
|
|
1670
1630
|
// 1.0.179 (punt 3): plausibiliteit, alle ordersoorten. Eén bevestiging per order en verpakking.
|
|
1671
|
-
|
|
1631
|
+
// 1.0.213: ook in droge modus rekenen (alleen lezen); schrijven alleen buiten droge modus.
|
|
1632
|
+
{
|
|
1672
1633
|
const oordeel = await beladingOnwaarschijnlijk(sb, inputs, rawRows, guardProfile, profielPerRegel);
|
|
1673
1634
|
const onwaarschijnlijk = oordeel.blokkeren;
|
|
1674
1635
|
// 1.0.197: fysiek onmogelijk = altijd blokkeren, niet te bevestigen; alleen gegevens aanpassen helpt.
|
|
1675
1636
|
if (oordeel.onmogelijk.length > 0) {
|
|
1676
1637
|
beladingWaarschuwingen.push(...oordeel.waarschuwingen);
|
|
1677
|
-
|
|
1638
|
+
if (!options.dryRun)
|
|
1639
|
+
await bewaarBeladingWaarschuwingen(sb, orderIds, beladingWaarschuwingen, warnings);
|
|
1678
1640
|
const reason = `Belading fysiek onmogelijk: ${oordeel.onmogelijk.slice(0, 10).map((o) => o.redenen.join("; ")).join(" | ")}. ` +
|
|
1679
1641
|
"Pas de gegevens aan in Beheer → Gegevens voor karindeling; bevestigen is hier niet mogelijk.";
|
|
1680
|
-
const { error: blockError } = await sb.rpc("logistics_plan_block", {
|
|
1642
|
+
const { error: blockError } = options.dryRun ? { error: null } : await sb.rpc("logistics_plan_block", {
|
|
1681
1643
|
p_order_ids: orderIds,
|
|
1682
1644
|
p_reason: reason,
|
|
1683
1645
|
p_details: {
|
|
@@ -1707,11 +1669,12 @@ async function replanBufferUnlocked(sb, bufferId, options = {}) {
|
|
|
1707
1669
|
beladingWaarschuwingen.push(...oordeel.waarschuwingen);
|
|
1708
1670
|
for (const w of beladingWaarschuwingen)
|
|
1709
1671
|
warnings.push(w.tekst);
|
|
1710
|
-
|
|
1672
|
+
if (!options.dryRun)
|
|
1673
|
+
await bewaarBeladingWaarschuwingen(sb, orderIds, beladingWaarschuwingen, warnings);
|
|
1711
1674
|
if (onwaarschijnlijk.length > 0) {
|
|
1712
1675
|
const reason = `Belading onwaarschijnlijk: ${onwaarschijnlijk.slice(0, 10).map((o) => `${o.product}: ${o.redenen.join("; ")}`).join(" | ")}. ` +
|
|
1713
1676
|
"Kantoor moet dit bevestigen voordat er wordt ingedeeld.";
|
|
1714
|
-
const { error: blockError } = await sb.rpc("logistics_plan_block", {
|
|
1677
|
+
const { error: blockError } = options.dryRun ? { error: null } : await sb.rpc("logistics_plan_block", {
|
|
1715
1678
|
p_order_ids: orderIds,
|
|
1716
1679
|
p_reason: reason,
|
|
1717
1680
|
p_details: { reason_code: "belading_onwaarschijnlijk", bufferId, path: "typescript", bevestigen: onwaarschijnlijk.slice(0, 50) },
|
|
@@ -1838,6 +1801,7 @@ async function replanBufferUnlocked(sb, bufferId, options = {}) {
|
|
|
1838
1801
|
}
|
|
1839
1802
|
else {
|
|
1840
1803
|
// Ladingdrager per orderregel bepalen en per type een ronde draaien.
|
|
1804
|
+
const geenLadingdrager = [];
|
|
1841
1805
|
const groups = new Map();
|
|
1842
1806
|
for (const input of inputs) {
|
|
1843
1807
|
const code = ladingdragerPerRegel.get(input.order_item_id) ?? defaultProfile.code;
|
|
@@ -1871,12 +1835,34 @@ async function replanBufferUnlocked(sb, bufferId, options = {}) {
|
|
|
1871
1835
|
ownCarrierFromLayers: settings?.own_cart_from_layers ?? null,
|
|
1872
1836
|
sortOrder: "none",
|
|
1873
1837
|
});
|
|
1838
|
+
if (profile.capacity_model === "none" && list.length > 0) {
|
|
1839
|
+
geenLadingdrager.push(...list.map((x) => x.product_name));
|
|
1840
|
+
continue;
|
|
1841
|
+
}
|
|
1874
1842
|
plannedCarts = plannedCarts.concat(result.carts);
|
|
1875
1843
|
warnings.push(...result.warnings);
|
|
1876
1844
|
}
|
|
1877
1845
|
plannedCarts.forEach((c, idx) => {
|
|
1878
1846
|
c.cart_number = idx + 1;
|
|
1879
1847
|
});
|
|
1848
|
+
// 1.0.213: een product zonder ladingdrager (NONE / losse levering) kan niet op een kar: geen indeling.
|
|
1849
|
+
if (geenLadingdrager.length > 0) {
|
|
1850
|
+
const namen = Array.from(new Set(geenLadingdrager)).slice(0, 10).join(", ");
|
|
1851
|
+
const reason = `Geen indeling: ladingdrager ontbreekt (${namen}). Stel de ladingdrager van de hoofdverpakking in.`;
|
|
1852
|
+
if (!options.dryRun) {
|
|
1853
|
+
const { error: blockError } = await sb.rpc("logistics_plan_block", {
|
|
1854
|
+
p_order_ids: orderIds,
|
|
1855
|
+
p_reason: reason,
|
|
1856
|
+
p_details: { reason_code: "ladingdrager_ontbreekt", bufferId, path: "typescript", producten: Array.from(new Set(geenLadingdrager)).slice(0, 50) },
|
|
1857
|
+
});
|
|
1858
|
+
if (blockError)
|
|
1859
|
+
warnings.push(`Blokkade kon niet worden vastgelegd: ${blockError.message}`);
|
|
1860
|
+
}
|
|
1861
|
+
return {
|
|
1862
|
+
ok: false, bufferId, orderIds, cartsCreated: 0, replacedManualCount: 0, usedFloridayPacking,
|
|
1863
|
+
warnings: [...warnings, reason], skipped: "blocked", blockedReason: reason, beladingSources,
|
|
1864
|
+
};
|
|
1865
|
+
}
|
|
1880
1866
|
}
|
|
1881
1867
|
// Veiligheidsgrens: een onrealistisch grote uitkomst wordt niet afgekapt maar
|
|
1882
1868
|
// geblokkeerd. Een half plan laat planten stilzwijgend uit de pickstroom vallen.
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const MODULE_VERSION = "1.0.
|
|
1
|
+
export declare const MODULE_VERSION = "1.0.216";
|
|
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.
|
|
2
|
+
export const MODULE_VERSION = "1.0.216";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { PlannedLoadUnit } from "./loadCarrierPlanner.js";
|
|
2
|
+
export interface PlanPreviewRegel {
|
|
3
|
+
orderItemId: string;
|
|
4
|
+
product: string;
|
|
5
|
+
fust: number;
|
|
6
|
+
stuks: number;
|
|
7
|
+
}
|
|
8
|
+
export interface PlanPreviewKar {
|
|
9
|
+
karNummer: number;
|
|
10
|
+
ladingdrager: string;
|
|
11
|
+
lagen: number;
|
|
12
|
+
platen: number;
|
|
13
|
+
vulgraadPct: number;
|
|
14
|
+
teHoog: boolean;
|
|
15
|
+
karTekst: string;
|
|
16
|
+
regels: PlanPreviewRegel[];
|
|
17
|
+
}
|
|
18
|
+
export interface PlanPreviewOrder {
|
|
19
|
+
orderId: string;
|
|
20
|
+
orderNummer: string | null;
|
|
21
|
+
ok: boolean;
|
|
22
|
+
reden: string | null;
|
|
23
|
+
waarschuwingen: string[];
|
|
24
|
+
karren: PlanPreviewKar[];
|
|
25
|
+
}
|
|
26
|
+
type DryRun = (sb: any, bufferId: string) => Promise<{
|
|
27
|
+
ok: boolean;
|
|
28
|
+
blockedReason?: string;
|
|
29
|
+
warnings?: string[];
|
|
30
|
+
carts?: PlannedLoadUnit[];
|
|
31
|
+
} | null>;
|
|
32
|
+
/** Vulgraad zoals Floriday: Σ per regel (lagen ÷ lagen per kar van die regel). */
|
|
33
|
+
export declare function vulgraadFloriday(items: PlannedLoadUnit["items"]): number;
|
|
34
|
+
export declare function lagenVanKar(kar: PlannedLoadUnit): number;
|
|
35
|
+
/** Zelfde vorm als karTekst in de database: "6,6 lagen · Deense container + 6 platen · 83 %". */
|
|
36
|
+
export declare function karTekstVan(lagen: number, ladingdrager: string, pct: number): string;
|
|
37
|
+
export declare function bouwPlanPreview(sb: any, orderIds: string[], dryRun: DryRun): Promise<PlanPreviewOrder[]>;
|
|
38
|
+
export {};
|
|
39
|
+
//# sourceMappingURL=planPreview.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planPreview.d.ts","sourceRoot":"","sources":["../../src/lib/planPreview.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAG5D,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AACD,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,gBAAgB,EAAE,CAAC;CAC5B;AACD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,MAAM,EAAE,cAAc,EAAE,CAAC;CAC1B;AAED,KAAK,MAAM,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,eAAe,EAAE,CAAA;CAAE,GAAG,IAAI,CAAC,CAAC;AAIrJ,kFAAkF;AAClF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,GAAG,MAAM,CAOxE;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAKxD;AAED,iGAAiG;AACjG,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAKpF;AAED,wBAAsB,eAAe,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAyD9G"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type PlanPreviewOrder } from "./planPreview.js";
|
|
2
|
+
export declare const logisticsPlanPreview: import("@tanstack/start-client-core").RequiredFetcher<readonly [import("@tanstack/start-client-core").FunctionMiddlewareAfterServer<{}, unknown, undefined, undefined, undefined, undefined, undefined>, import("@tanstack/start-client-core").FunctionMiddlewareAfterServer<{}, unknown, undefined, {
|
|
3
|
+
supabase: import("../integrations/supabase/auth-middleware.js").AuthedSupabaseClient;
|
|
4
|
+
userId: string;
|
|
5
|
+
claims: import("@supabase/auth-js").User;
|
|
6
|
+
}, undefined, undefined, undefined>], (input: {
|
|
7
|
+
orderIds: string[];
|
|
8
|
+
}) => {
|
|
9
|
+
orderIds: string[];
|
|
10
|
+
}, Promise<{
|
|
11
|
+
orders: PlanPreviewOrder[];
|
|
12
|
+
}>>;
|
|
13
|
+
//# sourceMappingURL=planPreview.functions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planPreview.functions.d.ts","sourceRoot":"","sources":["../../src/lib/planPreview.functions.ts"],"names":[],"mappings":"AAMA,OAAO,EAAmB,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAIvE,eAAO,MAAM,oBAAoB;;;;8CAEP;IAAE,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE;;;YAQQ,gBAAgB,EAAE;GAatE,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// 1.0.213: logistics_plan_preview — karindeling narekenen zonder iets te schrijven.
|
|
2
|
+
// Zelfde planner en werkwijze als de wachtrij (replanBufferInternal), maar in droge modus:
|
|
3
|
+
// geen karren, geen wachtrij, geen events, geen blokkades, geen bufferbesluit.
|
|
4
|
+
import { createServerFn } from "@tanstack/react-start";
|
|
5
|
+
import { requireSupabaseAuth } from "../integrations/supabase/auth-middleware.js";
|
|
6
|
+
import { readableServerErrors } from "./readableServerErrors.js";
|
|
7
|
+
import { bouwPlanPreview } from "./planPreview.js";
|
|
8
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
9
|
+
export const logisticsPlanPreview = createServerFn({ method: "POST" })
|
|
10
|
+
.middleware([readableServerErrors, requireSupabaseAuth])
|
|
11
|
+
.inputValidator((input) => {
|
|
12
|
+
const ids = Array.isArray(input?.orderIds) ? input.orderIds.map(String) : [];
|
|
13
|
+
if (ids.length === 0)
|
|
14
|
+
throw new Error("Geef minimaal één order op.");
|
|
15
|
+
if (ids.length > 50)
|
|
16
|
+
throw new Error(`Maximaal 50 orders per voorbeeld (ontvangen: ${ids.length}).`);
|
|
17
|
+
const fout = ids.find((x) => !UUID_RE.test(x));
|
|
18
|
+
if (fout)
|
|
19
|
+
throw new Error(`Ongeldig order-id: ${fout}`);
|
|
20
|
+
return { orderIds: Array.from(new Set(ids)) };
|
|
21
|
+
})
|
|
22
|
+
.handler(async ({ data, context }) => {
|
|
23
|
+
// Toegang: ingelogd, via dezelfde interne guard als de rest van de Engine (fail-closed).
|
|
24
|
+
const { error: gErr } = await context.supabase.rpc("logistics_acc_guard", {
|
|
25
|
+
p_level: "ingelogd",
|
|
26
|
+
p_fn: "logistics_plan_preview",
|
|
27
|
+
});
|
|
28
|
+
if (gErr)
|
|
29
|
+
throw new Error(`Geen toegang: ${gErr.message}`);
|
|
30
|
+
const { supabaseAdmin } = await import("../integrations/supabase/client.server.js");
|
|
31
|
+
const { replanBufferInternal } = await import("./loadCarrierPlanning.server.js");
|
|
32
|
+
const orders = await bouwPlanPreview(supabaseAdmin, data.orderIds, (sb, bufferId) => replanBufferInternal(sb, bufferId, { dryRun: true }));
|
|
33
|
+
return { orders };
|
|
34
|
+
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { extraPlaten } from "./extraPlaten.js";
|
|
2
|
+
const nl1 = (n) => String(Math.round(n * 10) / 10).replace(".", ",");
|
|
3
|
+
/** Vulgraad zoals Floriday: Σ per regel (lagen ÷ lagen per kar van die regel). */
|
|
4
|
+
export function vulgraadFloriday(items) {
|
|
5
|
+
let v = 0;
|
|
6
|
+
for (const it of Array.isArray(items) ? items : []) {
|
|
7
|
+
const cpl = Number(it.crates_per_layer) || 0, lpc = Number(it.layers_per_cart) || 0;
|
|
8
|
+
if (cpl > 0 && lpc > 0)
|
|
9
|
+
v += Number(it.crates) / cpl / lpc;
|
|
10
|
+
}
|
|
11
|
+
return v;
|
|
12
|
+
}
|
|
13
|
+
export function lagenVanKar(kar) {
|
|
14
|
+
const t = Number(kar.total_layers_used);
|
|
15
|
+
if (Number.isFinite(t) && t > 0)
|
|
16
|
+
return t;
|
|
17
|
+
return (Array.isArray(kar.items) ? kar.items : []).reduce((s, it) => s + (Number(it.crates_per_layer) > 0 ? Number(it.crates) / Number(it.crates_per_layer) : 0), 0);
|
|
18
|
+
}
|
|
19
|
+
/** Zelfde vorm als karTekst in de database: "6,6 lagen · Deense container + 6 platen · 83 %". */
|
|
20
|
+
export function karTekstVan(lagen, ladingdrager, pct) {
|
|
21
|
+
const p = extraPlaten(lagen) ?? 0;
|
|
22
|
+
const laagWoord = Math.round(lagen * 10) / 10 === 1 ? "laag" : "lagen";
|
|
23
|
+
const platen = p === 0 ? "" : p === 1 ? " + 1 plaat" : ` + ${p} platen`;
|
|
24
|
+
return `${nl1(lagen)} ${laagWoord} · ${ladingdrager}${platen} · ${Math.round(pct)} %`;
|
|
25
|
+
}
|
|
26
|
+
export async function bouwPlanPreview(sb, orderIds, dryRun) {
|
|
27
|
+
const { data: rows, error } = await sb.from("orders").select("id, order_number, buffer_id").in("id", orderIds);
|
|
28
|
+
if (error)
|
|
29
|
+
throw new Error(`Orders konden niet worden gelezen: ${error.message}`);
|
|
30
|
+
const orders = Array.isArray(rows) ? rows : [];
|
|
31
|
+
const { data: typen } = await sb.from("load_carrier_types").select("code, name");
|
|
32
|
+
const naamVan = new Map((Array.isArray(typen) ? typen : []).map((t) => [String(t.code), String(t.name ?? t.code)]));
|
|
33
|
+
const perBuffer = new Map();
|
|
34
|
+
const uit = [];
|
|
35
|
+
for (const id of orderIds) {
|
|
36
|
+
const o = orders.find((x) => String(x.id) === id);
|
|
37
|
+
if (!o) {
|
|
38
|
+
uit.push({ orderId: id, orderNummer: null, ok: false, reden: "Order niet gevonden.", waarschuwingen: [], karren: [] });
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
// Geen bufferbesluit nemen in een voorbeeld: dat zou schrijven.
|
|
42
|
+
if (!o.buffer_id) {
|
|
43
|
+
uit.push({ orderId: id, orderNummer: o.order_number ?? null, ok: false,
|
|
44
|
+
reden: "De order heeft nog geen buffer; het voorbeeld neemt dat besluit niet (zou iets opslaan).", waarschuwingen: [], karren: [] });
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const bid = String(o.buffer_id);
|
|
48
|
+
if (!perBuffer.has(bid))
|
|
49
|
+
perBuffer.set(bid, await dryRun(sb, bid));
|
|
50
|
+
const res = perBuffer.get(bid);
|
|
51
|
+
const carts = Array.isArray(res?.carts) ? res.carts : [];
|
|
52
|
+
const karren = carts
|
|
53
|
+
.filter((c) => (Array.isArray(c.items) ? c.items : []).some((it) => String(it.order_id ?? "") === id))
|
|
54
|
+
.map((c) => {
|
|
55
|
+
const lagen = lagenVanKar(c);
|
|
56
|
+
const vul = vulgraadFloriday(c.items);
|
|
57
|
+
const drager = naamVan.get(String(c.carrier_type)) ?? String(c.carrier_type ?? "Ladingdrager");
|
|
58
|
+
return {
|
|
59
|
+
karNummer: c.cart_number,
|
|
60
|
+
ladingdrager: drager,
|
|
61
|
+
lagen: Math.round(lagen * 100) / 100,
|
|
62
|
+
platen: extraPlaten(lagen) ?? 0,
|
|
63
|
+
vulgraadPct: Math.round(vul * 100),
|
|
64
|
+
teHoog: vul > 1.001,
|
|
65
|
+
karTekst: karTekstVan(lagen, drager, vul * 100),
|
|
66
|
+
regels: (Array.isArray(c.items) ? c.items : [])
|
|
67
|
+
.filter((it) => String(it.order_id ?? "") === id)
|
|
68
|
+
.map((it) => ({ orderItemId: it.order_item_id, product: it.product_name, fust: Number(it.crates) || 0, stuks: Number(it.plants) || 0 })),
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
uit.push({
|
|
72
|
+
orderId: id,
|
|
73
|
+
orderNummer: o.order_number ?? null,
|
|
74
|
+
ok: Boolean(res?.ok),
|
|
75
|
+
reden: res
|
|
76
|
+
? res.ok
|
|
77
|
+
? karren.length === 0
|
|
78
|
+
? "Geen nieuwe karren: alle fusten staan al op vastgelegde karren (geprint, gescand of gecontroleerd); die blijven zoals ze zijn."
|
|
79
|
+
: null
|
|
80
|
+
: res.blockedReason ?? "Niet ingedeeld."
|
|
81
|
+
: "Geen buffer gevonden.",
|
|
82
|
+
waarschuwingen: Array.isArray(res?.warnings) ? res.warnings : [],
|
|
83
|
+
karren,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
return uit;
|
|
87
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flowselections/logistiek-engine",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.216",
|
|
4
4
|
"flowselections": {
|
|
5
5
|
"moduleId": "logistiek-engine",
|
|
6
6
|
"pages": [
|
|
@@ -52,6 +52,12 @@
|
|
|
52
52
|
"export": "BeheerPage",
|
|
53
53
|
"route": "logistiek-engine/beheer",
|
|
54
54
|
"title": "Beheer"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"export": "ProefindelingPage",
|
|
58
|
+
"route": "logistiek-engine/proefindeling",
|
|
59
|
+
"title": "Proefindeling",
|
|
60
|
+
"nav": false
|
|
55
61
|
}
|
|
56
62
|
],
|
|
57
63
|
"serverRoutes": [
|