@flowselections/logistiek-engine 1.0.153 → 1.0.157

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.
@@ -1 +1 @@
1
- {"version":3,"file":"BeheerPage.d.ts","sourceRoot":"","sources":["../../src/components/BeheerPage.tsx"],"names":[],"mappings":"AAqJA,wBAAgB,UAAU,gCAUzB"}
1
+ {"version":3,"file":"BeheerPage.d.ts","sourceRoot":"","sources":["../../src/components/BeheerPage.tsx"],"names":[],"mappings":"AAsJA,wBAAgB,UAAU,gCAWzB"}
@@ -13,6 +13,7 @@ import { supabase } from "../integrations/supabase/moduleClient.js";
13
13
  import { RolPoort } from "./RolPoort";
14
14
  import { OudeOrderregelsCard } from "./OudeOrderregelsCard";
15
15
  import { AutomatischVersturenCard } from "./AutomatischVersturenCard";
16
+ import { OpruimlijstKarrenCard } from "./OpruimlijstKarrenCard";
16
17
  import { ENGINE_TOEGANG } from "../hooks/useEngineRollen";
17
18
  function HerindelenBeheer() {
18
19
  const [datum, setDatum] = useState("");
@@ -71,5 +72,5 @@ function HerindelenBeheer() {
71
72
  : `${voor?.geprintOfGepickt ?? 0} order(s) die al geprint of gepickt zijn, blijven ongemoeid.` })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: "Annuleren" }), _jsxs(AlertDialogAction, { onClick: () => void voerUit(), disabled: (voor?.aantal ?? 0) === 0, children: ["Ja, ", voor?.aantal ?? 0, " order(s) opnieuw indelen"] })] })] }) })] }));
72
73
  }
73
74
  export function BeheerPage() {
74
- return (_jsx(RolPoort, { rollen: ENGINE_TOEGANG.beheer, children: _jsxs("div", { className: "space-y-6 p-6", children: [_jsx(HerindelenBeheer, {}), _jsx(OudeOrderregelsCard, {}), _jsx(AutomatischVersturenCard, {})] }) }));
75
+ return (_jsx(RolPoort, { rollen: ENGINE_TOEGANG.beheer, children: _jsxs("div", { className: "space-y-6 p-6", children: [_jsx(HerindelenBeheer, {}), _jsx(OudeOrderregelsCard, {}), _jsx(AutomatischVersturenCard, {}), _jsx(OpruimlijstKarrenCard, {})] }) }));
75
76
  }
