@flowselections/floriday-voorraad 1.0.137 → 1.0.139
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/ArtikelWizard.d.ts.map +1 -1
- package/dist-lib/components/voorraad/ArtikelWizard.js +9 -7
- package/dist-lib/components/voorraad/StockMutationHistoryCard.d.ts.map +1 -1
- package/dist-lib/components/voorraad/StockMutationHistoryCard.js +17 -3
- package/dist-lib/components/voorraad/VoorraadPage.d.ts.map +1 -1
- package/dist-lib/components/voorraad/VoorraadPage.js +2 -5
- package/dist-lib/components/voorraad/VoorraadStockCard.d.ts.map +1 -1
- package/dist-lib/components/voorraad/VoorraadStockCard.js +59 -5
- package/dist-lib/hooks/useTradeItemStock.d.ts +2 -0
- package/dist-lib/hooks/useTradeItemStock.d.ts.map +1 -1
- package/dist-lib/hooks/useTradeItemStock.js +4 -3
- package/dist-lib/integrations/supabase/types.d.ts +360 -0
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/__tests__/stock-save.test.d.ts +2 -0
- package/dist-lib/lib/__tests__/stock-save.test.d.ts.map +1 -0
- package/dist-lib/lib/__tests__/stock-save.test.js +35 -0
- package/dist-lib/lib/stock-save.d.ts +32 -0
- package/dist-lib/lib/stock-save.d.ts.map +1 -0
- package/dist-lib/lib/stock-save.js +28 -0
- package/package.json +1 -1
- package/sql/AGENTS.md +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ArtikelWizard.d.ts","sourceRoot":"","sources":["../../../src/components/voorraad/ArtikelWizard.tsx"],"names":[],"mappings":"AA2DA,OAAO,EAUL,KAAK,UAAU,EAMhB,MAAM,4BAA4B,CAAC;AA4DpC,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAMpF,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,UAAU,CA0BrF;AAiED,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EAAE,cAAc,EACvB,WAAW,EACX,SAAS,EACT,WAAW,EACX,OAAO,GACR,GAAE;IACD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,aAAa,CAAC;CACpB,+
|
|
1
|
+
{"version":3,"file":"ArtikelWizard.d.ts","sourceRoot":"","sources":["../../../src/components/voorraad/ArtikelWizard.tsx"],"names":[],"mappings":"AA2DA,OAAO,EAUL,KAAK,UAAU,EAMhB,MAAM,4BAA4B,CAAC;AA4DpC,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAMpF,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,UAAU,CA0BrF;AAiED,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EAAE,cAAc,EACvB,WAAW,EACX,SAAS,EACT,WAAW,EACX,OAAO,GACR,GAAE;IACD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,aAAa,CAAC;CACpB,+BAy4EL"}
|
|
@@ -1908,13 +1908,15 @@ export function ArtikelWizard({ draftId: initialDraftId, tradeItemId, productId,
|
|
|
1908
1908
|
}
|
|
1909
1909
|
}, [persistAndPush, data]);
|
|
1910
1910
|
if (connLoading || draftLoading || publishedLoading || productLoading) {
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
? "
|
|
1915
|
-
:
|
|
1916
|
-
? "
|
|
1917
|
-
:
|
|
1911
|
+
// Voorraadblok direct bruikbaar; Floriday-gegevens laden op de achtergrond (1.0.138).
|
|
1912
|
+
const vroegVoorraad = !connLoading && (tradeItemId || productId || draftId);
|
|
1913
|
+
return (_jsxs("main", { className: "p-6 space-y-4", children: [vroegVoorraad && (_jsx(VoorraadStockCard, { connectionId: activeId, tradeItemId: tradeItemId ?? null, draftId: draftId ?? null, productId: productId ?? null })), _jsxs(Card, { className: "p-6 flex items-center gap-2 text-sm text-muted-foreground", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), publishedLoading
|
|
1914
|
+
? "Artikel laden..."
|
|
1915
|
+
: draftLoading
|
|
1916
|
+
? "Lokaal artikel laden..."
|
|
1917
|
+
: productLoading
|
|
1918
|
+
? "Product laden..."
|
|
1919
|
+
: "Floriday-koppeling laden..."] })] }));
|
|
1918
1920
|
}
|
|
1919
1921
|
if (!activeConnection) {
|
|
1920
1922
|
return (_jsx("main", { className: "p-6", children: _jsx(Card, { className: "p-6", children: "Geen actieve Floriday-koppeling gevonden. Voeg er eerst een toe in Instellingen \u203A Floriday." }) }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StockMutationHistoryCard.d.ts","sourceRoot":"","sources":["../../../src/components/voorraad/StockMutationHistoryCard.tsx"],"names":[],"mappings":"AAWA,UAAU,KAAK;IACb,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;
|
|
1
|
+
{"version":3,"file":"StockMutationHistoryCard.d.ts","sourceRoot":"","sources":["../../../src/components/voorraad/StockMutationHistoryCard.tsx"],"names":[],"mappings":"AAWA,UAAU,KAAK;IACb,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAiDD,wBAAgB,wBAAwB,CAAC,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,KAAK,+BA4O1E"}
|
|
@@ -16,6 +16,7 @@ const TYPE_LABEL = {
|
|
|
16
16
|
reservation: { label: "Reservering", tone: "bg-blue-100 text-blue-800 border-blue-200" },
|
|
17
17
|
reservation_release: { label: "Reservering vrijgegeven", tone: "bg-blue-100 text-blue-800 border-blue-200" },
|
|
18
18
|
reservation_skipped: { label: "Reservering overgeslagen", tone: "bg-amber-100 text-amber-800 border-amber-200" },
|
|
19
|
+
manual_writeoff: { label: "Afgeboekt (met reden)", tone: "bg-rose-100 text-rose-800 border-rose-200" },
|
|
19
20
|
manual_correction: { label: "Handmatige correctie", tone: "bg-slate-100 text-slate-700 border-slate-200" },
|
|
20
21
|
order_sync: { label: "Verwerking verkooporders", tone: "bg-indigo-100 text-indigo-800 border-indigo-200" },
|
|
21
22
|
import: { label: "Import", tone: "bg-slate-100 text-slate-700 border-slate-200" },
|
|
@@ -69,7 +70,7 @@ export function StockMutationHistoryCard({ tradeItemKey, productId }) {
|
|
|
69
70
|
}
|
|
70
71
|
const { data, error } = await supabase
|
|
71
72
|
.from("stock_mutation_log")
|
|
72
|
-
.select("id,created_at,mutation_type,qty_delta,physical_before,physical_after,reserved_before,reserved_after,reason,order_id")
|
|
73
|
+
.select("id,created_at,mutation_type,qty_delta,physical_before,physical_after,reserved_before,reserved_after,reason,order_id,created_by")
|
|
73
74
|
.in("trade_item_key", [...keys])
|
|
74
75
|
.order("created_at", { ascending: false })
|
|
75
76
|
.limit(100);
|
|
@@ -90,6 +91,18 @@ export function StockMutationHistoryCard({ tradeItemKey, productId }) {
|
|
|
90
91
|
orderNumbers.set(String(o.id), String(o.order_number ?? ""));
|
|
91
92
|
}
|
|
92
93
|
}
|
|
94
|
+
// Wie: namen los ophalen uit profiles (geen databaserelatie).
|
|
95
|
+
const userIds = Array.from(new Set((data ?? []).map((r) => r.created_by).filter(Boolean)));
|
|
96
|
+
const userNames = new Map();
|
|
97
|
+
if (userIds.length > 0) {
|
|
98
|
+
const { data: profs } = await supabase
|
|
99
|
+
.from("profiles")
|
|
100
|
+
.select("id, display_name, email")
|
|
101
|
+
.in("id", userIds);
|
|
102
|
+
for (const p of (profs ?? [])) {
|
|
103
|
+
userNames.set(String(p.id), String(p.display_name || p.email || ""));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
93
106
|
if (cancelled)
|
|
94
107
|
return;
|
|
95
108
|
setRows((data ?? []).map((r) => ({
|
|
@@ -104,6 +117,7 @@ export function StockMutationHistoryCard({ tradeItemKey, productId }) {
|
|
|
104
117
|
reason: r.reason ?? null,
|
|
105
118
|
order_id: r.order_id ?? null,
|
|
106
119
|
order_number: r.order_id ? orderNumbers.get(String(r.order_id)) ?? null : null,
|
|
120
|
+
created_by_name: r.created_by ? userNames.get(String(r.created_by)) || "Onbekende gebruiker" : null,
|
|
107
121
|
})));
|
|
108
122
|
}
|
|
109
123
|
catch (e) {
|
|
@@ -121,7 +135,7 @@ export function StockMutationHistoryCard({ tradeItemKey, productId }) {
|
|
|
121
135
|
supabase.removeChannel(channel);
|
|
122
136
|
};
|
|
123
137
|
}, [tradeItemKey, productId]);
|
|
124
|
-
return (_jsxs(Card, { children: [_jsxs("div", { className: "grid grid-cols-[auto_minmax(0,1fr)_auto] items-center gap-3 px-6 py-4", children: [_jsx("span", { className: "flex h-7 w-7 items-center justify-center rounded-full border border-primary/40 bg-primary/10 text-primary", children: _jsx(History, { className: "h-4 w-4" }) }), _jsx("span", { className: "font-medium", children: "Afboekgeschiedenis" }), _jsx("span", { className: "text-xs text-muted-foreground tabular-nums", children: rows ? `${rows.length} mutatie${rows.length === 1 ? "" : "s"}` : "" })] }), _jsxs(CardContent, { className: "pt-0", children: [error && (_jsxs("div", { className: "text-sm text-destructive", children: ["Kon voorraadmutaties niet laden: ", error] })), !rows && !error && (_jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), " Mutaties laden\u2026"] })), rows && rows.length === 0 && !error && (_jsx("div", { className: "text-sm text-muted-foreground", children: "Nog geen voorraadmutaties voor dit artikel." })), rows && rows.length > 0 && (_jsxs("div", { className: "overflow-x-auto rounded-md border", children: [_jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { className: "bg-muted/50 text-xs uppercase text-muted-foreground", children: _jsxs("tr", { children: [_jsx("th", { className: "px-3 py-2 text-left", children: "Wanneer" }), _jsx("th", { className: "px-3 py-2 text-left", children: "Soort" }), _jsx("th", { className: "px-3 py-2 text-right", children: "Aantal" }), _jsx("th", { className: "px-3 py-2 text-left", children: "Van \u2192 naar" }), _jsx("th", { className: "px-3 py-2 text-left", children: "Order" }), _jsx("th", { className: "px-3 py-2 text-left", children: "Reden" })] }) }), _jsx("tbody", { children: (expanded ? rows : rows.slice(0, 5)).map((r) => {
|
|
138
|
+
return (_jsxs(Card, { children: [_jsxs("div", { className: "grid grid-cols-[auto_minmax(0,1fr)_auto] items-center gap-3 px-6 py-4", children: [_jsx("span", { className: "flex h-7 w-7 items-center justify-center rounded-full border border-primary/40 bg-primary/10 text-primary", children: _jsx(History, { className: "h-4 w-4" }) }), _jsx("span", { className: "font-medium", children: "Afboekgeschiedenis" }), _jsx("span", { className: "text-xs text-muted-foreground tabular-nums", children: rows ? `${rows.length} mutatie${rows.length === 1 ? "" : "s"}` : "" })] }), _jsxs(CardContent, { className: "pt-0", children: [error && (_jsxs("div", { className: "text-sm text-destructive", children: ["Kon voorraadmutaties niet laden: ", error] })), !rows && !error && (_jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), " Mutaties laden\u2026"] })), rows && rows.length === 0 && !error && (_jsx("div", { className: "text-sm text-muted-foreground", children: "Nog geen voorraadmutaties voor dit artikel." })), rows && rows.length > 0 && (_jsxs("div", { className: "overflow-x-auto rounded-md border", children: [_jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { className: "bg-muted/50 text-xs uppercase text-muted-foreground", children: _jsxs("tr", { children: [_jsx("th", { className: "px-3 py-2 text-left", children: "Wanneer" }), _jsx("th", { className: "px-3 py-2 text-left", children: "Soort" }), _jsx("th", { className: "px-3 py-2 text-right", children: "Aantal" }), _jsx("th", { className: "px-3 py-2 text-left", children: "Van \u2192 naar" }), _jsx("th", { className: "px-3 py-2 text-left", children: "Order" }), _jsx("th", { className: "px-3 py-2 text-left", children: "Door" }), _jsx("th", { className: "px-3 py-2 text-left", children: "Reden" })] }) }), _jsx("tbody", { children: (expanded ? rows : rows.slice(0, 5)).map((r) => {
|
|
125
139
|
const meta = TYPE_LABEL[r.mutation_type] ?? {
|
|
126
140
|
label: r.mutation_type || "Onbekend",
|
|
127
141
|
tone: "bg-slate-100 text-slate-700 border-slate-200",
|
|
@@ -132,6 +146,6 @@ export function StockMutationHistoryCard({ tradeItemKey, productId }) {
|
|
|
132
146
|
const resChanged = r.reserved_before !== null &&
|
|
133
147
|
r.reserved_after !== null &&
|
|
134
148
|
r.reserved_before !== r.reserved_after;
|
|
135
|
-
return (_jsxs("tr", { className: "border-t align-top", children: [_jsx("td", { className: "whitespace-nowrap px-3 py-2", children: formatMoment(r.created_at) }), _jsx("td", { className: "px-3 py-2", children: _jsx(Badge, { variant: "outline", className: `border ${meta.tone}`, children: meta.label }) }), _jsxs("td", { className: `px-3 py-2 text-right tabular-nums font-medium ${r.qty_delta < 0 ? "text-rose-700" : r.qty_delta > 0 ? "text-emerald-700" : ""}`, children: [r.qty_delta > 0 ? "+" : "", r.qty_delta] }), _jsxs("td", { className: "whitespace-nowrap px-3 py-2 tabular-nums text-muted-foreground", children: [physChanged && (_jsxs("div", { children: ["Liggend ", r.physical_before, " \u2192 ", r.physical_after] })), resChanged && (_jsxs("div", { children: ["Gereserveerd ", r.reserved_before, " \u2192 ", r.reserved_after] })), !physChanged && !resChanged && _jsx("span", { children: "\u2014" })] }), _jsx("td", { className: "whitespace-nowrap px-3 py-2", children: r.order_id ? (_jsx("a", { href: `/floriday-verkoop/verkooporders/${r.order_id}`, className: "text-primary hover:underline", children: r.order_number ?? "Order" })) : (_jsx("span", { className: "text-muted-foreground", children: "\u2014" })) }), _jsx("td", { className: "px-3 py-2 text-muted-foreground", children: _jsx(CollapsibleText, { text: r.reason }) })] }, r.id));
|
|
149
|
+
return (_jsxs("tr", { className: "border-t align-top", children: [_jsx("td", { className: "whitespace-nowrap px-3 py-2", children: formatMoment(r.created_at) }), _jsx("td", { className: "px-3 py-2", children: _jsx(Badge, { variant: "outline", className: `border ${meta.tone}`, children: meta.label }) }), _jsxs("td", { className: `px-3 py-2 text-right tabular-nums font-medium ${r.qty_delta < 0 ? "text-rose-700" : r.qty_delta > 0 ? "text-emerald-700" : ""}`, children: [r.qty_delta > 0 ? "+" : "", r.qty_delta] }), _jsxs("td", { className: "whitespace-nowrap px-3 py-2 tabular-nums text-muted-foreground", children: [physChanged && (_jsxs("div", { children: ["Liggend ", r.physical_before, " \u2192 ", r.physical_after] })), resChanged && (_jsxs("div", { children: ["Gereserveerd ", r.reserved_before, " \u2192 ", r.reserved_after] })), !physChanged && !resChanged && _jsx("span", { children: "\u2014" })] }), _jsx("td", { className: "whitespace-nowrap px-3 py-2", children: r.order_id ? (_jsx("a", { href: `/floriday-verkoop/verkooporders/${r.order_id}`, className: "text-primary hover:underline", children: r.order_number ?? "Order" })) : (_jsx("span", { className: "text-muted-foreground", children: "\u2014" })) }), _jsx("td", { className: "whitespace-nowrap px-3 py-2 text-muted-foreground", children: r.created_by_name ?? "Systeem" }), _jsx("td", { className: "px-3 py-2 text-muted-foreground", children: _jsx(CollapsibleText, { text: r.reason }) })] }, r.id));
|
|
136
150
|
}) })] }), rows.length > 5 && (_jsx("div", { className: "flex justify-center border-t bg-muted/20 px-3 py-2", children: _jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => setExpanded((current) => !current), className: "gap-1.5", children: expanded ? (_jsxs(_Fragment, { children: [_jsx(ChevronUp, { className: "h-4 w-4" }), " Inklappen"] })) : (_jsxs(_Fragment, { children: [_jsx(ChevronDown, { className: "h-4 w-4" }), " Meer tonen (", rows.length - 5, ")"] })) }) }))] }))] })] }));
|
|
137
151
|
}
|
|
@@ -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":"AA6BA,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,gCAqW3B"}
|
|
@@ -4,7 +4,7 @@ import { useNoPriceProducts } from "../../hooks/useNoPriceProducts.js";
|
|
|
4
4
|
import { pageRequestGuard } from "../../lib/request-guard.js";
|
|
5
5
|
const EMPTY_TRIPS = [];
|
|
6
6
|
import { Link } from "@tanstack/react-router";
|
|
7
|
-
import { Button, Card, Input, Select, SelectContent, SelectItem, SelectTrigger, SelectValue,
|
|
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
10
|
import { FloridayConnectionNotice } from "./FloridayConnectionNotice.js";
|
|
@@ -12,8 +12,6 @@ import { useVoorraadData } from "../../hooks/useVoorraadData.js";
|
|
|
12
12
|
import { StockSyncStatus } from "./StockSyncStatus.js";
|
|
13
13
|
import { StockIntegrityAlert } from "./StockIntegrityAlert.js";
|
|
14
14
|
import { SupplyReadScopeAlert } from "./SupplyReadScopeAlert.js";
|
|
15
|
-
import { StockPushMonitor } from "./StockPushMonitor.js";
|
|
16
|
-
import { FloridayLeadingSummary, FloridayTakeoverPanel } from "./FloridayTakeoverPanel.js";
|
|
17
15
|
import { ExcelExportButton } from "./ExcelExportButton.js";
|
|
18
16
|
import { StockBulkButtons } from "./StockBulkButtons.js";
|
|
19
17
|
import { VoorraadTable } from "./VoorraadTable.js";
|
|
@@ -71,7 +69,6 @@ export function countStock(items) {
|
|
|
71
69
|
return { total: items.length, inStock, outOfStock, belowMin, fullyReserved, freeAvailable };
|
|
72
70
|
}
|
|
73
71
|
export function VoorraadPage() {
|
|
74
|
-
const auth = useAuthState();
|
|
75
72
|
const conn = useFloridayConnection();
|
|
76
73
|
const { activeId, error: connError } = conn;
|
|
77
74
|
const { items, loading, error, reload } = useVoorraadData(activeId);
|
|
@@ -152,7 +149,7 @@ export function VoorraadPage() {
|
|
|
152
149
|
noPriceBreakdown.unit > 0 ? `${noPriceBreakdown.unit} met een andere eenheid dan stuks` : null,
|
|
153
150
|
]
|
|
154
151
|
.filter(Boolean)
|
|
155
|
-
.join(", "), "."] }), " ", "Kies \"Toon deze artikelen\", open een artikel en vul bij Artikel regulier de verkoopprijs per stuk (excl. btw) in. De voorraadsturing van elk artikel heeft ook een link \"Prijs invullen\"."] }), _jsx(Button, { variant: "outline", size: "sm", onClick: () => setNoPriceOnly((v) => !v), children: noPriceOnly ? "Alle artikelen tonen" : "Toon deze artikelen" })] })), _jsx(
|
|
152
|
+
.join(", "), "."] }), " ", "Kies \"Toon deze artikelen\", open een artikel en vul bij Artikel regulier de verkoopprijs per stuk (excl. btw) in. De voorraadsturing van elk artikel heeft ook een link \"Prijs invullen\"."] }), _jsx(Button, { variant: "outline", size: "sm", onClick: () => setNoPriceOnly((v) => !v), children: noPriceOnly ? "Alle artikelen tonen" : "Toon deze artikelen" })] })), _jsx(FloridayConnectionNotice, { status: conn.status, environment: conn.selectedEnvironment, error: connError }), error && (_jsxs("div", { className: "rounded-md border border-destructive/40 bg-destructive/10 text-destructive p-3 text-sm", children: ["Voorraad laden mislukt: ", error] })), _jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-4", children: [_jsx(KpiCard, { icon: _jsx(FileText, { className: "h-4 w-4" }), tone: "primary", label: "Artikelen", count: counts.total, active: stockFilter === "all", onClick: () => toggle("all") }), _jsx(KpiCard, { icon: _jsx(CheckCircle2, { className: "h-4 w-4" }), tone: "emerald", label: "Op voorraad", count: counts.inStock, active: stockFilter === "in_stock", onClick: () => toggle("in_stock"), hint: "Artikelen waarvan nu iets op de kwekerij staat." }), _jsx(KpiCard, { icon: _jsx(CheckCircle2, { className: "h-4 w-4" }), tone: "primary", label: "Vrij beschikbaar", count: counts.freeAvailable, active: false, hint: "Artikelen waarvan na aftrek van wat voor orders gereserveerd is nog iets over is." }), _jsx(KpiCard, { icon: _jsx(PackageX, { className: "h-4 w-4" }), tone: "rose", label: "Niet op voorraad", count: counts.outOfStock, active: stockFilter === "out_of_stock", onClick: () => toggle("out_of_stock") }), _jsx(KpiCard, { icon: _jsx(AlertTriangle, { className: "h-4 w-4" }), tone: "amber", label: "Onder minimum", count: counts.belowMin, active: stockFilter === "below_min", onClick: () => toggle("below_min") })] }), _jsxs(Card, { className: "overflow-hidden p-0", children: [_jsx("div", { className: "flex flex-wrap items-center gap-1 border-b px-4", children: TABS.map((t) => {
|
|
156
153
|
const active = stockFilter === t.id;
|
|
157
154
|
return (_jsxs("button", { type: "button", onClick: () => setStockFilter(t.id), className: `relative py-3 px-3 text-sm font-medium whitespace-nowrap transition-colors ${active
|
|
158
155
|
? "text-foreground"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VoorraadStockCard.d.ts","sourceRoot":"","sources":["../../../src/components/voorraad/VoorraadStockCard.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"VoorraadStockCard.d.ts","sourceRoot":"","sources":["../../../src/components/voorraad/VoorraadStockCard.tsx"],"names":[],"mappings":"AA4BA,UAAU,KAAK;IACb,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,wBAAgB,iBAAiB,CAAC,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,KAAK,sCAiTzF"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useState } from "react";
|
|
3
|
-
import { Button, Card, CardContent, Input, Label, Textarea, toast, } from "@flowselections/core";
|
|
3
|
+
import { Button, Card, CardContent, Input, Label, Textarea, toast, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@flowselections/core";
|
|
4
4
|
import { Loader2, Package, Check } from "lucide-react";
|
|
5
5
|
import { useTradeItemStock, stockKeysFor } from "../../hooks/useTradeItemStock.js";
|
|
6
6
|
import { supabase } from "../../integrations/supabase/client.js";
|
|
7
7
|
import { FloridaySentCard } from "./FloridaySentCard.js";
|
|
8
8
|
import { LOCAL_STOCK_TEXT } from "../../lib/stock-scope.js";
|
|
9
|
+
import { AFBOEK_REDENEN, afboekFout, floridayNaOpslaanTekst, valuesAfterSave } from "../../lib/stock-save.js";
|
|
9
10
|
export function VoorraadStockCard({ connectionId, tradeItemId, draftId, productId }) {
|
|
10
11
|
const keys = stockKeysFor({
|
|
11
12
|
tradeItemId,
|
|
@@ -13,11 +14,16 @@ export function VoorraadStockCard({ connectionId, tradeItemId, draftId, productI
|
|
|
13
14
|
productId,
|
|
14
15
|
});
|
|
15
16
|
const key = keys[0] ?? null;
|
|
16
|
-
const { row, loading, save, error: stockError } = useTradeItemStock(connectionId, keys, productId);
|
|
17
|
+
const { row, loading, save, error: stockError, resolvedKey, resolvedConnectionId, refetch } = useTradeItemStock(connectionId, keys, productId);
|
|
17
18
|
const [values, setValues] = useState(row);
|
|
18
19
|
const [saving, setSaving] = useState(false);
|
|
19
20
|
const [touched, setTouched] = useState(false);
|
|
20
21
|
const [hasBom, setHasBom] = useState(false);
|
|
22
|
+
const [afboekOpen, setAfboekOpen] = useState(false);
|
|
23
|
+
const [afboekAantal, setAfboekAantal] = useState("");
|
|
24
|
+
const [afboekReden, setAfboekReden] = useState(null);
|
|
25
|
+
const [afboekNotitie, setAfboekNotitie] = useState("");
|
|
26
|
+
const [afboekBezig, setAfboekBezig] = useState(false);
|
|
21
27
|
// Heeft dit artikel onderdelen (samenstelling)? Bepaalt alleen het label
|
|
22
28
|
// in de Floriday-kaart. Produceren bestaat niet meer in deze module.
|
|
23
29
|
useEffect(() => {
|
|
@@ -97,18 +103,66 @@ export function VoorraadStockCard({ connectionId, tradeItemId, draftId, productI
|
|
|
97
103
|
setSaving(true);
|
|
98
104
|
try {
|
|
99
105
|
await save(values);
|
|
100
|
-
|
|
106
|
+
setValues(valuesAfterSave(true, values, row));
|
|
107
|
+
setTouched(false);
|
|
108
|
+
let poortOpen = null;
|
|
109
|
+
if (tradeItemId) {
|
|
110
|
+
const { data } = await supabase.rpc("voorraad_floriday_klaarzetten_toegestaan");
|
|
111
|
+
poortOpen = data === true;
|
|
112
|
+
}
|
|
113
|
+
const extra = floridayNaOpslaanTekst(!!tradeItemId, poortOpen);
|
|
114
|
+
toast.success(extra ? `Voorraad opgeslagen. ${extra}` : "Voorraad opgeslagen");
|
|
101
115
|
}
|
|
102
116
|
catch (e) {
|
|
103
|
-
|
|
117
|
+
// Niets opgeslagen: laatst opgeslagen waarden terug in beeld.
|
|
118
|
+
setValues(valuesAfterSave(false, values, row));
|
|
119
|
+
setTouched(false);
|
|
120
|
+
toast.error(`Opslaan mislukt, niets gewijzigd: ${humanError(e)}`);
|
|
104
121
|
}
|
|
105
122
|
finally {
|
|
106
123
|
setSaving(false);
|
|
107
124
|
}
|
|
108
125
|
};
|
|
126
|
+
const handleAfboeken = async () => {
|
|
127
|
+
const aantal = Number(afboekAantal);
|
|
128
|
+
const fout = afboekFout(aantal, afboekReden, Number(row.physical_stock));
|
|
129
|
+
if (fout) {
|
|
130
|
+
toast.error(fout);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const key2 = resolvedKey ?? key;
|
|
134
|
+
if (!key2) {
|
|
135
|
+
toast.error("Sla eerst de voorraad op voordat je afboekt.");
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
setAfboekBezig(true);
|
|
139
|
+
try {
|
|
140
|
+
const { error } = await supabase.rpc("voorraad_afboeken", {
|
|
141
|
+
p_connection_id: resolvedConnectionId ?? connectionId,
|
|
142
|
+
p_trade_item_key: key2,
|
|
143
|
+
p_aantal: aantal,
|
|
144
|
+
p_reden: afboekReden,
|
|
145
|
+
p_notitie: afboekNotitie.trim() || null,
|
|
146
|
+
});
|
|
147
|
+
if (error)
|
|
148
|
+
throw new Error(error.message);
|
|
149
|
+
toast.success(`${aantal} afgeboekt`);
|
|
150
|
+
setAfboekOpen(false);
|
|
151
|
+
setAfboekAantal("");
|
|
152
|
+
setAfboekReden(null);
|
|
153
|
+
setAfboekNotitie("");
|
|
154
|
+
await refetch();
|
|
155
|
+
}
|
|
156
|
+
catch (e) {
|
|
157
|
+
toast.error(`Afboeken mislukt, niets gewijzigd: ${humanError(e)}`);
|
|
158
|
+
}
|
|
159
|
+
finally {
|
|
160
|
+
setAfboekBezig(false);
|
|
161
|
+
}
|
|
162
|
+
};
|
|
109
163
|
const numField = (id, label) => (_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: id, children: label }), _jsx(Input, { id: id, type: "number", min: 0, disabled: !canWrite, value: String(values[id] ?? 0), onChange: (e) => {
|
|
110
164
|
setTouched(true);
|
|
111
165
|
setValues((v) => ({ ...v, [id]: Number(e.target.value) || 0 }));
|
|
112
166
|
} })] }));
|
|
113
|
-
return (_jsxs("div", { className: "space-y-4", children: [_jsxs(Card, { children: [_jsxs("div", { className: "grid grid-cols-[auto_minmax(0,1fr)_auto] items-center gap-3 px-6 py-4", children: [_jsx("span", { className: "flex h-7 w-7 items-center justify-center rounded-full border border-primary/40 bg-primary/10 text-primary", children: _jsx(Package, { className: "h-4 w-4" }) }), _jsx("span", { className: "font-medium", children: "Voorraad" }), _jsxs("span", { className: "text-xs text-muted-foreground", children: ["Beschikbaar: ", _jsx("span", { className: "tabular-nums font-medium text-foreground", children: available })] })] }), _jsx(CardContent, { className: "pt-0 space-y-4", children: loading ? (_jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), " Voorraad laden\u2026"] })) : (_jsxs(_Fragment, { children: [Number(values.reserved_stock) > Number(values.physical_stock) && (_jsxs("div", { className: "rounded-md border border-amber-300 bg-amber-50 px-3 py-2 text-xs text-amber-800", children: ["Let op: er is meer gereserveerd (", Number(values.reserved_stock), ") dan er ligt (", Number(values.physical_stock), "). Controleer de open orders van dit artikel."] })), _jsxs("div", { className: "grid grid-cols-2 gap-4 sm:grid-cols-4", children: [numField("physical_stock", "Liggend"), numField("minimum_stock", "Minimum"),
|
|
167
|
+
return (_jsxs("div", { className: "space-y-4", children: [_jsxs(Card, { children: [_jsxs("div", { className: "grid grid-cols-[auto_minmax(0,1fr)_auto] items-center gap-3 px-6 py-4", children: [_jsx("span", { className: "flex h-7 w-7 items-center justify-center rounded-full border border-primary/40 bg-primary/10 text-primary", children: _jsx(Package, { className: "h-4 w-4" }) }), _jsx("span", { className: "font-medium", children: "Voorraad" }), _jsxs("span", { className: "text-xs text-muted-foreground", children: ["Beschikbaar: ", _jsx("span", { className: "tabular-nums font-medium text-foreground", children: available })] })] }), _jsx(CardContent, { className: "pt-0 space-y-4", children: loading ? (_jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), " Voorraad laden\u2026"] })) : (_jsxs(_Fragment, { children: [Number(values.reserved_stock) > Number(values.physical_stock) && (_jsxs("div", { className: "rounded-md border border-amber-300 bg-amber-50 px-3 py-2 text-xs text-amber-800", children: ["Let op: er is meer gereserveerd (", Number(values.reserved_stock), ") dan er ligt (", Number(values.physical_stock), "). Controleer de open orders van dit artikel."] })), _jsxs("div", { className: "grid grid-cols-2 gap-4 sm:grid-cols-4", children: [numField("physical_stock", "Liggend"), numField("minimum_stock", "Minimum"), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "reserved_stock", children: "Gereserveerd" }), _jsx(Input, { id: "reserved_stock", type: "number", readOnly: true, disabled: true, value: String(values.reserved_stock ?? 0) }), _jsx("p", { className: "text-[11px] text-muted-foreground", children: "Berekend uit open orders" })] }), numField("incoming_stock", "Inkomend")] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "stock-notes", children: "Notitie (optioneel)" }), _jsx(Textarea, { id: "stock-notes", rows: 2, value: values.notes ?? "", disabled: !canWrite, onChange: (e) => setValues((v) => ({ ...v, notes: e.target.value })), placeholder: "Bijv. locatie of opmerking" })] }), _jsxs("div", { className: "flex justify-end", children: [!connectionId && (_jsx("span", { className: "mr-auto self-center text-xs text-muted-foreground", children: LOCAL_STOCK_TEXT })), _jsx(Button, { variant: "outline", className: "mr-2", onClick: () => setAfboekOpen(true), disabled: saving || !canWrite || Number(row.physical_stock) <= 0, children: "Afboeken" }), _jsxs(Button, { onClick: handleSave, disabled: saving || !canWrite, children: [saving ? (_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" })) : (_jsx(Check, { className: "mr-2 h-4 w-4" })), "Voorraad opslaan"] })] })] })) })] }), _jsx(Dialog, { open: afboekOpen, onOpenChange: setAfboekOpen, children: _jsxs(DialogContent, { children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Afboeken" }), _jsxs(DialogDescription, { children: ["Haal planten van de liggende voorraad (", Number(row.physical_stock), "). Kies altijd een reden."] })] }), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "afboek-aantal", children: "Aantal" }), _jsx(Input, { id: "afboek-aantal", type: "number", min: 1, value: afboekAantal, onChange: (e) => setAfboekAantal(e.target.value) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Reden" }), _jsxs(Select, { value: afboekReden ?? undefined, onValueChange: setAfboekReden, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: "Kies een reden" }) }), _jsx(SelectContent, { children: AFBOEK_REDENEN.map((r) => (_jsx(SelectItem, { value: r.value, children: r.label }, r.value))) })] })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { htmlFor: "afboek-notitie", children: "Notitie (optioneel)" }), _jsx(Textarea, { id: "afboek-notitie", rows: 2, value: afboekNotitie, onChange: (e) => setAfboekNotitie(e.target.value) })] })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { variant: "ghost", onClick: () => setAfboekOpen(false), children: "Annuleren" }), _jsxs(Button, { onClick: handleAfboeken, disabled: afboekBezig || !afboekReden || !afboekAantal, children: [afboekBezig && _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Afboeken"] })] })] }) }), _jsx(FloridaySentCard, { connectionId: connectionId, productId: productId, tradeItemId: tradeItemId, productType: isGroupHead ? "GROUP" : hasBom ? "SET" : null })] }));
|
|
114
168
|
}
|
|
@@ -43,6 +43,8 @@ export declare function useTradeItemStock(connectionId: string | null, keyOrKeys
|
|
|
43
43
|
save: (values: TradeItemStockRow) => Promise<void>;
|
|
44
44
|
error: string | null;
|
|
45
45
|
resolvedKey: string | null;
|
|
46
|
+
resolvedConnectionId: string | null;
|
|
47
|
+
refetch: () => Promise<void>;
|
|
46
48
|
};
|
|
47
49
|
export declare function fetchStockMap(connectionId: string | null): Promise<Map<string, TradeItemStockRow>>;
|
|
48
50
|
//# sourceMappingURL=useTradeItemStock.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTradeItemStock.d.ts","sourceRoot":"","sources":["../../src/hooks/useTradeItemStock.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAUD,wBAAgB,WAAW,CAAC,MAAM,EAAE;IAClC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,GAAG,MAAM,GAAG,IAAI,CAEhB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE;IACnC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,GAAG,MAAM,EAAE,CAUX;AAGD;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,EACnC,MAAM,EAAE;IACN,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,GACA,iBAAiB,GAAG,SAAS,CAa/B;AAGD,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,EACnC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;;;mBA0GR,iBAAiB
|
|
1
|
+
{"version":3,"file":"useTradeItemStock.d.ts","sourceRoot":"","sources":["../../src/hooks/useTradeItemStock.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAUD,wBAAgB,WAAW,CAAC,MAAM,EAAE;IAClC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,GAAG,MAAM,GAAG,IAAI,CAEhB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE;IACnC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,GAAG,MAAM,EAAE,CAUX;AAGD;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,EACnC,MAAM,EAAE;IACN,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,GACA,iBAAiB,GAAG,SAAS,CAa/B;AAGD,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,EACnC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;;;mBA0GR,iBAAiB;;;;;EA6FnC;AAED,wBAAsB,aAAa,CACjC,YAAY,EAAE,MAAM,GAAG,IAAI,GAC1B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAuBzC"}
|
|
@@ -185,9 +185,10 @@ export function useTradeItemStock(connectionId, keyOrKeys, productId) {
|
|
|
185
185
|
trade_item_key: primaryKey,
|
|
186
186
|
physical_stock: values.physical_stock,
|
|
187
187
|
minimum_stock: values.minimum_stock,
|
|
188
|
-
|
|
188
|
+
// Gereserveerd wordt berekend uit de orders; nooit vanuit dit scherm schrijven.
|
|
189
189
|
incoming_stock: values.incoming_stock,
|
|
190
190
|
notes: values.notes,
|
|
191
|
+
change_source: "MANUAL_STOCK",
|
|
191
192
|
}, { onConflict: "connection_id,trade_item_key" });
|
|
192
193
|
if (upsertError)
|
|
193
194
|
throw new Error(upsertError.message);
|
|
@@ -196,7 +197,7 @@ export function useTradeItemStock(connectionId, keyOrKeys, productId) {
|
|
|
196
197
|
throw new Error("Ontbrekende connectie of artikel-key");
|
|
197
198
|
}
|
|
198
199
|
const previousPhysical = row?.physical_stock ?? 0;
|
|
199
|
-
setRow(values);
|
|
200
|
+
setRow({ ...values, reserved_stock: row?.reserved_stock ?? values.reserved_stock });
|
|
200
201
|
// Verkoop = daling van de fysieke voorraad. Het bijbehorende aantal
|
|
201
202
|
// fusten wordt automatisch van de fustenvoorraad afgeschreven op basis
|
|
202
203
|
// van de primaire belading van dit artikel.
|
|
@@ -234,7 +235,7 @@ export function useTradeItemStock(connectionId, keyOrKeys, productId) {
|
|
|
234
235
|
}
|
|
235
236
|
})();
|
|
236
237
|
}, [connectionId, primaryKey, productId, resolvedConnectionId, resolvedKey, row]);
|
|
237
|
-
return { row: row ?? EMPTY, loading, save, error, resolvedKey };
|
|
238
|
+
return { row: row ?? EMPTY, loading, save, error, resolvedKey, resolvedConnectionId, refetch };
|
|
238
239
|
}
|
|
239
240
|
export async function fetchStockMap(connectionId) {
|
|
240
241
|
// Met koppeling: alleen de rijen van die koppeling. Zonder koppeling: de
|