@flowselections/floriday-voorraad 1.0.141 → 1.0.143
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/dist-lib/components/voorraad/NieuwArtikelPage.d.ts.map +1 -1
- package/dist-lib/components/voorraad/NieuwArtikelPage.js +22 -3
- package/dist-lib/components/voorraad/VoorraadPage.d.ts.map +1 -1
- package/dist-lib/components/voorraad/VoorraadPage.js +2 -0
- package/dist-lib/hooks/useEnsureVoorraadDefaults.d.ts +7 -0
- package/dist-lib/hooks/useEnsureVoorraadDefaults.d.ts.map +1 -0
- package/dist-lib/hooks/useEnsureVoorraadDefaults.js +25 -0
- package/dist-lib/integrations/supabase/types.d.ts +365 -0
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/engine-carrier.d.ts +15 -0
- package/dist-lib/lib/engine-carrier.d.ts.map +1 -0
- package/dist-lib/lib/engine-carrier.js +27 -0
- package/dist-lib/lib/simple-packing.d.ts +2 -4
- package/dist-lib/lib/simple-packing.d.ts.map +1 -1
- package/dist-lib/lib/simple-packing.js +5 -12
- package/package.json +2 -2
- package/sql/AGENTS.md +3 -1
- package/sql/floriday-voorraad-schema.sql +142 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NieuwArtikelPage.d.ts","sourceRoot":"","sources":["../../../src/components/voorraad/NieuwArtikelPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"NieuwArtikelPage.d.ts","sourceRoot":"","sources":["../../../src/components/voorraad/NieuwArtikelPage.tsx"],"names":[],"mappings":"AA8BA,wBAAgB,gBAAgB,gCA4Y/B"}
|
|
@@ -19,6 +19,7 @@ import { useLoadCarriers } from "../../hooks/useLoadCarriers.js";
|
|
|
19
19
|
import { saveOwnPackings } from "../../lib/product-packings.js";
|
|
20
20
|
import { assertArticleCode } from "../../lib/article-code.js";
|
|
21
21
|
import { EMPTY_SIMPLE_PACKING, engineOordeelRegel, missingPackingFields, simplePackingToRow, } from "../../lib/simple-packing.js";
|
|
22
|
+
import { resolveEngineCarrier } from "../../lib/engine-carrier.js";
|
|
22
23
|
const STEPS = ["Naam en code", "Voorraad", "Prijs", "Belading"];
|
|
23
24
|
export function NieuwArtikelPage() {
|
|
24
25
|
const carriers = useLoadCarriers();
|
|
@@ -41,6 +42,22 @@ export function NieuwArtikelPage() {
|
|
|
41
42
|
const [fusts, setFusts] = useState([]);
|
|
42
43
|
const [oordeel, setOordeel] = useState(null);
|
|
43
44
|
const missingPacking = missingPackingFields(packing);
|
|
45
|
+
// Vertaling naar de Engine-code: alleen via de Logistiek Engine, geen eigen lijst.
|
|
46
|
+
const [engineCarrier, setEngineCarrier] = useState({ code: null, melding: null });
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
let off = false;
|
|
49
|
+
setEngineCarrier({ code: null, melding: null });
|
|
50
|
+
if (!packing.loadCarrier)
|
|
51
|
+
return;
|
|
52
|
+
void resolveEngineCarrier(supabase, packing.loadCarrier).then((r) => {
|
|
53
|
+
if (!off)
|
|
54
|
+
setEngineCarrier(r);
|
|
55
|
+
});
|
|
56
|
+
return () => {
|
|
57
|
+
off = true;
|
|
58
|
+
};
|
|
59
|
+
}, [packing.loadCarrier]);
|
|
60
|
+
const packingReady = missingPacking.length === 0 && !!engineCarrier.code;
|
|
44
61
|
const setPack = (k, v) => setPacking((p) => ({ ...p, [k]: v }));
|
|
45
62
|
useEffect(() => {
|
|
46
63
|
let off = false;
|
|
@@ -84,7 +101,7 @@ export function NieuwArtikelPage() {
|
|
|
84
101
|
: step === 1
|
|
85
102
|
? !canSaveStock || (Number(stock) >= 0 && stock !== "")
|
|
86
103
|
: step === 3
|
|
87
|
-
?
|
|
104
|
+
? packingReady
|
|
88
105
|
: true;
|
|
89
106
|
const save = async () => {
|
|
90
107
|
if (savingRef.current)
|
|
@@ -98,6 +115,8 @@ export function NieuwArtikelPage() {
|
|
|
98
115
|
throw new Error("Vul een geldige prijs in (groter dan 0)");
|
|
99
116
|
assertArticleCode(code, name, "manual");
|
|
100
117
|
const packingRow = simplePackingToRow(packing);
|
|
118
|
+
if (!engineCarrier.code)
|
|
119
|
+
throw new Error(engineCarrier.melding ?? "De ladingdrager wordt nog gecontroleerd door de Logistiek Engine.");
|
|
101
120
|
let id = insertedIdRef.current;
|
|
102
121
|
if (!id) {
|
|
103
122
|
const { data, error } = await supabase
|
|
@@ -139,7 +158,7 @@ export function NieuwArtikelPage() {
|
|
|
139
158
|
}
|
|
140
159
|
// Controle door de Engine (alleen lezen); uitkomst tonen, niet blokkeren.
|
|
141
160
|
const { data: oo, error: ooErr } = await supabase.rpc("logistics_product_oordeel_belading", {
|
|
142
|
-
p_regels: [engineOordeelRegel(id, packing)],
|
|
161
|
+
p_regels: [engineOordeelRegel(id, packing, engineCarrier.code)],
|
|
143
162
|
});
|
|
144
163
|
const first = Array.isArray(oo) ? oo[0] : null;
|
|
145
164
|
setOordeel(ooErr
|
|
@@ -167,5 +186,5 @@ export function NieuwArtikelPage() {
|
|
|
167
186
|
? "rounded-md border p-3 text-sm"
|
|
168
187
|
: "rounded-md border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive", children: [_jsxs("p", { className: "font-medium", children: ["Controle karindeling: ", oordeel.tekst] }), oordeel.regels.length > 0 && (_jsx("ul", { className: "list-disc pl-5", children: oordeel.regels.map((r) => (_jsx("li", { children: r }, r))) }))] })), hasFloriday ? (_jsxs(_Fragment, { children: [_jsx("p", { className: "text-sm text-muted-foreground", children: "Wil je het artikel ook op Floriday zetten? Daarvoor is nog nodig:" }), _jsxs("ul", { className: "list-disc pl-5 text-sm", children: [!hasPrice && _jsx("li", { children: "Prijs per stuk (excl. btw)" }), missing.map((m) => (_jsx("li", { children: m }, m)))] })] })) : (_jsx("p", { className: "text-sm text-muted-foreground", children: "De voorraad is opgeslagen als eigen voorraad. Die gaat niet naar Floriday." })), _jsxs("div", { className: "flex flex-wrap gap-2", children: [hasFloriday && (_jsxs(Button, { onClick: () => navigate({ to: "/voorraad/$id", params: { id: createdId } }), children: [_jsx(Send, { className: "mr-2 h-4 w-4" }), "Op Floriday zetten"] })), _jsx(Button, { variant: "outline", asChild: true, children: _jsx(Link, { to: "/voorraad", children: "Terug naar voorraad" }) })] })] }) }));
|
|
169
188
|
}
|
|
170
|
-
return (_jsxs("main", { className: "p-6 space-y-4 max-w-2xl", children: [_jsxs(Link, { to: "/voorraad", className: "inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground", children: [_jsx(ArrowLeft, { className: "h-4 w-4" }), "Terug naar voorraad"] }), _jsxs("div", { children: [_jsx("h1", { className: "text-xl font-semibold", children: "Artikel toevoegen" }), _jsxs("p", { className: "text-sm text-muted-foreground", children: ["Stap ", step + 1, " van ", STEPS.length, ": ", STEPS[step]] })] }), _jsx(FloridayConnectionNotice, { status: conn.status, environment: conn.selectedEnvironment, error: conn.error }), _jsxs(Card, { className: "p-5 space-y-4", children: [step === 0 && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "na-name", children: "Naam" }), _jsx(Input, { id: "na-name", value: name, onChange: (e) => setName(e.target.value), autoFocus: true })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "na-code", children: "Artikelcode (optioneel)" }), _jsx(Input, { id: "na-code", value: code, onChange: (e) => setCode(e.target.value) }), _jsx("p", { className: "text-xs text-muted-foreground", children: "Leeg laten: er wordt automatisch een code gemaakt." })] })] })), step === 1 && (_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "na-stock", children: "Voorraad (stuks)" }), _jsx(Input, { id: "na-stock", type: "number", min: 0, value: canSaveStock ? stock : "", onChange: (e) => setStock(e.target.value), disabled: !canSaveStock, "aria-describedby": "na-stock-help", autoFocus: true }), !canSaveStock && (_jsx("p", { id: "na-stock-help", className: "text-xs text-muted-foreground", children: "Koppeling wordt gecontroleerd\u2026" })), canSaveStock && !hasFloriday && (_jsx("p", { id: "na-stock-help", className: "text-xs text-muted-foreground", children: LOCAL_STOCK_TEXT }))] })), step === 2 && (_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "na-price", children: "Prijs per stuk (EUR, excl. btw)" }), _jsx(Input, { id: "na-price", inputMode: "decimal", value: price, onChange: (e) => setPrice(e.target.value), placeholder: "Bijv. 1,10", autoFocus: true }), _jsx("p", { className: "text-xs text-muted-foreground", children: "Zonder prijs komt het artikel niet in Floriday (\"Prijs ontbreekt\")." })] })), step === 3 && (_jsxs("div", { className: "space-y-3", children: [_jsx("p", { className: "text-sm text-muted-foreground", children: "Zonder volledige belading kan de karindeling dit artikel niet plannen. Alle vijf velden zijn verplicht." }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "na-fust", children: "Fust (VBN-code)" }), _jsxs("select", { id: "na-fust", className: "w-full rounded-md border bg-background px-3 py-2 text-sm", value: packing.vbnPackageCode, onChange: (e) => setPack("vbnPackageCode", e.target.value), children: [_jsx("option", { value: "", children: "Kies een fust\u2026" }), fusts.map((f) => (_jsxs("option", { value: String(f.vbn), children: [f.vbn, " \u2013 ", f.name] }, f.vbn)))] }), _jsx(Input, { "aria-label": "Andere VBN-fustcode", placeholder: "Of typ een VBN-fustcode, bijv. 412", inputMode: "numeric", value: packing.vbnPackageCode, onChange: (e) => setPack("vbnPackageCode", e.target.value) })] }), _jsxs("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-3", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "na-ppc", children: "Planten per fust" }), _jsx(Input, { id: "na-ppc", inputMode: "numeric", value: packing.piecesPerPackage, onChange: (e) => setPack("piecesPerPackage", e.target.value) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "na-cpl", children: "Fusten per laag" }), _jsx(Input, { id: "na-cpl", inputMode: "numeric", value: packing.packagesPerLayer, onChange: (e) => setPack("packagesPerLayer", e.target.value) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "na-lpc", children: "Lagen per kar" }), _jsx(Input, { id: "na-lpc", inputMode: "numeric", value: packing.layersPerLoadCarrier, onChange: (e) => setPack("layersPerLoadCarrier", e.target.value) })] })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "na-lc", children: "Ladingdrager" }), _jsxs("select", { id: "na-lc", className: "w-full rounded-md border bg-background px-3 py-2 text-sm", value: packing.loadCarrier, onChange: (e) => setPack("loadCarrier", e.target.value), children: [_jsx("option", { value: "", children: "Kies een ladingdrager\u2026" }), carriers.items.map((c) => (_jsx("option", { value: c.code, children: c.naam }, c.code)))] }), carriers.error && _jsx("p", { className: "text-xs text-destructive", children: carriers.error })] }), missingPacking.length > 0 && (_jsxs("p", { className: "text-xs text-muted-foreground", children: ["Nog invullen: ", missingPacking.join(", "), "."] }))] })), saveError && (_jsx("div", { role: "alert", className: "rounded-md border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive", children: saveError })), _jsxs("div", { className: "flex flex-wrap justify-between gap-2", children: [_jsx(Button, { variant: "outline", disabled: step === 0 || saving, onClick: () => setStep((s) => s - 1), children: "Vorige" }), step < STEPS.length - 1 ? (_jsx(Button, { disabled: !canNext, onClick: () => setStep((s) => s + 1), children: "Volgende" })) : (_jsxs(Button, { disabled: saving || !name.trim() ||
|
|
189
|
+
return (_jsxs("main", { className: "p-6 space-y-4 max-w-2xl", children: [_jsxs(Link, { to: "/voorraad", className: "inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground", children: [_jsx(ArrowLeft, { className: "h-4 w-4" }), "Terug naar voorraad"] }), _jsxs("div", { children: [_jsx("h1", { className: "text-xl font-semibold", children: "Artikel toevoegen" }), _jsxs("p", { className: "text-sm text-muted-foreground", children: ["Stap ", step + 1, " van ", STEPS.length, ": ", STEPS[step]] })] }), _jsx(FloridayConnectionNotice, { status: conn.status, environment: conn.selectedEnvironment, error: conn.error }), _jsxs(Card, { className: "p-5 space-y-4", children: [step === 0 && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "na-name", children: "Naam" }), _jsx(Input, { id: "na-name", value: name, onChange: (e) => setName(e.target.value), autoFocus: true })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "na-code", children: "Artikelcode (optioneel)" }), _jsx(Input, { id: "na-code", value: code, onChange: (e) => setCode(e.target.value) }), _jsx("p", { className: "text-xs text-muted-foreground", children: "Leeg laten: er wordt automatisch een code gemaakt." })] })] })), step === 1 && (_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "na-stock", children: "Voorraad (stuks)" }), _jsx(Input, { id: "na-stock", type: "number", min: 0, value: canSaveStock ? stock : "", onChange: (e) => setStock(e.target.value), disabled: !canSaveStock, "aria-describedby": "na-stock-help", autoFocus: true }), !canSaveStock && (_jsx("p", { id: "na-stock-help", className: "text-xs text-muted-foreground", children: "Koppeling wordt gecontroleerd\u2026" })), canSaveStock && !hasFloriday && (_jsx("p", { id: "na-stock-help", className: "text-xs text-muted-foreground", children: LOCAL_STOCK_TEXT }))] })), step === 2 && (_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "na-price", children: "Prijs per stuk (EUR, excl. btw)" }), _jsx(Input, { id: "na-price", inputMode: "decimal", value: price, onChange: (e) => setPrice(e.target.value), placeholder: "Bijv. 1,10", autoFocus: true }), _jsx("p", { className: "text-xs text-muted-foreground", children: "Zonder prijs komt het artikel niet in Floriday (\"Prijs ontbreekt\")." })] })), step === 3 && (_jsxs("div", { className: "space-y-3", children: [_jsx("p", { className: "text-sm text-muted-foreground", children: "Zonder volledige belading kan de karindeling dit artikel niet plannen. Alle vijf velden zijn verplicht." }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "na-fust", children: "Fust (VBN-code)" }), _jsxs("select", { id: "na-fust", className: "w-full rounded-md border bg-background px-3 py-2 text-sm", value: packing.vbnPackageCode, onChange: (e) => setPack("vbnPackageCode", e.target.value), children: [_jsx("option", { value: "", children: "Kies een fust\u2026" }), fusts.map((f) => (_jsxs("option", { value: String(f.vbn), children: [f.vbn, " \u2013 ", f.name] }, f.vbn)))] }), _jsx(Input, { "aria-label": "Andere VBN-fustcode", placeholder: "Of typ een VBN-fustcode, bijv. 412", inputMode: "numeric", value: packing.vbnPackageCode, onChange: (e) => setPack("vbnPackageCode", e.target.value) })] }), _jsxs("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-3", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "na-ppc", children: "Planten per fust" }), _jsx(Input, { id: "na-ppc", inputMode: "numeric", value: packing.piecesPerPackage, onChange: (e) => setPack("piecesPerPackage", e.target.value) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "na-cpl", children: "Fusten per laag" }), _jsx(Input, { id: "na-cpl", inputMode: "numeric", value: packing.packagesPerLayer, onChange: (e) => setPack("packagesPerLayer", e.target.value) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "na-lpc", children: "Lagen per kar" }), _jsx(Input, { id: "na-lpc", inputMode: "numeric", value: packing.layersPerLoadCarrier, onChange: (e) => setPack("layersPerLoadCarrier", e.target.value) })] })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "na-lc", children: "Ladingdrager" }), _jsxs("select", { id: "na-lc", className: "w-full rounded-md border bg-background px-3 py-2 text-sm", value: packing.loadCarrier, onChange: (e) => setPack("loadCarrier", e.target.value), children: [_jsx("option", { value: "", children: "Kies een ladingdrager\u2026" }), carriers.items.map((c) => (_jsx("option", { value: c.code, children: c.naam }, c.code)))] }), carriers.error && _jsx("p", { className: "text-xs text-destructive", children: carriers.error }), engineCarrier.melding && _jsx("p", { className: "text-xs text-destructive", children: engineCarrier.melding })] }), missingPacking.length > 0 && (_jsxs("p", { className: "text-xs text-muted-foreground", children: ["Nog invullen: ", missingPacking.join(", "), "."] }))] })), saveError && (_jsx("div", { role: "alert", className: "rounded-md border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive", children: saveError })), _jsxs("div", { className: "flex flex-wrap justify-between gap-2", children: [_jsx(Button, { variant: "outline", disabled: step === 0 || saving, onClick: () => setStep((s) => s - 1), children: "Vorige" }), step < STEPS.length - 1 ? (_jsx(Button, { disabled: !canNext, onClick: () => setStep((s) => s + 1), children: "Volgende" })) : (_jsxs(Button, { disabled: saving || !name.trim() || !packingReady, onClick: () => void save(), children: [saving ? _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : _jsx(Check, { className: "mr-2 h-4 w-4" }), saving ? "Bezig met opslaan…" : "Artikel opslaan"] }))] })] }), hasFloriday && (_jsx("button", { type: "button", className: "text-sm text-muted-foreground underline hover:text-foreground", onClick: () => setFull(true), children: "Meteen alle Floriday-gegevens invullen" }))] }));
|
|
171
190
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VoorraadPage.d.ts","sourceRoot":"","sources":["../../../src/components/voorraad/VoorraadPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"VoorraadPage.d.ts","sourceRoot":"","sources":["../../../src/components/voorraad/VoorraadPage.tsx"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAmF3D;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,GAAG,mBAAmB,GAAG,aAAa,CAAC,CAAC;;;;;;;EAgBzG;AAED,wBAAgB,YAAY,gCAsW3B"}
|
|
@@ -7,6 +7,7 @@ import { Link } from "@tanstack/react-router";
|
|
|
7
7
|
import { Button, Card, Input, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@flowselections/core";
|
|
8
8
|
import { AlertTriangle, CheckCircle2, FileText, PackageX, Plus, Search, } from "lucide-react";
|
|
9
9
|
import { useFloridayConnection } from "../../hooks/useFloridayConnection.js";
|
|
10
|
+
import { useEnsureVoorraadDefaults } from "../../hooks/useEnsureVoorraadDefaults.js";
|
|
10
11
|
import { FloridayConnectionNotice } from "./FloridayConnectionNotice.js";
|
|
11
12
|
import { useVoorraadData } from "../../hooks/useVoorraadData.js";
|
|
12
13
|
import { StockSyncStatus } from "./StockSyncStatus.js";
|
|
@@ -69,6 +70,7 @@ export function countStock(items) {
|
|
|
69
70
|
return { total: items.length, inStock, outOfStock, belowMin, fullyReserved, freeAvailable };
|
|
70
71
|
}
|
|
71
72
|
export function VoorraadPage() {
|
|
73
|
+
useEnsureVoorraadDefaults();
|
|
72
74
|
const conn = useFloridayConnection();
|
|
73
75
|
const { activeId, error: connError } = conn;
|
|
74
76
|
const { items, loading, error, reload } = useVoorraadData(activeId);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zelfherstel bij het openen van Voorraad: vult ontbrekende standaardgegevens
|
|
3
|
+
* aan via voorraad_ensure_defaults(). Eén keer per sessie, op de achtergrond;
|
|
4
|
+
* een fout blokkeert niets en geeft alleen een melding in gewone taal.
|
|
5
|
+
*/
|
|
6
|
+
export declare function useEnsureVoorraadDefaults(): void;
|
|
7
|
+
//# sourceMappingURL=useEnsureVoorraadDefaults.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEnsureVoorraadDefaults.d.ts","sourceRoot":"","sources":["../../src/hooks/useEnsureVoorraadDefaults.ts"],"names":[],"mappings":"AAMA;;;;GAIG;AACH,wBAAgB,yBAAyB,SAaxC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
import { toast } from "@flowselections/core";
|
|
3
|
+
import { supabase } from "../integrations/supabase/client.js";
|
|
4
|
+
let gestart = false;
|
|
5
|
+
/**
|
|
6
|
+
* Zelfherstel bij het openen van Voorraad: vult ontbrekende standaardgegevens
|
|
7
|
+
* aan via voorraad_ensure_defaults(). Eén keer per sessie, op de achtergrond;
|
|
8
|
+
* een fout blokkeert niets en geeft alleen een melding in gewone taal.
|
|
9
|
+
*/
|
|
10
|
+
export function useEnsureVoorraadDefaults() {
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
if (gestart)
|
|
13
|
+
return;
|
|
14
|
+
gestart = true;
|
|
15
|
+
void (async () => {
|
|
16
|
+
const { data, error } = await supabase.rpc("voorraad_ensure_defaults");
|
|
17
|
+
if (error || (data && data.ok === false)) {
|
|
18
|
+
// Functie nog niet geïnstalleerd of mislukt: niets blokkeren.
|
|
19
|
+
if (error?.code === "PGRST202")
|
|
20
|
+
return;
|
|
21
|
+
toast.error("Standaardgegevens van Voorraad konden niet worden aangevuld. Neem contact op met de beheerder als dit blijft gebeuren.");
|
|
22
|
+
}
|
|
23
|
+
})();
|
|
24
|
+
}, []);
|
|
25
|
+
}
|