@flowselections/floriday-voorraad 1.0.69 → 1.0.71
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 +35 -14
- package/dist-lib/components/voorraad/FloridaySentCard.d.ts.map +1 -1
- package/dist-lib/components/voorraad/FloridaySentCard.js +35 -1
- package/dist-lib/components/voorraad/PriceStatusBadge.d.ts.map +1 -1
- package/dist-lib/components/voorraad/PriceStatusBadge.js +34 -0
- package/dist-lib/components/voorraad/ProductSalePriceField.d.ts.map +1 -1
- package/dist-lib/components/voorraad/ProductSalePriceField.js +5 -2
- package/dist-lib/integrations/supabase/types.d.ts +24 -0
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/__tests__/floriday-base-supply.test.js +3 -2
- package/dist-lib/lib/floriday-base-supply.d.ts +3 -1
- package/dist-lib/lib/floriday-base-supply.d.ts.map +1 -1
- package/dist-lib/lib/floriday-base-supply.js +18 -7
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ArtikelWizard.d.ts","sourceRoot":"","sources":["../../../src/components/voorraad/ArtikelWizard.tsx"],"names":[],"mappings":"AA6MA,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EAAE,cAAc,EACvB,WAAW,EACX,SAAS,EACT,WAAW,GACZ,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;CACjB,+
|
|
1
|
+
{"version":3,"file":"ArtikelWizard.d.ts","sourceRoot":"","sources":["../../../src/components/voorraad/ArtikelWizard.tsx"],"names":[],"mappings":"AA6MA,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EAAE,cAAc,EACvB,WAAW,EACX,SAAS,EACT,WAAW,GACZ,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;CACjB,+BAssEL"}
|
|
@@ -291,7 +291,7 @@ export function ArtikelWizard({ draftId: initialDraftId, tradeItemId, productId,
|
|
|
291
291
|
setProductLoading(true);
|
|
292
292
|
(async () => {
|
|
293
293
|
try {
|
|
294
|
-
const baseCols = "id,product,barcode,article_number,quantity,image_url,plants_per_crate,crates_per_layer,layers_per_cart,trade_item_key,floriday_trade_item_id,custom_fields";
|
|
294
|
+
const baseCols = "id,product,sale_price,unit,barcode,article_number,quantity,image_url,plants_per_crate,crates_per_layer,layers_per_cart,trade_item_key,floriday_trade_item_id,custom_fields";
|
|
295
295
|
let { data: product, error } = await supabase
|
|
296
296
|
.from("products")
|
|
297
297
|
.select(`${baseCols},floriday_packing_confirmed_at,floriday_packing_source`)
|
|
@@ -487,7 +487,10 @@ export function ArtikelWizard({ draftId: initialDraftId, tradeItemId, productId,
|
|
|
487
487
|
: validGtin
|
|
488
488
|
? barcode
|
|
489
489
|
: (payload.gtin ?? ""),
|
|
490
|
-
|
|
490
|
+
// M26: de verkoopprijs van het artikel is leidend (zelfde veld als "Prijs opslaan").
|
|
491
|
+
salePricePerPiece: Number(product.sale_price) > 0
|
|
492
|
+
? Number(product.sale_price)
|
|
493
|
+
: Number(customFields.sale_price ?? customFields.salePrice ?? payload.salePricePerPiece) || 0,
|
|
491
494
|
// Voorkeur: werkelijke voorraad uit trade_item_stock.
|
|
492
495
|
// Fallback: opgeslagen payload-waarde. `products.quantity` wordt
|
|
493
496
|
// bewust NIET meer gelezen — die staat structureel op 0.
|
|
@@ -925,18 +928,34 @@ export function ArtikelWizard({ draftId: initialDraftId, tradeItemId, productId,
|
|
|
925
928
|
}, [spec.characteristics]);
|
|
926
929
|
const wantsPublish = (isEditingPublished && Boolean(tradeItemId)) ||
|
|
927
930
|
(!isEditingPublished && publishToFloriday);
|
|
928
|
-
const readiness = useMemo(() =>
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
931
|
+
const readiness = useMemo(() => {
|
|
932
|
+
const r = buildReadinessReport({
|
|
933
|
+
data,
|
|
934
|
+
spec,
|
|
935
|
+
connectionOk: Boolean(activeId) && connectionReadiness.data?.ready === true,
|
|
936
|
+
connectionLoading: connLoading || connectionReadiness.isLoading,
|
|
937
|
+
environment: activeConnection?.active_environment ?? null,
|
|
938
|
+
connectionMessage: connectionReadiness.data?.message ?? null,
|
|
939
|
+
schemaReady: schemaQuery.isSuccess,
|
|
940
|
+
learnedCharacteristicCodes: serverRequiredCodes,
|
|
941
|
+
characteristicLabels,
|
|
942
|
+
wantsPublish,
|
|
943
|
+
});
|
|
944
|
+
// M26: één controle — elke onvolledige stap (zelfde check als de teller) telt mee.
|
|
945
|
+
const extra = steps
|
|
946
|
+
.filter((s, i) => !stepValidity[i])
|
|
947
|
+
.filter((s) => !r.items.some((it) => it.stepKey === s.key && !it.ok))
|
|
948
|
+
.map((s) => ({
|
|
949
|
+
key: `step-${s.key}`,
|
|
950
|
+
label: `Stap "${s.label}" is nog onvolledig`,
|
|
951
|
+
ok: false,
|
|
952
|
+
stepKey: s.key,
|
|
953
|
+
blocking: true,
|
|
954
|
+
}));
|
|
955
|
+
const items = [...r.items, ...extra];
|
|
956
|
+
const blockers = items.filter((i) => i.blocking && !i.ok);
|
|
957
|
+
return { ok: blockers.length === 0, items, blockers };
|
|
958
|
+
}, [
|
|
940
959
|
data,
|
|
941
960
|
spec,
|
|
942
961
|
activeId,
|
|
@@ -948,6 +967,8 @@ export function ArtikelWizard({ draftId: initialDraftId, tradeItemId, productId,
|
|
|
948
967
|
serverRequiredCodes,
|
|
949
968
|
characteristicLabels,
|
|
950
969
|
wantsPublish,
|
|
970
|
+
steps,
|
|
971
|
+
stepValidity,
|
|
951
972
|
]);
|
|
952
973
|
const goToStepKey = useCallback((key) => {
|
|
953
974
|
const idx = visibleSteps(data).findIndex((s) => s.key === key);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FloridaySentCard.d.ts","sourceRoot":"","sources":["../../../src/components/voorraad/FloridaySentCard.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"FloridaySentCard.d.ts","sourceRoot":"","sources":["../../../src/components/voorraad/FloridaySentCard.tsx"],"names":[],"mappings":"AAWA,KAAK,GAAG,GAAG;IACT,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAUF,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,QAAQ,GAAG,cAAc,GAAG,aAAa,GAAG,YAAY,GAAG,YAAY,GAAG,aAAa,CAAC,GAAG,MAAM,CA0BxI;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,YAAY,EACZ,SAAS,EACT,WAAW,EACX,WAAW,GACZ,EAAE;IACD,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,+BAiIA"}
|
|
@@ -8,6 +8,7 @@ import { useEffect, useState } from "react";
|
|
|
8
8
|
import { Card, CardContent } from "@flowselections/core";
|
|
9
9
|
import { Send } from "lucide-react";
|
|
10
10
|
import { supabase } from "../../integrations/supabase/client";
|
|
11
|
+
import { priceProblem } from "../../lib/floriday-base-supply";
|
|
11
12
|
const MODE_LABEL = {
|
|
12
13
|
FOLLOW_ERP: "Volgt ERP",
|
|
13
14
|
MAXIMUM: "Maximum",
|
|
@@ -46,6 +47,8 @@ export function resultText(r) {
|
|
|
46
47
|
}
|
|
47
48
|
export function FloridaySentCard({ connectionId, productId, tradeItemId, productType, }) {
|
|
48
49
|
const [rows, setRows] = useState([]);
|
|
50
|
+
const [weekPrice, setWeekPrice] = useState({});
|
|
51
|
+
const [reason, setReason] = useState(null);
|
|
49
52
|
useEffect(() => {
|
|
50
53
|
if (!connectionId || (!productId && !tradeItemId))
|
|
51
54
|
return;
|
|
@@ -76,10 +79,41 @@ export function FloridaySentCard({ connectionId, productId, tradeItemId, product
|
|
|
76
79
|
out.push(r);
|
|
77
80
|
}
|
|
78
81
|
setRows(out.slice(0, 8));
|
|
82
|
+
// M26: laatst verzonden prijs per week, ook van inmiddels vervangen regels
|
|
83
|
+
// (latere aantal-wijzigingen sturen geen prijs; die blijft in Floriday staan).
|
|
84
|
+
const { data: priced } = await supabase
|
|
85
|
+
.from("floriday_continuous_stock_queue")
|
|
86
|
+
.select("target_year,target_week,price_sent,updated_at")
|
|
87
|
+
.eq("connection_id", connectionId)
|
|
88
|
+
.or(ors)
|
|
89
|
+
.not("price_sent", "is", null)
|
|
90
|
+
.order("updated_at", { ascending: false })
|
|
91
|
+
.limit(100);
|
|
92
|
+
const wp = {};
|
|
93
|
+
for (const r of (priced ?? [])) {
|
|
94
|
+
const k = `${r.target_year ?? ""}-${r.target_week ?? ""}`;
|
|
95
|
+
if (!(k in wp))
|
|
96
|
+
wp[k] = Number(r.price_sent);
|
|
97
|
+
}
|
|
98
|
+
// M26: werkelijke reden bij "Prijs ontbreekt" uit het artikel zelf.
|
|
99
|
+
let why = null;
|
|
100
|
+
if (productId) {
|
|
101
|
+
const { data: p } = await supabase
|
|
102
|
+
.from("products").select("sale_price,unit").eq("id", productId).maybeSingle();
|
|
103
|
+
if (p)
|
|
104
|
+
why = priceProblem(p.sale_price, p.unit);
|
|
105
|
+
}
|
|
106
|
+
if (cancelled)
|
|
107
|
+
return;
|
|
108
|
+
setWeekPrice(wp);
|
|
109
|
+
setReason(why);
|
|
79
110
|
})();
|
|
80
111
|
return () => {
|
|
81
112
|
cancelled = true;
|
|
82
113
|
};
|
|
83
114
|
}, [connectionId, productId, tradeItemId]);
|
|
84
|
-
return (_jsx(Card, { children: _jsxs(CardContent, { className: "space-y-3 p-4", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx(Send, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium", children: "Laatst naar Floriday" })] }), _jsxs("p", { className: "text-xs text-muted-foreground break-all", children: ["Floriday-id: ", tradeItemId ? _jsx("span", { className: "font-mono", children: tradeItemId }) : "nog niet gekoppeld"] }), (productType === "GROUP" || productType === "SET" || productType === "COMPOSITION") && (_jsx("p", { className: "text-xs text-muted-foreground", children: "Productgroep (ERP): leden met eigen voorraad; alleen het totaal gaat naar Floriday. Set (Floriday): \u00E9\u00E9n artikel samengesteld uit onderdelen; de voorraad gaat pas naar Floriday na akkoord." })), rows.length === 0 ? (_jsx("p", { className: "text-sm text-muted-foreground", children: "Nog niets naar Floriday gestuurd." })) : (_jsx("div", { className: "overflow-x-auto", children: _jsxs("table", { className: "w-full text-xs", children: [_jsx("thead", { className: "text-left text-muted-foreground", children: _jsxs("tr", { children: [_jsx("th", { className: "py-1 pr-3", children: "Week" }), _jsx("th", { className: "py-1 pr-3 text-right", children: "Aantal" }), _jsx("th", { className: "py-1 pr-3 text-right", children: "Prijs (excl. btw)" }), _jsx("th", { className: "py-1 pr-3", children: "Modus" }), _jsx("th", { className: "py-1 pr-3", children: "Tijd" }), _jsx("th", { className: "py-1", children: "Resultaat" })] }) }), _jsx("tbody", { children: rows.map((r) => (_jsxs("tr", { className: "border-t align-top", children: [_jsx("td", { className: "py-1 pr-3 whitespace-nowrap", children: r.target_week ? `${r.target_year}-${r.target_week}` : "—" }), _jsx("td", { className: "py-1 pr-3 text-right tabular-nums", children: r.number_of_pieces ?? "—" }), _jsx("td", { className: "py-1 pr-3 text-right tabular-nums", children:
|
|
115
|
+
return (_jsx(Card, { children: _jsxs(CardContent, { className: "space-y-3 p-4", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx(Send, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium", children: "Laatst naar Floriday" })] }), _jsxs("p", { className: "text-xs text-muted-foreground break-all", children: ["Floriday-id: ", tradeItemId ? _jsx("span", { className: "font-mono", children: tradeItemId }) : "nog niet gekoppeld"] }), (productType === "GROUP" || productType === "SET" || productType === "COMPOSITION") && (_jsx("p", { className: "text-xs text-muted-foreground", children: "Productgroep (ERP): leden met eigen voorraad; alleen het totaal gaat naar Floriday. Set (Floriday): \u00E9\u00E9n artikel samengesteld uit onderdelen; de voorraad gaat pas naar Floriday na akkoord." })), rows.length === 0 ? (_jsx("p", { className: "text-sm text-muted-foreground", children: "Nog niets naar Floriday gestuurd." })) : (_jsx("div", { className: "overflow-x-auto", children: _jsxs("table", { className: "w-full text-xs", children: [_jsx("thead", { className: "text-left text-muted-foreground", children: _jsxs("tr", { children: [_jsx("th", { className: "py-1 pr-3", children: "Week" }), _jsx("th", { className: "py-1 pr-3 text-right", children: "Aantal" }), _jsx("th", { className: "py-1 pr-3 text-right", children: "Prijs (excl. btw)" }), _jsx("th", { className: "py-1 pr-3", children: "Modus" }), _jsx("th", { className: "py-1 pr-3", children: "Tijd" }), _jsx("th", { className: "py-1", children: "Resultaat" })] }) }), _jsx("tbody", { children: rows.map((r) => (_jsxs("tr", { className: "border-t align-top", children: [_jsx("td", { className: "py-1 pr-3 whitespace-nowrap", children: r.target_week ? `${r.target_year}-${r.target_week}` : "—" }), _jsx("td", { className: "py-1 pr-3 text-right tabular-nums", children: r.number_of_pieces ?? "—" }), _jsx("td", { className: "py-1 pr-3 text-right tabular-nums", children: (() => {
|
|
116
|
+
const p = r.price_sent ?? weekPrice[`${r.target_year ?? ""}-${r.target_week ?? ""}`];
|
|
117
|
+
return p != null ? `€ ${Number(p).toFixed(2)}` : "—";
|
|
118
|
+
})() }), _jsx("td", { className: "py-1 pr-3 whitespace-nowrap", children: r.stock_mode ? MODE_LABEL[r.stock_mode] ?? r.stock_mode : "—" }), _jsx("td", { className: "py-1 pr-3 whitespace-nowrap", children: new Date(r.sent_at ?? r.updated_at).toLocaleString("nl-NL") }), _jsxs("td", { className: "py-1", children: [r.status === "skipped_no_price" && reason ? reason : resultText(r), r.price_note && r.price_note !== resultText(r) && (_jsx("div", { className: "text-xs text-muted-foreground", children: r.price_note }))] })] }, r.id))) })] }) }))] }) }));
|
|
85
119
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PriceStatusBadge.d.ts","sourceRoot":"","sources":["../../../src/components/voorraad/PriceStatusBadge.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PriceStatusBadge.d.ts","sourceRoot":"","sources":["../../../src/components/voorraad/PriceStatusBadge.tsx"],"names":[],"mappings":"AAmCA,KAAK,KAAK,GAAG;IACX,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACvC,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC;AAeF,wBAAgB,gBAAgB,CAAC,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE,KAAK,sCA8EpE"}
|
|
@@ -1,6 +1,36 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { CircleDollarSign, Clock, MinusCircle, Loader2 } from "lucide-react";
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
3
4
|
import { useTradeItemSupplyLine } from "../../hooks/useTradeItemSupplyLine.js";
|
|
5
|
+
import { supabase } from "../../integrations/supabase/client.js";
|
|
6
|
+
/** M26: laatst naar Floriday verzonden weekprijs (weekaanbod), uit de wachtrij. */
|
|
7
|
+
function useLastSentPrice(tradeItemId) {
|
|
8
|
+
const [v, setV] = useState(null);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
if (!tradeItemId)
|
|
11
|
+
return;
|
|
12
|
+
let cancelled = false;
|
|
13
|
+
const load = async () => {
|
|
14
|
+
const { data } = await supabase
|
|
15
|
+
.from("floriday_continuous_stock_queue")
|
|
16
|
+
.select("price_sent,target_week,target_year,updated_at")
|
|
17
|
+
.eq("trade_item_id", tradeItemId)
|
|
18
|
+
.not("price_sent", "is", null)
|
|
19
|
+
.order("updated_at", { ascending: false })
|
|
20
|
+
.limit(1)
|
|
21
|
+
.maybeSingle();
|
|
22
|
+
if (!cancelled)
|
|
23
|
+
setV(data ? { price: Number(data.price_sent), week: data.target_week, year: data.target_year, at: data.updated_at } : null);
|
|
24
|
+
};
|
|
25
|
+
void load();
|
|
26
|
+
const t = setInterval(load, 30000);
|
|
27
|
+
return () => {
|
|
28
|
+
cancelled = true;
|
|
29
|
+
clearInterval(t);
|
|
30
|
+
};
|
|
31
|
+
}, [tradeItemId]);
|
|
32
|
+
return v;
|
|
33
|
+
}
|
|
4
34
|
function formatDate(iso) {
|
|
5
35
|
if (!iso)
|
|
6
36
|
return "—";
|
|
@@ -17,11 +47,15 @@ function formatDate(iso) {
|
|
|
17
47
|
}
|
|
18
48
|
export function PriceStatusBadge({ tradeItemId, offerForSale }) {
|
|
19
49
|
const { data: supplyLine, isLoading } = useTradeItemSupplyLine(tradeItemId);
|
|
50
|
+
const sent = useLastSentPrice(tradeItemId);
|
|
20
51
|
if (!tradeItemId)
|
|
21
52
|
return null;
|
|
22
53
|
if (isLoading) {
|
|
23
54
|
return (_jsxs("span", { className: "inline-flex items-center gap-1 text-xs px-2 py-0.5 rounded-full bg-muted text-muted-foreground", children: [_jsx(Loader2, { className: "h-3 w-3 animate-spin" }), " Prijsstatus laden\u2026"] }));
|
|
24
55
|
}
|
|
56
|
+
if (!supplyLine && sent) {
|
|
57
|
+
return (_jsxs("span", { className: "inline-flex items-center gap-1 text-xs px-2 py-0.5 rounded-full cursor-help bg-emerald-100 text-emerald-700", title: `Weekaanbod verzonden op ${new Date(sent.at).toLocaleString("nl-NL")}`, children: [_jsx(CircleDollarSign, { className: "h-3 w-3" }), " Prijs live in Floriday \u00B7 week ", sent.week ?? "?", " \u00B7 \u20AC ", sent.price.toFixed(2)] }));
|
|
58
|
+
}
|
|
25
59
|
const now = Date.now();
|
|
26
60
|
const endMs = supplyLine?.period_end ? new Date(supplyLine.period_end).getTime() : null;
|
|
27
61
|
const qty = supplyLine?.available_quantity ?? 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProductSalePriceField.d.ts","sourceRoot":"","sources":["../../../src/components/voorraad/ProductSalePriceField.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ProductSalePriceField.d.ts","sourceRoot":"","sources":["../../../src/components/voorraad/ProductSalePriceField.tsx"],"names":[],"mappings":"AAmBA,wBAAgB,qBAAqB,CAAC,EACpC,SAAS,EACT,OAAO,GACR,EAAE;IACD,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC,sCAkGA;AAED,wFAAwF;AACxF,wBAAgB,kBAAkB,CAAC,EAAE,SAAS,EAAE,EAAE;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,sCAqCtE"}
|
|
@@ -11,6 +11,7 @@ import { Link } from "@tanstack/react-router";
|
|
|
11
11
|
import { Button, Input, Label, toast } from "@flowselections/core";
|
|
12
12
|
import { AlertTriangle, Loader2 } from "lucide-react";
|
|
13
13
|
import { supabase } from "../../integrations/supabase/client";
|
|
14
|
+
import { priceProblem } from "../../lib/floriday-base-supply";
|
|
14
15
|
function isPieceUnit(unit) {
|
|
15
16
|
const u = String(unit ?? "").trim().toLowerCase();
|
|
16
17
|
return u === "" || u === "stuks" || u === "stuk";
|
|
@@ -81,11 +82,12 @@ export function ProductSalePriceField({ productId, onSaved, }) {
|
|
|
81
82
|
};
|
|
82
83
|
if (!exists)
|
|
83
84
|
return null;
|
|
84
|
-
return (_jsxs("div", { id: "verkoopprijs", className: "space-y-2 rounded-md border p-4", children: [_jsx(Label, { htmlFor: `price-${productId}`, children: "Verkoopprijs per stuk (excl. btw)" }), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx(Input, { id: `price-${productId}`, inputMode: "decimal", className: "w-40", placeholder: "Bijv. 1,40", disabled: !loaded || saving, value: value, onChange: (e) => setValue(e.target.value) }), _jsxs(Button, { size: "sm", disabled: !dirty || saving, onClick: () => void save(), children: [saving && _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), saving ? "Bezig met opslaan…" : "Prijs opslaan"] })] }), value.trim() !== "" && !valid && (_jsx("p", { className: "text-xs text-destructive", children: "Vul een prijs groter dan 0 in, met maximaal 5 decimalen." })), loaded && !isPieceUnit(unit) && (_jsxs("p", { className: "text-xs text-amber-700", children: ["Eenheid
|
|
85
|
+
return (_jsxs("div", { id: "verkoopprijs", className: "space-y-2 rounded-md border p-4", children: [_jsx(Label, { htmlFor: `price-${productId}`, children: "Verkoopprijs per stuk (excl. btw)" }), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx(Input, { id: `price-${productId}`, inputMode: "decimal", className: "w-40", placeholder: "Bijv. 1,40", disabled: !loaded || saving, value: value, onChange: (e) => setValue(e.target.value) }), _jsxs(Button, { size: "sm", disabled: !dirty || saving, onClick: () => void save(), children: [saving && _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), saving ? "Bezig met opslaan…" : "Prijs opslaan"] })] }), value.trim() !== "" && !valid && (_jsx("p", { className: "text-xs text-destructive", children: "Vul een prijs groter dan 0 in, met maximaal 5 decimalen." })), loaded && !isPieceUnit(unit) && (_jsxs("p", { className: "text-xs text-amber-700", children: ["Eenheid is geen stuks (nu: ", unit, "): de prijs telt voor Floriday alleen bij eenheid \"stuks\"."] })), loaded && !(saved && saved > 0) && (_jsx("p", { className: "text-xs text-muted-foreground", children: "Zonder prijs komt dit artikel niet in Floriday (\"Prijs ontbreekt\")." })), error && _jsx("p", { role: "alert", className: "text-xs text-destructive", children: error })] }));
|
|
85
86
|
}
|
|
86
87
|
/** Melding met directe link naar het prijsveld; toont niets als de prijs in orde is. */
|
|
87
88
|
export function MissingPriceNotice({ productId }) {
|
|
88
89
|
const [state, setState] = useState(null);
|
|
90
|
+
const [why, setWhy] = useState(null);
|
|
89
91
|
useEffect(() => {
|
|
90
92
|
let cancelled = false;
|
|
91
93
|
(async () => {
|
|
@@ -96,6 +98,7 @@ export function MissingPriceNotice({ productId }) {
|
|
|
96
98
|
.maybeSingle();
|
|
97
99
|
if (cancelled || !data)
|
|
98
100
|
return;
|
|
101
|
+
setWhy(priceProblem(data.sale_price, data.unit));
|
|
99
102
|
if (!isPieceUnit(data.unit))
|
|
100
103
|
setState("unit");
|
|
101
104
|
else
|
|
@@ -107,5 +110,5 @@ export function MissingPriceNotice({ productId }) {
|
|
|
107
110
|
}, [productId]);
|
|
108
111
|
if (state !== "missing" && state !== "unit")
|
|
109
112
|
return null;
|
|
110
|
-
return (_jsxs("div", { className: "flex flex-wrap items-center gap-2 rounded-md border border-amber-500/30 bg-amber-500/10 px-3 py-2 text-sm text-amber-800", children: [_jsx(AlertTriangle, { className: "h-4 w-4 shrink-0" }),
|
|
113
|
+
return (_jsxs("div", { className: "flex flex-wrap items-center gap-2 rounded-md border border-amber-500/30 bg-amber-500/10 px-3 py-2 text-sm text-amber-800", children: [_jsx(AlertTriangle, { className: "h-4 w-4 shrink-0" }), _jsxs("span", { className: "flex-1", children: [why ?? (state === "missing" ? "Prijs ontbreekt" : "Eenheid is geen stuks"), ": dit artikel gaat niet naar Floriday."] }), _jsx(Link, { to: "/voorraad/$id", params: { id: productId }, hash: "verkoopprijs", className: "font-medium underline", children: "Prijs invullen" })] }));
|
|
111
114
|
}
|
|
@@ -26394,6 +26394,7 @@ export type Database = {
|
|
|
26394
26394
|
created_by: string;
|
|
26395
26395
|
customer_id: string | null;
|
|
26396
26396
|
id: string;
|
|
26397
|
+
offerte_id: string | null;
|
|
26397
26398
|
payload: Json;
|
|
26398
26399
|
reden: string | null;
|
|
26399
26400
|
status: string;
|
|
@@ -26409,6 +26410,7 @@ export type Database = {
|
|
|
26409
26410
|
created_by?: string;
|
|
26410
26411
|
customer_id?: string | null;
|
|
26411
26412
|
id?: string;
|
|
26413
|
+
offerte_id?: string | null;
|
|
26412
26414
|
payload?: Json;
|
|
26413
26415
|
reden?: string | null;
|
|
26414
26416
|
status?: string;
|
|
@@ -26424,6 +26426,7 @@ export type Database = {
|
|
|
26424
26426
|
created_by?: string;
|
|
26425
26427
|
customer_id?: string | null;
|
|
26426
26428
|
id?: string;
|
|
26429
|
+
offerte_id?: string | null;
|
|
26427
26430
|
payload?: Json;
|
|
26428
26431
|
reden?: string | null;
|
|
26429
26432
|
status?: string;
|
|
@@ -29810,6 +29813,12 @@ export type Database = {
|
|
|
29810
29813
|
};
|
|
29811
29814
|
Returns: string;
|
|
29812
29815
|
};
|
|
29816
|
+
logistics_afhandeling_fulfillment_order: {
|
|
29817
|
+
Args: {
|
|
29818
|
+
_order_id: string;
|
|
29819
|
+
};
|
|
29820
|
+
Returns: Json;
|
|
29821
|
+
};
|
|
29813
29822
|
logistics_allocation_check_changes: {
|
|
29814
29823
|
Args: {
|
|
29815
29824
|
p_order_item_ids?: string[];
|
|
@@ -31934,6 +31943,14 @@ export type Database = {
|
|
|
31934
31943
|
};
|
|
31935
31944
|
Returns: Json;
|
|
31936
31945
|
};
|
|
31946
|
+
logistics_shipping_note_wait_reasons: {
|
|
31947
|
+
Args: never;
|
|
31948
|
+
Returns: {
|
|
31949
|
+
order_number: string;
|
|
31950
|
+
reden: string;
|
|
31951
|
+
wacht_sinds: string;
|
|
31952
|
+
}[];
|
|
31953
|
+
};
|
|
31937
31954
|
logistics_shipping_note_wake: {
|
|
31938
31955
|
Args: {
|
|
31939
31956
|
_slip_job_id: string;
|
|
@@ -35375,6 +35392,13 @@ export type Database = {
|
|
|
35375
35392
|
};
|
|
35376
35393
|
Returns: Json;
|
|
35377
35394
|
};
|
|
35395
|
+
wo_send_proposal_to_quote: {
|
|
35396
|
+
Args: {
|
|
35397
|
+
_id: string;
|
|
35398
|
+
_overrides?: Json;
|
|
35399
|
+
};
|
|
35400
|
+
Returns: Json;
|
|
35401
|
+
};
|
|
35378
35402
|
wo_send_to_quote: {
|
|
35379
35403
|
Args: {
|
|
35380
35404
|
_werkbon_id: string;
|