@flowselections/logistiek-engine 1.0.236 → 1.0.238
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 +1260 -0
- package/dist-lib/components/StandaardgegevensCard.d.ts.map +1 -1
- package/dist-lib/components/StandaardgegevensCard.js +48 -2
- package/dist-lib/components/rule-engine/RuleFieldInput.d.ts.map +1 -1
- package/dist-lib/components/rule-engine/RuleFieldInput.js +6 -2
- package/dist-lib/hooks/usePickstations.d.ts +3 -0
- package/dist-lib/hooks/usePickstations.d.ts.map +1 -1
- package/dist-lib/hooks/usePickstations.js +19 -3
- package/dist-lib/integrations/supabase/types.d.ts +1519 -0
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/logisticsPlanner.d.ts.map +1 -1
- package/dist-lib/lib/logisticsPlanner.js +1 -11
- package/dist-lib/lib/moduleVersion.d.ts +1 -1
- package/dist-lib/lib/moduleVersion.js +1 -1
- package/dist-lib/lib/ruleEngineSchema.js +5 -5
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StandaardgegevensCard.d.ts","sourceRoot":"","sources":["../../src/components/StandaardgegevensCard.tsx"],"names":[],"mappings":"AAaA,wBAAgB,qBAAqB,
|
|
1
|
+
{"version":3,"file":"StandaardgegevensCard.d.ts","sourceRoot":"","sources":["../../src/components/StandaardgegevensCard.tsx"],"names":[],"mappings":"AAaA,wBAAgB,qBAAqB,gCA+CpC"}
|
|
@@ -7,7 +7,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
7
7
|
// GEEN <Header /> hier — die levert de shell.
|
|
8
8
|
// ============================================================================
|
|
9
9
|
import { useEffect, useState } from "react";
|
|
10
|
-
import { Badge, Card, CardContent, CardDescription, CardHeader, CardTitle, supabase } from "@flowselections/core";
|
|
10
|
+
import { Badge, Card, CardContent, CardDescription, CardHeader, CardTitle, formatDatumTijd, supabase } from "@flowselections/core";
|
|
11
11
|
import { Database } from "lucide-react";
|
|
12
12
|
import { aangevuldeOnderdelen, useEngineZelfherstel } from "../hooks/useEngineZelfherstel.js";
|
|
13
13
|
export function StandaardgegevensCard() {
|
|
@@ -24,7 +24,7 @@ export function StandaardgegevensCard() {
|
|
|
24
24
|
const eerder = aangevuldeOnderdelen(laatste);
|
|
25
25
|
const meldingen = Array.isArray(resultaat?.meldingen) ? resultaat.meldingen : [];
|
|
26
26
|
return (_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsxs(CardTitle, { className: "flex items-center gap-2 text-base", children: [_jsx(Database, { className: "h-4 w-4" }), " Standaardgegevens", fout ? _jsx(Badge, { variant: "destructive", children: "Controle mislukt" })
|
|
27
|
-
: resultaat ? _jsx(Badge, { variant: "secondary", children: nu.length ? "Aangevuld" : "Compleet" }) : null] }), _jsx(CardDescription, { children: "Ladingdragers, Floriday-vertalingen, planinstellingen, tijdinstelling en strategie." })] }), _jsxs(CardContent, { className: "space-y-2 text-sm", children: [fout && _jsxs("p", { className: "text-destructive", children: ["Kon niet controleren: ", fout] }), nu.length > 0 && (_jsxs("div", { children: [_jsx("p", { className: "font-medium", children: "Zojuist aangevuld:" }), _jsx("ul", { className: "list-disc pl-5", children: nu.map((t) => _jsx("li", { children: t }, t)) })] })), nu.length === 0 && eerder.length > 0 && laatste?.op && (_jsxs("div", { children: [_jsxs("p", { className: "text-muted-foreground", children: ["Laatst aangevuld op ", new Date(laatste.op).toLocaleString("nl-NL"), ":"] }), _jsx("ul", { className: "list-disc pl-5 text-muted-foreground", children: eerder.map((t) => _jsx("li", { children: t }, t)) })] })), resultaat && nu.length === 0 && eerder.length === 0 && _jsx("p", { className: "text-muted-foreground", children: "Alle standaardgegevens zijn aanwezig." }), meldingen.map((m) => _jsx("p", { className: "text-destructive", children: m }, m)), _jsx(OnderhoudStatus, {})] })] }));
|
|
27
|
+
: resultaat ? _jsx(Badge, { variant: "secondary", children: nu.length ? "Aangevuld" : "Compleet" }) : null] }), _jsx(CardDescription, { children: "Ladingdragers, Floriday-vertalingen, planinstellingen, tijdinstelling en strategie." })] }), _jsxs(CardContent, { className: "space-y-2 text-sm", children: [fout && _jsxs("p", { className: "text-destructive", children: ["Kon niet controleren: ", fout] }), nu.length > 0 && (_jsxs("div", { children: [_jsx("p", { className: "font-medium", children: "Zojuist aangevuld:" }), _jsx("ul", { className: "list-disc pl-5", children: nu.map((t) => _jsx("li", { children: t }, t)) })] })), nu.length === 0 && eerder.length > 0 && laatste?.op && (_jsxs("div", { children: [_jsxs("p", { className: "text-muted-foreground", children: ["Laatst aangevuld op ", new Date(laatste.op).toLocaleString("nl-NL"), ":"] }), _jsx("ul", { className: "list-disc pl-5 text-muted-foreground", children: eerder.map((t) => _jsx("li", { children: t }, t)) })] })), resultaat && nu.length === 0 && eerder.length === 0 && _jsx("p", { className: "text-muted-foreground", children: "Alle standaardgegevens zijn aanwezig." }), meldingen.map((m) => _jsx("p", { className: "text-destructive", children: m }, m)), _jsx(OnderhoudStatus, {}), _jsx(ProductiebonStatus, {}), _jsx(SamenvoeggroepenStatus, {})] })] }));
|
|
28
28
|
}
|
|
29
29
|
// 1.0.228: wachtrij per status, oudste trace-regel en laatste opruimronde.
|
|
30
30
|
function OnderhoudStatus() {
|
|
@@ -40,3 +40,49 @@ function OnderhoudStatus() {
|
|
|
40
40
|
const prune = o.laatsteOpruimronde;
|
|
41
41
|
return (_jsxs("div", { className: "border-t pt-2 text-muted-foreground", children: [_jsx("p", { className: "font-medium text-foreground", children: "Onderhoud" }), _jsxs("p", { children: ["Wachtrij: ", wachtrij.length ? wachtrij.map(([s, n]) => `${s} ${n}`).join(" · ") : "leeg"] }), _jsxs("p", { children: ["Oudste trace-regel: ", o.oudsteTrace ? new Date(o.oudsteTrace).toLocaleString("nl-NL") : "geen"] }), _jsxs("p", { children: ["Laatste opruimronde: ", prune?.op ? `${new Date(prune.op).toLocaleString("nl-NL")} (${prune.verwijderd ?? 0} verwijderd)` : "nog niet"] })] }));
|
|
42
42
|
}
|
|
43
|
+
// Geannuleerde/verwijderde orders die uit een samenvoeggroep zijn gehaald.
|
|
44
|
+
function SamenvoeggroepenStatus() {
|
|
45
|
+
const [info, setInfo] = useState(null);
|
|
46
|
+
const [fout, setFout] = useState(null);
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
supabase.rpc("logistics_buffers_herstel_status").then(({ data, error }) => {
|
|
49
|
+
if (error) {
|
|
50
|
+
console.error("logistics_buffers_herstel_status", error);
|
|
51
|
+
setFout(error.message);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
setInfo(data && typeof data === "object" ? data : null);
|
|
55
|
+
});
|
|
56
|
+
}, []);
|
|
57
|
+
if (fout)
|
|
58
|
+
return _jsx("p", { className: "text-destructive", children: "Samenvoeggroepen: status kon niet worden gelezen." });
|
|
59
|
+
if (!info)
|
|
60
|
+
return null;
|
|
61
|
+
const fouten = Array.isArray(info.fouten) ? info.fouten : [];
|
|
62
|
+
const groepen = info.stand?.totaalGroepen ?? 0;
|
|
63
|
+
return (_jsxs("div", { className: "border-t pt-2", children: [_jsx("p", { className: "font-medium", children: "Samenvoeggroepen" }), _jsx("p", { className: "text-muted-foreground", children: groepen > 0
|
|
64
|
+
? `${groepen} groep(en) hersteld: ${info.stand?.totaalOrders ?? 0} geannuleerde of verwijderde order(s) eruit gehaald${info.stand?.laatsteOp ? ` (laatst ${formatDatumTijd(info.stand.laatsteOp)})` : ""}.`
|
|
65
|
+
: "Geen groepen met geannuleerde orders gevonden." }), (info.nogInGroep ?? 0) > 0 && (_jsxs("p", { className: "text-destructive", children: ["Nog ", info.nogInGroep, " geannuleerde order(s) in een groep."] })), fouten.map((f, i) => (_jsxs("p", { className: "text-destructive", children: [formatDatumTijd(f.op), ": ", f.melding] }, i)))] }));
|
|
66
|
+
}
|
|
67
|
+
function ProductiebonStatus() {
|
|
68
|
+
const [info, setInfo] = useState(null);
|
|
69
|
+
const [fout, setFout] = useState(null);
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
supabase.rpc("logistics_productiebon_status").then(({ data, error }) => {
|
|
72
|
+
if (error) {
|
|
73
|
+
console.error("logistics_productiebon_status", error);
|
|
74
|
+
setFout(error.message);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
setInfo(data && typeof data === "object" ? data : null);
|
|
78
|
+
});
|
|
79
|
+
}, []);
|
|
80
|
+
if (fout)
|
|
81
|
+
return _jsx("p", { className: "text-destructive", children: "Productiebonnen: status kon niet worden gelezen." });
|
|
82
|
+
if (!info || info.beschikbaar === false)
|
|
83
|
+
return null;
|
|
84
|
+
const fouten = Array.isArray(info.fouten) ? info.fouten : [];
|
|
85
|
+
const stationMeldingen = Array.isArray(info.stationMeldingen) ? info.stationMeldingen : [];
|
|
86
|
+
return (_jsxs("div", { className: "border-t pt-2", children: [_jsx("p", { className: "font-medium", children: "Productiebonnen" }), _jsxs("p", { className: "text-muted-foreground", children: [info.inWachtrij ?? 0, " in wachtrij, ", info.wachtOpGoedkeuring ?? 0, " wachten op goedkeuring."] }), typeof info.stationMelding === "string" && info.stationMelding !== "" &&
|
|
87
|
+
!stationMeldingen.includes(info.stationMelding) && (_jsx("p", { className: "text-destructive", children: info.stationMelding })), stationMeldingen.map((m, i) => (_jsx("p", { className: "text-destructive", children: m }, `s${i}`))), fouten.map((f, i) => (_jsxs("p", { className: "text-destructive", children: [formatDatumTijd(f.op), ": ", f.melding] }, i)))] }));
|
|
88
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RuleFieldInput.d.ts","sourceRoot":"","sources":["../../../src/components/rule-engine/RuleFieldInput.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAQ3E,UAAU,KAAK;IACb,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"RuleFieldInput.d.ts","sourceRoot":"","sources":["../../../src/components/rule-engine/RuleFieldInput.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAQ3E,UAAU,KAAK;IACb,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,KAAK,sCAsW3E"}
|
|
@@ -12,7 +12,7 @@ import { usePickstations } from "../../hooks/usePickstations.js";
|
|
|
12
12
|
import { useScannersPrinters } from "../../hooks/useScannersPrinters.js";
|
|
13
13
|
import { useDocumentLayouts } from "../../hooks/useDocumentLayouts.js";
|
|
14
14
|
export function RuleFieldInput({ field, value, onChange, stepValues }) {
|
|
15
|
-
const { stations, types, loading } = usePickstations();
|
|
15
|
+
const { stations, types, standaard, loading } = usePickstations();
|
|
16
16
|
const { scanners, printers, loading: devicesLoading } = useScannersPrinters();
|
|
17
17
|
const { layouts: matching, allLayouts, autoLayout, loading: layoutsLoading, } = useDocumentLayouts(field.layoutTypes);
|
|
18
18
|
const help = fieldHelp(field);
|
|
@@ -34,8 +34,12 @@ export function RuleFieldInput({ field, value, onChange, stepValues }) {
|
|
|
34
34
|
}
|
|
35
35
|
if (field.type === "pickstation") {
|
|
36
36
|
const options = field.type === "pickstation" ? stations : types;
|
|
37
|
+
// Lege keuze = standaardstation (opgezocht op system_code, nooit op naam).
|
|
38
|
+
const standaardCode = field.key === "production_note_station" ? "productie" : "orders";
|
|
39
|
+
const standaardNaam = standaard[standaardCode];
|
|
40
|
+
const leegLabel = standaardNaam ? `Standaard: ${standaardNaam}` : "Geen standaardstation";
|
|
37
41
|
return (_jsxs("div", { className: "space-y-2", children: [_jsx(FieldLabel, { label: field.label, help: help ??
|
|
38
|
-
"Het pickstation waar dit document hoort. De pickschermen koppelen dat station aan een printplek uit de Layout maker; die printplek bepaalt de printer." }), _jsxs(Select, { value: String(value ?? ""), onValueChange: (v) => onChange(v === "__none__" ? "" : v), children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: loading ? "Laden…" :
|
|
42
|
+
"Het pickstation waar dit document hoort. De pickschermen koppelen dat station aan een printplek uit de Layout maker; die printplek bepaalt de printer." }), _jsxs(Select, { value: String(value ?? ""), onValueChange: (v) => onChange(v === "__none__" ? "" : v), children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: loading ? "Laden…" : leegLabel }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "__none__", children: leegLabel }), options.map((option) => (_jsx(SelectItem, { value: option.id, children: option.name }, option.id)))] })] }), !loading && options.length === 0 && (_jsx("p", { className: "text-xs text-muted-foreground", children: "Er zijn nog geen pickstations ingericht." })), !loading && !standaardNaam && String(value ?? "") === "" && (_jsx("p", { className: "text-xs text-destructive", children: "Er is geen standaardstation; kies hier een pickstation." }))] }));
|
|
39
43
|
}
|
|
40
44
|
if (field.type === "scanner" || field.type === "printer") {
|
|
41
45
|
const isScanner = field.type === "scanner";
|
|
@@ -2,9 +2,12 @@ export interface PickstationOption {
|
|
|
2
2
|
id: string;
|
|
3
3
|
name: string;
|
|
4
4
|
}
|
|
5
|
+
/** Namen van de standaardstations per system_code ('productie', 'orders'); ook als ze uit staan. */
|
|
6
|
+
export type StandaardStations = Partial<Record<"productie" | "orders", string>>;
|
|
5
7
|
export declare function usePickstations(): {
|
|
6
8
|
stations: PickstationOption[];
|
|
7
9
|
types: PickstationOption[];
|
|
10
|
+
standaard: Partial<Record<"orders" | "productie", string>>;
|
|
8
11
|
loading: boolean;
|
|
9
12
|
};
|
|
10
13
|
//# sourceMappingURL=usePickstations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePickstations.d.ts","sourceRoot":"","sources":["../../src/hooks/usePickstations.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;
|
|
1
|
+
{"version":3,"file":"usePickstations.d.ts","sourceRoot":"","sources":["../../src/hooks/usePickstations.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAID,oGAAoG;AACpG,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,GAAG,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;AAuChF,wBAAgB,eAAe;;;;;EAyB9B"}
|
|
@@ -7,19 +7,33 @@ import { supabase } from "@flowselections/core";
|
|
|
7
7
|
const db = () => supabase;
|
|
8
8
|
let cache = null;
|
|
9
9
|
let inflight = null;
|
|
10
|
+
async function loadStations() {
|
|
11
|
+
const metCode = await db().from("pick_stations").select("id, name, active, system_code").order("sort_order", { ascending: true });
|
|
12
|
+
if (!metCode?.error)
|
|
13
|
+
return metCode;
|
|
14
|
+
// Oudere Pickschermen zonder system_code: dan zijn er geen standaardstations.
|
|
15
|
+
console.warn("pick_stations.system_code niet beschikbaar", metCode.error);
|
|
16
|
+
return db().from("pick_stations").select("id, name, active").order("sort_order", { ascending: true });
|
|
17
|
+
}
|
|
10
18
|
async function load() {
|
|
11
19
|
if (cache)
|
|
12
20
|
return cache;
|
|
13
21
|
if (!inflight) {
|
|
14
22
|
inflight = (async () => {
|
|
15
23
|
const [stations, types] = await Promise.all([
|
|
16
|
-
|
|
24
|
+
loadStations(),
|
|
17
25
|
db().from("pick_station_types").select("id, name, active").order("sort_order", { ascending: true }),
|
|
18
26
|
]);
|
|
19
27
|
const map = (rows) => (Array.isArray(rows) ? rows : [])
|
|
20
28
|
.filter((r) => r && r.active !== false)
|
|
21
29
|
.map((r) => ({ id: String(r.id), name: String(r.name ?? r.id) }));
|
|
22
|
-
|
|
30
|
+
const standaard = {};
|
|
31
|
+
for (const r of Array.isArray(stations?.data) ? stations.data : []) {
|
|
32
|
+
const code = r?.system_code;
|
|
33
|
+
if (code === "productie" || code === "orders")
|
|
34
|
+
standaard[code] = String(r.name ?? r.id);
|
|
35
|
+
}
|
|
36
|
+
cache = { stations: map(stations?.data), types: map(types?.data), standaard };
|
|
23
37
|
return cache;
|
|
24
38
|
})();
|
|
25
39
|
}
|
|
@@ -28,6 +42,7 @@ async function load() {
|
|
|
28
42
|
export function usePickstations() {
|
|
29
43
|
const [stations, setStations] = useState(cache?.stations ?? []);
|
|
30
44
|
const [types, setTypes] = useState(cache?.types ?? []);
|
|
45
|
+
const [standaard, setStandaard] = useState(cache?.standaard ?? {});
|
|
31
46
|
const [loading, setLoading] = useState(!cache);
|
|
32
47
|
useEffect(() => {
|
|
33
48
|
let active = true;
|
|
@@ -37,6 +52,7 @@ export function usePickstations() {
|
|
|
37
52
|
return;
|
|
38
53
|
setStations(result.stations);
|
|
39
54
|
setTypes(result.types);
|
|
55
|
+
setStandaard(result.standaard);
|
|
40
56
|
})
|
|
41
57
|
.catch(() => undefined)
|
|
42
58
|
.finally(() => {
|
|
@@ -47,5 +63,5 @@ export function usePickstations() {
|
|
|
47
63
|
active = false;
|
|
48
64
|
};
|
|
49
65
|
}, []);
|
|
50
|
-
return { stations, types, loading };
|
|
66
|
+
return { stations, types, standaard, loading };
|
|
51
67
|
}
|