@@ -0,0 +1,2 @@
1
+ export declare function OpruimlijstKarrenCard(): import("react").JSX.Element;
2
+ //# sourceMappingURL=OpruimlijstKarrenCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OpruimlijstKarrenCard.d.ts","sourceRoot":"","sources":["../../src/components/OpruimlijstKarrenCard.tsx"],"names":[],"mappings":"AAwCA,wBAAgB,qBAAqB,gCAqLpC"}
@@ -0,0 +1,105 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // Opruimlijst losse karren: Voorstel / Twijfel / Nooit, archiveren met exacte
3
+ // aantalcontrole en terugzetten met controle. Nooit verwijderen.
4
+ import { useState } from "react";
5
+ import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Input, Label, } from "@flowselections/core";
6
+ import { supabase } from "../integrations/supabase/moduleClient.js";
7
+ const DELEN = [
8
+ { key: "voorstel", titel: "Voorstel archiveren" },
9
+ { key: "twijfel", titel: "Twijfel (niet automatisch)" },
10
+ { key: "nooit", titel: "Nooit archiveren" },
11
+ ];
12
+ export function OpruimlijstKarrenCard() {
13
+ const [karren, setKarren] = useState(null);
14
+ const [gearchiveerd, setGearchiveerd] = useState(0);
15
+ const [bezig, setBezig] = useState(false);
16
+ const [melding, setMelding] = useState(null);
17
+ const [open, setOpen] = useState(null);
18
+ const [bevestig, setBevestig] = useState(false);
19
+ const [reden, setReden] = useState("");
20
+ const [terugIds, setTerugIds] = useState("");
21
+ const laad = async () => {
22
+ setBezig(true);
23
+ setMelding(null);
24
+ try {
25
+ const { data, error } = await supabase.rpc("logistics_cart_archive_preview");
26
+ if (error)
27
+ throw error;
28
+ const d = (data ?? {});
29
+ setKarren(Array.isArray(d["karren"]) ? d["karren"] : []);
30
+ setGearchiveerd(Number(d["gearchiveerd"] ?? 0));
31
+ }
32
+ catch (e) {
33
+ setMelding(e?.message ? String(e.message) : "De lijst kon niet worden opgehaald.");
34
+ }
35
+ finally {
36
+ setBezig(false);
37
+ }
38
+ };
39
+ const lijst = Array.isArray(karren) ? karren : [];
40
+ const voorstel = lijst.filter((k) => k.deel === "voorstel");
41
+ const archiveer = async () => {
42
+ setBevestig(false);
43
+ setBezig(true);
44
+ const ids = voorstel.map((k) => k.id);
45
+ let totaal = 0;
46
+ try {
47
+ // Per deel van max. 250 met exacte aantalcontrole; elk deel is los atomair.
48
+ for (let i = 0; i < ids.length; i += 250) {
49
+ const deel = ids.slice(i, i + 250);
50
+ const { data, error } = await supabase.rpc("logistics_cart_archive", {
51
+ p_ids: deel,
52
+ p_confirm_count: deel.length,
53
+ p_reason: reden.trim(),
54
+ });
55
+ if (error)
56
+ throw error;
57
+ const n = Number(data?.gearchiveerd ?? 0);
58
+ if (n !== deel.length)
59
+ throw new Error(`Aantal klopt niet: ${n} van ${deel.length} in dit deel.`);
60
+ totaal += n;
61
+ }
62
+ if (totaal !== ids.length)
63
+ throw new Error(`Aantal klopt niet: ${totaal} van ${ids.length}.`);
64
+ setMelding(`${totaal} kar(ren) gearchiveerd (controle ${totaal} = ${ids.length}).`);
65
+ await laad();
66
+ }
67
+ catch (e) {
68
+ setMelding(`${e?.message ? String(e.message) : "Archiveren is niet gelukt."} Al gearchiveerd in eerdere delen: ${totaal}.`);
69
+ }
70
+ finally {
71
+ setBezig(false);
72
+ }
73
+ };
74
+ const zetTerug = async () => {
75
+ const ids = terugIds.split(/[\s,;]+/).map((s) => s.trim()).filter(Boolean);
76
+ if (ids.length === 0)
77
+ return;
78
+ setBezig(true);
79
+ try {
80
+ const { data, error } = await supabase.rpc("logistics_cart_unarchive", {
81
+ p_ids: ids,
82
+ p_reason: "Teruggezet via Beheer",
83
+ });
84
+ if (error)
85
+ throw error;
86
+ const res = Array.isArray(data?.resultaten) ? data.resultaten : [];
87
+ const ok = res.filter((r) => r?.teruggezet).length;
88
+ const fout = res.filter((r) => !r?.teruggezet).map((r) => `${r?.id}: ${r?.reden}`);
89
+ setMelding([`${ok} kar(ren) teruggezet.`, ...fout].join("\n"));
90
+ await laad();
91
+ }
92
+ catch (e) {
93
+ setMelding(e?.message ? String(e.message) : "Terugzetten is niet gelukt.");
94
+ }
95
+ finally {
96
+ setBezig(false);
97
+ }
98
+ };
99
+ return (_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { children: "Opruimlijst losse karren" }), _jsx(CardDescription, { children: "Archiveren is omkeerbaar; er wordt nooit iets verwijderd. Gearchiveerde karren tellen nergens meer mee." })] }), _jsxs(CardContent, { className: "space-y-4", children: [_jsx(Button, { onClick: () => void laad(), disabled: bezig, children: karren ? "Verversen" : "Lijst ophalen" }), melding ? _jsx("p", { className: "whitespace-pre-line text-sm", children: melding }) : null, karren ? _jsxs("p", { className: "text-sm text-muted-foreground", children: ["Al gearchiveerd: ", gearchiveerd] }) : null, karren
100
+ ? DELEN.map((g) => {
101
+ const rijen = lijst.filter((k) => k.deel === g.key);
102
+ return (_jsxs("div", { className: "rounded border border-border", children: [_jsxs("button", { type: "button", className: "flex w-full justify-between p-3 text-left text-sm font-medium", onClick: () => setOpen(open === g.key ? null : g.key), children: [_jsx("span", { children: g.titel }), _jsxs("span", { children: [rijen.length, " karren"] })] }), open === g.key ? (_jsx("div", { className: "max-h-96 overflow-auto border-t border-border", children: _jsxs("table", { className: "w-full text-xs", children: [_jsx("thead", { children: _jsxs("tr", { className: "text-left text-muted-foreground", children: [_jsx("th", { className: "p-2", children: "Kar-id" }), _jsx("th", { className: "p-2", children: "Kar" }), _jsx("th", { className: "p-2", children: "Buffer / order" }), _jsx("th", { className: "p-2", children: "Aangemaakt" }), _jsx("th", { className: "p-2", children: "Reden" })] }) }), _jsx("tbody", { children: rijen.map((k) => (_jsxs("tr", { className: "border-t border-border", children: [_jsx("td", { className: "p-2 font-mono", children: k.id }), _jsx("td", { className: "p-2", children: k.cartNumber ? `K${k.cartNumber}` : "—" }), _jsx("td", { className: "p-2", children: k.orderNumber ?? (k.bufferId ? `buffer ${k.bufferId.slice(0, 8)}` : "geen") }), _jsx("td", { className: "p-2", children: k.createdAt ? new Date(k.createdAt).toLocaleString("nl-NL") : "—" }), _jsx("td", { className: "p-2", children: k.reden })] }, k.id))) })] }) })) : null] }, g.key));
103
+ })
104
+ : null, karren && voorstel.length > 0 ? (_jsxs("div", { className: "grid gap-2 sm:max-w-md", children: [_jsx(Label, { htmlFor: "archief-reden", children: "Reden voor archiveren" }), _jsx(Input, { id: "archief-reden", value: reden, onChange: (e) => setReden(e.target.value) }), _jsxs(Button, { disabled: bezig || reden.trim() === "", onClick: () => setBevestig(true), children: [voorstel.length, " kar(ren) archiveren"] })] })) : null, _jsxs("div", { className: "grid gap-2 sm:max-w-md", children: [_jsx(Label, { htmlFor: "terug-ids", children: "Terugzetten (kar-id's)" }), _jsx(Input, { id: "terug-ids", value: terugIds, onChange: (e) => setTerugIds(e.target.value) }), _jsx(Button, { variant: "outline", disabled: bezig || terugIds.trim() === "", onClick: () => void zetTerug(), children: "Terugzetten" })] }), _jsx(AlertDialog, { open: bevestig, onOpenChange: setBevestig, children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsxs(AlertDialogTitle, { children: ["Je archiveert ", voorstel.length, " kar(ren)"] }), _jsx(AlertDialogDescription, { children: "Alleen de karren op Voorstel. De database controleert alles opnieuw; klopt het aantal niet precies, dan gebeurt er niets." })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: "Annuleren" }), _jsxs(AlertDialogAction, { onClick: () => void archiveer(), children: ["Ja, ", voorstel.length, " archiveren"] })] })] }) })] })] }));
105
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"useWerkwijzeStatus.d.ts","sourceRoot":"","sources":["../../src/hooks/useWerkwijzeStatus.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,UAAU,GAAG,YAAY,CAAC;IACnC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,wBAAgB,kBAAkB;;;;;;;sBAkCS,OAAO,CAAC,MAAM,CAAC;iCAmBJ,OAAO,CAAC;QAC1D,SAAS,EAAE,MAAM,CAAC;QAClB,gBAAgB,EAAE,MAAM,CAAC;QACzB,kBAAkB,EAAE,MAAM,CAAC;KAC5B,CAAC;gCA4BiD,OAAO,CAAC;QACzD,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;EA4BH"}
1
+ {"version":3,"file":"useWerkwijzeStatus.d.ts","sourceRoot":"","sources":["../../src/hooks/useWerkwijzeStatus.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,UAAU,GAAG,YAAY,CAAC;IACnC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,wBAAgB,kBAAkB;;;;;;;sBA0DS,OAAO,CAAC,MAAM,CAAC;iCAmBJ,OAAO,CAAC;QAC1D,SAAS,EAAE,MAAM,CAAC;QAClB,gBAAgB,EAAE,MAAM,CAAC;QACzB,kBAAkB,EAAE,MAAM,CAAC;KAC5B,CAAC;gCA4BiD,OAAO,CAAC;QACzD,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;EA4BH"}
@@ -21,10 +21,36 @@ export function useWerkwijzeStatus() {
21
21
  if (rpcError)
22
22
  throw rpcError;
23
23
  const raw = (data ?? {});
24
+ const werkwijzeId = raw["actieveWerkwijzeId"] ?? null;
25
+ // Naam uit de lijst met werkwijzen, gekoppeld op id (nooit op naam).
26
+ let naam = raw["actieveWerkwijze"] ?? null;
27
+ if (werkwijzeId) {
28
+ try {
29
+ const { data: cfg } = await supabase
30
+ .from("logistics_rule_configs")
31
+ .select("strategy_id")
32
+ .eq("id", werkwijzeId)
33
+ .maybeSingle();
34
+ const sid = cfg?.strategy_id ?? null;
35
+ if (sid) {
36
+ const { data: st } = await supabase
37
+ .from("logistics_strategies")
38
+ .select("name")
39
+ .eq("id", sid)
40
+ .maybeSingle();
41
+ const n = st?.name;
42
+ if (n && n.trim())
43
+ naam = n.trim();
44
+ }
45
+ }
46
+ catch {
47
+ /* naam uit de status blijft staan */
48
+ }
49
+ }
24
50
  setStatus({
25
51
  methode: raw["methode"] === "afmetingen" ? "afmetingen" : "belading",
26
- actieveWerkwijze: raw["actieveWerkwijze"] ?? null,
27
- actieveWerkwijzeId: raw["actieveWerkwijzeId"] ?? null,
52
+ actieveWerkwijze: naam,
53
+ actieveWerkwijzeId: werkwijzeId,
28
54
  karrenVolgensMethode: Number(raw["karrenVolgensMethode"] ?? 0),
29
55
  karrenOudeMethode: Number(raw["karrenOudeMethode"] ?? 0),
30
56
  wachtrij: raw["wachtrij"] ?? {},