@flowselections/floriday-voorraad 1.0.115 → 1.0.121
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/VoorraadPage.d.ts +3 -3
- package/dist-lib/components/voorraad/VoorraadPage.d.ts.map +1 -1
- package/dist-lib/components/voorraad/VoorraadPage.js +9 -7
- package/dist-lib/components/voorraad/__tests__/count-stock-free.test.d.ts +2 -0
- package/dist-lib/components/voorraad/__tests__/count-stock-free.test.d.ts.map +1 -0
- package/dist-lib/components/voorraad/__tests__/count-stock-free.test.js +12 -0
- package/dist-lib/integrations/supabase/types.d.ts +611 -0
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/__tests__/floricode-required-features.test.js +7 -3
- package/dist-lib/lib/__tests__/publish-packing-block.test.d.ts +2 -0
- package/dist-lib/lib/__tests__/publish-packing-block.test.d.ts.map +1 -0
- package/dist-lib/lib/__tests__/publish-packing-block.test.js +14 -0
- package/dist-lib/lib/publish-errors.d.ts +9 -0
- package/dist-lib/lib/publish-errors.d.ts.map +1 -1
- package/dist-lib/lib/publish-errors.js +42 -0
- package/package.json +1 -1
- package/sql/AGENTS.md +2 -0
- package/sql/floriday-voorraad-schema.sql +331 -86
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { TradeItem } from "../../lib/floriday-client.js";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
* beschikbaar
|
|
5
|
-
* als "Niet op voorraad" zien zonder dat er iets was afgeboekt.
|
|
3
|
+
* "Op voorraad" = artikelen met liggende voorraad (fysiek > 0).
|
|
4
|
+
* "Vrij beschikbaar" = artikelen waarvan liggend min gereserveerd > 0.
|
|
6
5
|
*/
|
|
7
6
|
export declare function countStock(items: Array<Pick<TradeItem, "quantity" | "availableQuantity" | "minQuantity">>): {
|
|
8
7
|
total: number;
|
|
@@ -10,6 +9,7 @@ export declare function countStock(items: Array<Pick<TradeItem, "quantity" | "av
|
|
|
10
9
|
outOfStock: number;
|
|
11
10
|
belowMin: number;
|
|
12
11
|
fullyReserved: number;
|
|
12
|
+
freeAvailable: number;
|
|
13
13
|
};
|
|
14
14
|
export declare function VoorraadPage(): import("react").JSX.Element;
|
|
15
15
|
//# sourceMappingURL=VoorraadPage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
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;
|
|
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;AAqF3D;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,GAAG,mBAAmB,GAAG,aAAa,CAAC,CAAC;;;;;;;EAgBzG;AAED,wBAAgB,YAAY,gCA0W3B"}
|
|
@@ -37,23 +37,23 @@ function toneClasses(tone) {
|
|
|
37
37
|
return { icon: "bg-primary/10 text-primary", value: "text-foreground" };
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
-
function KpiCard({ icon, label, count, tone, active, onClick, }) {
|
|
40
|
+
function KpiCard({ icon, label, count, tone, active, onClick, hint, }) {
|
|
41
41
|
const cls = toneClasses(tone);
|
|
42
|
-
return (_jsxs("button", { type: "button", onClick: onClick, className: `text-left rounded-lg border bg-card p-4 transition-colors hover:border-primary/50 ${active ? "border-primary ring-1 ring-primary" : "border-border"}`, children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: `inline-flex h-8 w-8 items-center justify-center rounded-md ${cls.icon}`, children: icon }), _jsx("span", { className: "text-sm font-medium text-foreground", children: label })] }), _jsx("div", { className: `mt-3 text-3xl font-bold tabular-nums ${cls.value}`, children: count })] }));
|
|
42
|
+
return (_jsxs("button", { type: "button", onClick: onClick, title: hint, className: `text-left rounded-lg border bg-card p-4 transition-colors hover:border-primary/50 ${active ? "border-primary ring-1 ring-primary" : "border-border"}`, children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: `inline-flex h-8 w-8 items-center justify-center rounded-md ${cls.icon}`, children: icon }), _jsx("span", { className: "text-sm font-medium text-foreground", children: label })] }), _jsx("div", { className: `mt-3 text-3xl font-bold tabular-nums ${cls.value}`, children: count }), hint && _jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: hint })] }));
|
|
43
43
|
}
|
|
44
44
|
function availableOf(i) {
|
|
45
45
|
return i.availableQuantity ?? i.quantity ?? 0;
|
|
46
46
|
}
|
|
47
47
|
/**
|
|
48
|
-
*
|
|
49
|
-
* beschikbaar
|
|
50
|
-
* als "Niet op voorraad" zien zonder dat er iets was afgeboekt.
|
|
48
|
+
* "Op voorraad" = artikelen met liggende voorraad (fysiek > 0).
|
|
49
|
+
* "Vrij beschikbaar" = artikelen waarvan liggend min gereserveerd > 0.
|
|
51
50
|
*/
|
|
52
51
|
export function countStock(items) {
|
|
53
52
|
let inStock = 0;
|
|
54
53
|
let outOfStock = 0;
|
|
55
54
|
let belowMin = 0;
|
|
56
55
|
let fullyReserved = 0;
|
|
56
|
+
let freeAvailable = 0;
|
|
57
57
|
for (const i of items) {
|
|
58
58
|
const physical = Number(i.quantity ?? 0);
|
|
59
59
|
const avail = availableOf(i);
|
|
@@ -61,12 +61,14 @@ export function countStock(items) {
|
|
|
61
61
|
inStock++;
|
|
62
62
|
else
|
|
63
63
|
outOfStock++;
|
|
64
|
+
if (avail > 0)
|
|
65
|
+
freeAvailable++;
|
|
64
66
|
if (physical > 0 && avail <= 0)
|
|
65
67
|
fullyReserved++;
|
|
66
68
|
if ((i.minQuantity ?? 0) > 0 && avail < (i.minQuantity ?? 0))
|
|
67
69
|
belowMin++;
|
|
68
70
|
}
|
|
69
|
-
return { total: items.length, inStock, outOfStock, belowMin, fullyReserved };
|
|
71
|
+
return { total: items.length, inStock, outOfStock, belowMin, fullyReserved, freeAvailable };
|
|
70
72
|
}
|
|
71
73
|
export function VoorraadPage() {
|
|
72
74
|
const auth = useAuthState();
|
|
@@ -150,7 +152,7 @@ export function VoorraadPage() {
|
|
|
150
152
|
noPriceBreakdown.unit > 0 ? `${noPriceBreakdown.unit} met een andere eenheid dan stuks` : null,
|
|
151
153
|
]
|
|
152
154
|
.filter(Boolean)
|
|
153
|
-
.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(FloridayLeadingSummary, { connectionId: activeId ?? null }), auth.isAdmin && _jsx(FloridayTakeoverPanel, { connectionId: activeId ?? null }), auth.isAdmin && _jsx(StockPushMonitor, { connectionId: activeId ?? null }), _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-
|
|
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(FloridayLeadingSummary, { connectionId: activeId ?? null }), auth.isAdmin && _jsx(FloridayTakeoverPanel, { connectionId: activeId ?? null }), auth.isAdmin && _jsx(StockPushMonitor, { connectionId: activeId ?? null }), _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) => {
|
|
154
156
|
const active = stockFilter === t.id;
|
|
155
157
|
return (_jsxs("button", { type: "button", onClick: () => setStockFilter(t.id), className: `relative py-3 px-3 text-sm font-medium whitespace-nowrap transition-colors ${active
|
|
156
158
|
? "text-foreground"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"count-stock-free.test.d.ts","sourceRoot":"","sources":["../../../../src/components/voorraad/__tests__/count-stock-free.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { countStock } from "../VoorraadPage.js";
|
|
3
|
+
describe("countStock vrij beschikbaar", () => {
|
|
4
|
+
it("liggend 100 met 100 gereserveerd: op voorraad, niet vrij", () => {
|
|
5
|
+
const c = countStock([{ quantity: 100, availableQuantity: 0, minQuantity: 0 }]);
|
|
6
|
+
expect(c.inStock).toBe(1);
|
|
7
|
+
expect(c.freeAvailable).toBe(0);
|
|
8
|
+
});
|
|
9
|
+
it("liggend 100 met 40 gereserveerd: vrij", () => {
|
|
10
|
+
expect(countStock([{ quantity: 100, availableQuantity: 60, minQuantity: 0 }]).freeAvailable).toBe(1);
|
|
11
|
+
});
|
|
12
|
+
});
|