@flowselections/floriday-voorraad 1.0.122 → 1.0.125

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.
Files changed (45) hide show
  1. package/dist-lib/components/voorraad/ArtikelWizard.d.ts +14 -1
  2. package/dist-lib/components/voorraad/ArtikelWizard.d.ts.map +1 -1
  3. package/dist-lib/components/voorraad/ArtikelWizard.js +88 -26
  4. package/dist-lib/components/voorraad/FloridayInfoCard.d.ts.map +1 -1
  5. package/dist-lib/components/voorraad/FloridayInfoCard.js +4 -2
  6. package/dist-lib/components/voorraad/FloridayLoadCarriers.d.ts.map +1 -1
  7. package/dist-lib/components/voorraad/FloridayLoadCarriers.js +3 -2
  8. package/dist-lib/components/voorraad/NieuwArtikelPage.d.ts.map +1 -1
  9. package/dist-lib/components/voorraad/NieuwArtikelPage.js +72 -6
  10. package/dist-lib/components/voorraad/PublishProgressCard.d.ts +7 -0
  11. package/dist-lib/components/voorraad/PublishProgressCard.d.ts.map +1 -1
  12. package/dist-lib/components/voorraad/PublishProgressCard.js +22 -1
  13. package/dist-lib/components/voorraad/StockSyncStatus.js +1 -1
  14. package/dist-lib/hooks/useLoadCarriers.d.ts +12 -0
  15. package/dist-lib/hooks/useLoadCarriers.d.ts.map +1 -0
  16. package/dist-lib/hooks/useLoadCarriers.js +49 -0
  17. package/dist-lib/hooks/usePublishJob.d.ts +1 -0
  18. package/dist-lib/hooks/usePublishJob.d.ts.map +1 -1
  19. package/dist-lib/hooks/usePublishJob.js +20 -1
  20. package/dist-lib/hooks/useStockSyncHealth.d.ts +3 -1
  21. package/dist-lib/hooks/useStockSyncHealth.d.ts.map +1 -1
  22. package/dist-lib/hooks/useStockSyncHealth.js +68 -19
  23. package/dist-lib/integrations/supabase/types.d.ts +192 -0
  24. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  25. package/dist-lib/lib/__tests__/erp-test-123.test.d.ts +2 -0
  26. package/dist-lib/lib/__tests__/erp-test-123.test.d.ts.map +1 -0
  27. package/dist-lib/lib/__tests__/erp-test-123.test.js +43 -0
  28. package/dist-lib/lib/__tests__/load-carriers.test.d.ts +2 -0
  29. package/dist-lib/lib/__tests__/load-carriers.test.d.ts.map +1 -0
  30. package/dist-lib/lib/__tests__/load-carriers.test.js +15 -0
  31. package/dist-lib/lib/buyer-organizations.d.ts +26 -0
  32. package/dist-lib/lib/buyer-organizations.d.ts.map +1 -0
  33. package/dist-lib/lib/buyer-organizations.js +41 -0
  34. package/dist-lib/lib/floriday-customer-offer.functions.d.ts +4 -0
  35. package/dist-lib/lib/floriday-customer-offer.functions.d.ts.map +1 -1
  36. package/dist-lib/lib/floriday-customer-offer.functions.js +54 -16
  37. package/dist-lib/lib/floriday-info.d.ts +0 -1
  38. package/dist-lib/lib/floriday-info.d.ts.map +1 -1
  39. package/dist-lib/lib/floriday-info.js +0 -8
  40. package/dist-lib/lib/simple-packing.d.ts +31 -0
  41. package/dist-lib/lib/simple-packing.d.ts.map +1 -0
  42. package/dist-lib/lib/simple-packing.js +62 -0
  43. package/package.json +1 -1
  44. package/sql/AGENTS.md +2 -1
  45. package/sql/floriday-voorraad-schema.sql +328 -5
@@ -44,5 +44,5 @@ export function StockSyncStatus() {
44
44
  if (stalePending > 0) {
45
45
  parts.push(`${stalePending} wacht${stalePending === 1 ? "" : "en"} langer dan 10 minuten`);
46
46
  }
47
- return (_jsxs("div", { className: "flex items-start 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: "mt-0.5 h-4 w-4 shrink-0" }), _jsxs("div", { className: "flex-1 space-y-0.5", children: [parts.length > 0 && (_jsxs("div", { children: [_jsx("span", { className: "font-medium", children: "Voorraadsync naar Floriday: " }), parts.join(" · "), " (laatste 24 uur), voor ", articleCount, " artikel", articleCount === 1 ? "" : "en", ".", oldestPendingAt && (_jsxs("span", { className: "opacity-80", children: [" ", "Oudste wachtende regel: ", new Date(oldestPendingAt).toLocaleString("nl-NL"), "."] }))] })), cause && (_jsxs("div", { children: [_jsx("span", { className: "font-medium", children: "Oorzaak: " }), cause] })), blockedCount > 0 && (_jsxs("div", { className: "space-y-0.5", children: [_jsxs("div", { children: [_jsx("span", { className: "font-medium", children: "Wacht op Floriday \u2013 verpakkingsverschil: " }), blockedCount, " regel", blockedCount === 1 ? "" : "s", " tegengehouden."] }), _jsxs("ul", { className: "list-disc pl-5 text-xs", children: [blocked.map((b) => (_jsx("li", { children: _jsx(Link, { to: "/voorraad/$id", params: { id: b.productId }, className: "underline hover:no-underline", children: gateBlockedText({ name: b.name, code: b.code }) }) }, b.productId))), data.blockedWithoutProduct > 0 && (_jsxs("li", { children: [data.blockedWithoutProduct, " regel", data.blockedWithoutProduct === 1 ? "" : "s", " zonder bekend artikel"] }))] })] })), topReason && (_jsxs("div", { children: [_jsx("span", { className: "font-medium", children: "Meest voorkomende reden: " }), topReason, "."] })), noPriceCount > 0 && (_jsxs("div", { className: "opacity-90", children: [noPriceCount, " van deze artikelen ", noPriceCount === 1 ? "heeft" : "hebben", " nog geen prijs in het weekaanbod; het aantal wordt dan zonder prijs doorgezet."] }))] }), failed > 0 && (_jsxs("button", { type: "button", className: "inline-flex shrink-0 items-center rounded-md border border-amber-500/40 bg-amber-500/10 px-2 py-1 text-xs font-medium text-amber-900 hover:bg-amber-500/20 disabled:opacity-50", disabled: mutation.isPending, onClick: () => mutation.mutate(), children: [_jsx(RotateCw, { className: `mr-1 h-3.5 w-3.5 ${mutation.isPending ? "animate-spin" : ""}` }), "Opnieuw proberen"] }))] }));
47
+ return (_jsxs("div", { className: "flex items-start 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: "mt-0.5 h-4 w-4 shrink-0" }), _jsxs("div", { className: "flex-1 space-y-0.5", children: [parts.length > 0 && (_jsxs("div", { children: [_jsx("span", { className: "font-medium", children: "Voorraadsync naar Floriday: " }), parts.join(" · "), " (laatste 24 uur), voor ", articleCount, " artikel", articleCount === 1 ? "" : "en", ".", oldestPendingAt && (_jsxs("span", { className: "opacity-80", children: [" ", "Oudste wachtende regel: ", new Date(oldestPendingAt).toLocaleString("nl-NL"), "."] }))] })), cause && (_jsxs("div", { children: [_jsx("span", { className: "font-medium", children: "Oorzaak: " }), cause] })), blockedCount > 0 && (_jsxs("div", { className: "space-y-0.5", children: [_jsxs("div", { children: [_jsx("span", { className: "font-medium", children: "Wacht op Floriday \u2013 verpakkingsverschil: " }), blockedCount, " artikel", blockedCount === 1 ? "" : "en", " tegengehouden."] }), _jsxs("ul", { className: "list-disc pl-5 text-xs", children: [blocked.map((b) => (_jsx("li", { children: _jsx(Link, { to: "/voorraad/$id", params: { id: b.productId }, className: "underline hover:no-underline", children: gateBlockedText({ name: b.name, code: b.code }) }) }, b.productId))), data.blockedWithoutProduct > 0 && (_jsxs("li", { children: [data.blockedWithoutProduct, " Floriday-artikel", data.blockedWithoutProduct === 1 ? "" : "en", " zonder lokaal artikel"] }))] })] })), topReason && (_jsxs("div", { children: [_jsx("span", { className: "font-medium", children: "Meest voorkomende reden: " }), topReason, "."] })), noPriceCount > 0 && (_jsxs("div", { className: "opacity-90", children: [noPriceCount, " van deze artikelen ", noPriceCount === 1 ? "heeft" : "hebben", " nog geen prijs in het weekaanbod; het aantal wordt dan zonder prijs doorgezet."] }))] }), failed > 0 && (_jsxs("button", { type: "button", className: "inline-flex shrink-0 items-center rounded-md border border-amber-500/40 bg-amber-500/10 px-2 py-1 text-xs font-medium text-amber-900 hover:bg-amber-500/20 disabled:opacity-50", disabled: mutation.isPending, onClick: () => mutation.mutate(), children: [_jsx(RotateCw, { className: `mr-1 h-3.5 w-3.5 ${mutation.isPending ? "animate-spin" : ""}` }), "Opnieuw proberen"] }))] }));
48
48
  }
@@ -0,0 +1,12 @@
1
+ export interface LoadCarrierType {
2
+ code: string;
3
+ naam: string;
4
+ volgorde: number;
5
+ }
6
+ export declare function loadCarriersFromRows(rows: unknown): LoadCarrierType[];
7
+ export declare function useLoadCarriers(): {
8
+ items: LoadCarrierType[];
9
+ error: string | null;
10
+ label: (code: string | null | undefined) => string;
11
+ };
12
+ //# sourceMappingURL=useLoadCarriers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLoadCarriers.d.ts","sourceRoot":"","sources":["../../src/hooks/useLoadCarriers.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAKD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,eAAe,EAAE,CAKrE;AAQD,wBAAgB,eAAe;;;kBAqBR,MAAM,GAAG,IAAI,GAAG,SAAS;EAE/C"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Gedeelde lijst ladingdragers uit de database (`voorraad_load_carriers()`).
3
+ * Codes zijn Floriday-codes (DANISH_TROLLEY enz.), zoals bewaard in
4
+ * `product_packings.load_carrier`. Productontwerp leest dezelfde functie.
5
+ * Geen vaste kopie in de code en geen terugvallijst: lukt lezen niet, dan `error`.
6
+ */
7
+ import { useEffect, useMemo, useState } from "react";
8
+ import { supabase } from "../integrations/supabase/client.js";
9
+ let cache = null;
10
+ let pending = null;
11
+ export function loadCarriersFromRows(rows) {
12
+ return (rows ?? [])
13
+ .filter((r) => r && typeof r.code === "string" && r.code)
14
+ .map((r) => ({ code: String(r.code), naam: String(r.naam ?? r.code), volgorde: Number(r.volgorde ?? 0) }))
15
+ .sort((a, b) => a.volgorde - b.volgorde);
16
+ }
17
+ async function fetchLoadCarriers() {
18
+ const { data, error } = await supabase.rpc("voorraad_load_carriers");
19
+ if (error)
20
+ throw new Error(`Ladingdragers konden niet worden gelezen: ${error.message}`);
21
+ return loadCarriersFromRows(data);
22
+ }
23
+ export function useLoadCarriers() {
24
+ const [items, setItems] = useState(cache ?? []);
25
+ const [error, setError] = useState(null);
26
+ useEffect(() => {
27
+ if (cache)
28
+ return;
29
+ let alive = true;
30
+ pending ?? (pending = fetchLoadCarriers());
31
+ pending
32
+ .then((list) => {
33
+ cache = list;
34
+ if (alive)
35
+ setItems(list);
36
+ })
37
+ .catch((e) => {
38
+ pending = null;
39
+ if (alive)
40
+ setError(e instanceof Error ? e.message : String(e));
41
+ });
42
+ return () => {
43
+ alive = false;
44
+ };
45
+ }, []);
46
+ const labels = useMemo(() => new Map(items.map((i) => [i.code, i.naam])), [items]);
47
+ const label = (code) => (code ? labels.get(code) ?? code : "—");
48
+ return { items, error, label };
49
+ }
@@ -4,6 +4,7 @@ export declare function usePublishJob(jobId: string | null): {
4
4
  steps: PublishStepRow[];
5
5
  loading: boolean;
6
6
  reload: () => Promise<void>;
7
+ reloadFor: (id: string) => Promise<void>;
7
8
  };
8
9
  export declare function usePublishJobs(limit?: number): {
9
10
  jobs: PublishJobRow[];
@@ -1 +1 @@
1
- {"version":3,"file":"usePublishJob.d.ts","sourceRoot":"","sources":["../../src/hooks/usePublishJob.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,cAAc,EACpB,MAAM,yBAAyB,CAAC;AAEjC,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;;;;;EAqDjD;AAED,wBAAgB,cAAc,CAAC,KAAK,SAAK;;;;EAoBxC"}
1
+ {"version":3,"file":"usePublishJob.d.ts","sourceRoot":"","sources":["../../src/hooks/usePublishJob.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,cAAc,EACpB,MAAM,yBAAyB,CAAC;AAEjC,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;;;;;oBAuBP,MAAM;EAiDhD;AAED,wBAAgB,cAAc,CAAC,KAAK,SAAK;;;;EAoBxC"}
@@ -23,6 +23,25 @@ export function usePublishJob(jobId) {
23
23
  useEffect(() => {
24
24
  void reload();
25
25
  }, [reload]);
26
+ /** Laadt een opgegeven opdracht direct (na afronden in dezelfde klik). */
27
+ const reloadFor = useCallback(async (id) => {
28
+ const res = await loadPublishJob(id);
29
+ setJob(res.job);
30
+ setSteps(res.steps);
31
+ }, []);
32
+ // Vangnet als een seintje uitblijft: zolang de opdracht loopt en het
33
+ // tabblad zichtbaar is, elke 15 seconden de stand ophalen.
34
+ const running = job?.status === "running";
35
+ useEffect(() => {
36
+ if (!jobId || !running)
37
+ return;
38
+ const t = setInterval(() => {
39
+ if (typeof document !== "undefined" && document.visibilityState !== "visible")
40
+ return;
41
+ void reload();
42
+ }, 15000);
43
+ return () => clearInterval(t);
44
+ }, [jobId, running, reload]);
26
45
  useEffect(() => {
27
46
  if (!jobId)
28
47
  return;
@@ -45,7 +64,7 @@ export function usePublishJob(jobId) {
45
64
  void supabase.removeChannel(channel);
46
65
  };
47
66
  }, [jobId, reload]);
48
- return { job, steps, loading, reload };
67
+ return { job, steps, loading, reload, reloadFor };
49
68
  }
50
69
  export function usePublishJobs(limit = 50) {
51
70
  const [jobs, setJobs] = useState([]);
@@ -11,8 +11,10 @@ export interface StockSyncHealth {
11
11
  noPriceCount: number;
12
12
  /** Artikelen met regels die door het verpakkingsverschil zijn tegengehouden. */
13
13
  blocked: BlockedArticle[];
14
- /** Tegengehouden regels zonder bekend artikel. */
14
+ /** Tegengehouden artikelen zonder bekend lokaal artikel. */
15
15
  blockedWithoutProduct: number;
16
+ /** Bron van de telling: Floriday-auth of (oude bron) de wachtrij. */
17
+ blockedSource: "floriday-auth" | "wachtrij";
16
18
  }
17
19
  export interface BlockedArticle {
18
20
  productId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"useStockSyncHealth.d.ts","sourceRoot":"","sources":["../../src/hooks/useStockSyncHealth.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kEAAkE;IAClE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,4DAA4D;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,YAAY,EAAE,MAAM,CAAC;IACrB,gFAAgF;IAChF,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,kDAAkD;IAClD,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAS3E;AAED,wBAAgB,kBAAkB,2EAyGjC"}
1
+ {"version":3,"file":"useStockSyncHealth.d.ts","sourceRoot":"","sources":["../../src/hooks/useStockSyncHealth.ts"],"names":[],"mappings":"AAiBA,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kEAAkE;IAClE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,4DAA4D;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,YAAY,EAAE,MAAM,CAAC;IACrB,gFAAgF;IAChF,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,4DAA4D;IAC5D,qBAAqB,EAAE,MAAM,CAAC;IAC9B,qEAAqE;IACrE,aAAa,EAAE,eAAe,GAAG,UAAU,CAAC;CAC7C;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAS3E;AAED,wBAAgB,kBAAkB,2EAsJjC"}
@@ -1,5 +1,6 @@
1
1
  import { useQuery } from "@tanstack/react-query";
2
2
  import { supabase } from "../integrations/supabase/client.js";
3
+ import { isMissingFunctionError } from "../lib/buyer-organizations.js";
3
4
  const STALE_MINUTES = 10;
4
5
  const WINDOW_HOURS = 24;
5
6
  export function reasonLabel(error) {
@@ -81,26 +82,73 @@ export function useStockSyncHealth() {
81
82
  const withPrice = new Set((priced ?? []).map((p) => p.trade_item_id));
82
83
  noPriceCount = ids.filter((id) => !withPrice.has(id)).length;
83
84
  }
84
- // Regels tegengehouden door het verpakkingsverschil (alleen lezen).
85
- const { data: gateRows } = await supabase
86
- .from("floriday_continuous_stock_queue")
87
- .select("product_id, trade_item_id")
88
- .eq("status", "blocked_by_gate")
89
- .limit(500);
90
- const gateProductIds = Array.from(new Set((gateRows ?? []).map((r) => r.product_id).filter(Boolean)));
91
- const gateNoProduct = (gateRows ?? []).filter((r) => !r.product_id).length;
85
+ // Tegengehouden artikelen: bron = Floriday-auth `floriday_packing_blocked_items`
86
+ // (zelfde als de Floriday-koppelingspagina). Bestaat die nog niet: oude bron
87
+ // (wachtrijregels met status blocked_by_gate). Altijd artikelen tellen.
92
88
  let blocked = [];
93
- if (gateProductIds.length > 0) {
94
- const { data: prods } = await supabase
95
- .from("products")
96
- .select("id, product, article_number")
97
- .in("id", gateProductIds.slice(0, 200));
98
- const byId = new Map((prods ?? []).map((p) => [p.id, p]));
99
- blocked = gateProductIds.slice(0, 200).map((id) => ({
100
- productId: id,
101
- name: byId.get(id)?.product ?? null,
102
- code: byId.get(id)?.article_number ?? null,
103
- }));
89
+ let gateNoProduct = 0;
90
+ let blockedSource = "wachtrij";
91
+ const { data: ctx } = await supabase.rpc("get_stock_context", { p_ensure: false });
92
+ const ctxRow = Array.isArray(ctx) ? ctx[0] : ctx;
93
+ const connectionId = ctxRow?.connection_id ?? null;
94
+ let viaAuth = false;
95
+ if (connectionId) {
96
+ const { data: items, error: itemsErr } = await supabase.rpc("floriday_packing_blocked_items", {
97
+ p_connection_id: connectionId,
98
+ });
99
+ if (!itemsErr) {
100
+ viaAuth = true;
101
+ blockedSource = "floriday-auth";
102
+ // Kolommen Floriday-auth 1.0.126: trade_item_id, article_code, article_name,
103
+ // blocked_by, reason, ... Match uitsluitend op trade_item_id; alleen lezen.
104
+ const rows = (items ?? []).filter((r) => r?.trade_item_id);
105
+ const tradeIds = Array.from(new Set(rows.map((r) => String(r.trade_item_id))));
106
+ const prodByTrade = new Map();
107
+ if (tradeIds.length) {
108
+ const { data: prods } = await supabase
109
+ .from("products")
110
+ .select("id, floriday_trade_item_id")
111
+ .in("floriday_trade_item_id", tradeIds.slice(0, 500));
112
+ for (const p of (prods ?? []))
113
+ prodByTrade.set(String(p.floriday_trade_item_id), String(p.id));
114
+ }
115
+ const seen = new Set();
116
+ for (const r of rows) {
117
+ const tid = String(r.trade_item_id);
118
+ if (seen.has(tid))
119
+ continue;
120
+ seen.add(tid);
121
+ const pid = prodByTrade.get(tid);
122
+ if (pid)
123
+ blocked.push({ productId: pid, name: r.article_name ?? null, code: r.article_code ?? null });
124
+ else
125
+ gateNoProduct += 1;
126
+ }
127
+ }
128
+ else if (!isMissingFunctionError(itemsErr)) {
129
+ throw new Error(`Tegengehouden artikelen konden niet worden gelezen: ${itemsErr.message}`);
130
+ }
131
+ }
132
+ if (!viaAuth) {
133
+ const { data: gateRows } = await supabase
134
+ .from("floriday_continuous_stock_queue")
135
+ .select("product_id, trade_item_id")
136
+ .eq("status", "blocked_by_gate")
137
+ .limit(500);
138
+ const gateProductIds = Array.from(new Set((gateRows ?? []).map((r) => r.product_id).filter(Boolean)));
139
+ gateNoProduct = new Set((gateRows ?? []).filter((r) => !r.product_id).map((r) => r.trade_item_id)).size;
140
+ if (gateProductIds.length > 0) {
141
+ const { data: prods } = await supabase
142
+ .from("products")
143
+ .select("id, product, article_number")
144
+ .in("id", gateProductIds.slice(0, 200));
145
+ const byId = new Map((prods ?? []).map((p) => [p.id, p]));
146
+ blocked = gateProductIds.slice(0, 200).map((id) => ({
147
+ productId: id,
148
+ name: byId.get(id)?.product ?? null,
149
+ code: byId.get(id)?.article_number ?? null,
150
+ }));
151
+ }
104
152
  }
105
153
  return {
106
154
  failed,
@@ -112,6 +160,7 @@ export function useStockSyncHealth() {
112
160
  noPriceCount,
113
161
  blocked,
114
162
  blockedWithoutProduct: gateNoProduct,
163
+ blockedSource,
115
164
  };
116
165
  },
117
166
  });
@@ -6115,6 +6115,24 @@ export type Database = {
6115
6115
  };
6116
6116
  Relationships: [];
6117
6117
  };
6118
+ floricode_record_counts: {
6119
+ Row: {
6120
+ count: number;
6121
+ counted_at: string;
6122
+ resource: string;
6123
+ };
6124
+ Insert: {
6125
+ count?: number;
6126
+ counted_at?: string;
6127
+ resource: string;
6128
+ };
6129
+ Update: {
6130
+ count?: number;
6131
+ counted_at?: string;
6132
+ resource?: string;
6133
+ };
6134
+ Relationships: [];
6135
+ };
6118
6136
  floricode_records: {
6119
6137
  Row: {
6120
6138
  change_date_time: string | null;
@@ -10456,6 +10474,7 @@ export type Database = {
10456
10474
  created_at: string;
10457
10475
  enabled: boolean;
10458
10476
  id: string;
10477
+ invoice_without_signoff: boolean;
10459
10478
  offset_days: number;
10460
10479
  pickup_anchor: string;
10461
10480
  pickup_business_days_only: boolean;
@@ -10471,6 +10490,7 @@ export type Database = {
10471
10490
  created_at?: string;
10472
10491
  enabled?: boolean;
10473
10492
  id?: string;
10493
+ invoice_without_signoff?: boolean;
10474
10494
  offset_days?: number;
10475
10495
  pickup_anchor?: string;
10476
10496
  pickup_business_days_only?: boolean;
@@ -10486,6 +10506,7 @@ export type Database = {
10486
10506
  created_at?: string;
10487
10507
  enabled?: boolean;
10488
10508
  id?: string;
10509
+ invoice_without_signoff?: boolean;
10489
10510
  offset_days?: number;
10490
10511
  pickup_anchor?: string;
10491
10512
  pickup_business_days_only?: boolean;
@@ -18552,6 +18573,8 @@ export type Database = {
18552
18573
  floriday_sales_order_id: string | null;
18553
18574
  id: string;
18554
18575
  invoice_due_at: string | null;
18576
+ invoice_ready_at: string | null;
18577
+ invoice_ready_note: string | null;
18555
18578
  is_reservation: boolean;
18556
18579
  notes: string | null;
18557
18580
  order_date: string;
@@ -18586,6 +18609,8 @@ export type Database = {
18586
18609
  floriday_sales_order_id?: string | null;
18587
18610
  id?: string;
18588
18611
  invoice_due_at?: string | null;
18612
+ invoice_ready_at?: string | null;
18613
+ invoice_ready_note?: string | null;
18589
18614
  is_reservation?: boolean;
18590
18615
  notes?: string | null;
18591
18616
  order_date?: string;
@@ -18620,6 +18645,8 @@ export type Database = {
18620
18645
  floriday_sales_order_id?: string | null;
18621
18646
  id?: string;
18622
18647
  invoice_due_at?: string | null;
18648
+ invoice_ready_at?: string | null;
18649
+ invoice_ready_note?: string | null;
18623
18650
  is_reservation?: boolean;
18624
18651
  notes?: string | null;
18625
18652
  order_date?: string;
@@ -19876,25 +19903,31 @@ export type Database = {
19876
19903
  Row: {
19877
19904
  id: boolean;
19878
19905
  last_cleanup_at: string | null;
19906
+ last_duration_ms: number | null;
19879
19907
  last_error: string | null;
19880
19908
  last_error_at: string | null;
19881
19909
  last_sync_at: string | null;
19910
+ sync_requested_at: string | null;
19882
19911
  updated_at: string;
19883
19912
  };
19884
19913
  Insert: {
19885
19914
  id?: boolean;
19886
19915
  last_cleanup_at?: string | null;
19916
+ last_duration_ms?: number | null;
19887
19917
  last_error?: string | null;
19888
19918
  last_error_at?: string | null;
19889
19919
  last_sync_at?: string | null;
19920
+ sync_requested_at?: string | null;
19890
19921
  updated_at?: string;
19891
19922
  };
19892
19923
  Update: {
19893
19924
  id?: boolean;
19894
19925
  last_cleanup_at?: string | null;
19926
+ last_duration_ms?: number | null;
19895
19927
  last_error?: string | null;
19896
19928
  last_error_at?: string | null;
19897
19929
  last_sync_at?: string | null;
19930
+ sync_requested_at?: string | null;
19898
19931
  updated_at?: string;
19899
19932
  };
19900
19933
  Relationships: [];
@@ -26330,6 +26363,8 @@ export type Database = {
26330
26363
  default_payment_term_days: number;
26331
26364
  default_vat_code: string;
26332
26365
  email_purpose: string | null;
26366
+ email_test_address: string | null;
26367
+ email_test_mode: boolean;
26333
26368
  home_country_code: string;
26334
26369
  invoice_enabled_ao: boolean;
26335
26370
  invoice_enabled_fo: boolean;
@@ -26361,6 +26396,8 @@ export type Database = {
26361
26396
  default_payment_term_days?: number;
26362
26397
  default_vat_code?: string;
26363
26398
  email_purpose?: string | null;
26399
+ email_test_address?: string | null;
26400
+ email_test_mode?: boolean;
26364
26401
  home_country_code?: string;
26365
26402
  invoice_enabled_ao?: boolean;
26366
26403
  invoice_enabled_fo?: boolean;
@@ -26392,6 +26429,8 @@ export type Database = {
26392
26429
  default_payment_term_days?: number;
26393
26430
  default_vat_code?: string;
26394
26431
  email_purpose?: string | null;
26432
+ email_test_address?: string | null;
26433
+ email_test_mode?: boolean;
26395
26434
  home_country_code?: string;
26396
26435
  invoice_enabled_ao?: boolean;
26397
26436
  invoice_enabled_fo?: boolean;
@@ -28347,6 +28386,30 @@ export type Database = {
28347
28386
  };
28348
28387
  Relationships: [];
28349
28388
  };
28389
+ voorraad_load_carrier_types: {
28390
+ Row: {
28391
+ code: string;
28392
+ created_at: string;
28393
+ naam: string;
28394
+ updated_at: string;
28395
+ volgorde: number;
28396
+ };
28397
+ Insert: {
28398
+ code: string;
28399
+ created_at?: string;
28400
+ naam: string;
28401
+ updated_at?: string;
28402
+ volgorde: number;
28403
+ };
28404
+ Update: {
28405
+ code?: string;
28406
+ created_at?: string;
28407
+ naam?: string;
28408
+ updated_at?: string;
28409
+ volgorde?: number;
28410
+ };
28411
+ Relationships: [];
28412
+ };
28350
28413
  voorraad_local_context: {
28351
28414
  Row: {
28352
28415
  created_at: string;
@@ -29768,6 +29831,7 @@ export type Database = {
29768
29831
  sequence_number: number;
29769
29832
  signature_accepted_at: string | null;
29770
29833
  signature_by_user_id: string | null;
29834
+ signature_image_path: string | null;
29771
29835
  signature_name: string | null;
29772
29836
  source_email_meta: Json | null;
29773
29837
  source_mailbox_message_id: string | null;
@@ -29816,6 +29880,7 @@ export type Database = {
29816
29880
  sequence_number: number;
29817
29881
  signature_accepted_at?: string | null;
29818
29882
  signature_by_user_id?: string | null;
29883
+ signature_image_path?: string | null;
29819
29884
  signature_name?: string | null;
29820
29885
  source_email_meta?: Json | null;
29821
29886
  source_mailbox_message_id?: string | null;
@@ -29864,6 +29929,7 @@ export type Database = {
29864
29929
  sequence_number?: number;
29865
29930
  signature_accepted_at?: string | null;
29866
29931
  signature_by_user_id?: string | null;
29932
+ signature_image_path?: string | null;
29867
29933
  signature_name?: string | null;
29868
29934
  source_email_meta?: Json | null;
29869
29935
  source_mailbox_message_id?: string | null;
@@ -32814,6 +32880,20 @@ export type Database = {
32814
32880
  niveau: string;
32815
32881
  }[];
32816
32882
  };
32883
+ floriday_buyer_organizations: {
32884
+ Args: {
32885
+ p_connection_id: string;
32886
+ };
32887
+ Returns: {
32888
+ gln: string;
32889
+ in_connections: boolean;
32890
+ in_trade_settings: boolean;
32891
+ organization_id: string;
32892
+ organization_name: string;
32893
+ price_group_ids: string[];
32894
+ sources: string[];
32895
+ }[];
32896
+ };
32817
32897
  floriday_caller_is_server: {
32818
32898
  Args: never;
32819
32899
  Returns: boolean;
@@ -32993,6 +33073,23 @@ export type Database = {
32993
33073
  Args: never;
32994
33074
  Returns: number;
32995
33075
  };
33076
+ floriday_packing_blocked_items: {
33077
+ Args: {
33078
+ p_connection_id: string;
33079
+ };
33080
+ Returns: {
33081
+ article_code: string;
33082
+ article_name: string;
33083
+ blocked_attempts: number;
33084
+ blocked_by: string;
33085
+ details: string;
33086
+ last_blocked_at: string;
33087
+ mismatch_id: string;
33088
+ reason: string;
33089
+ since: string;
33090
+ trade_item_id: string;
33091
+ }[];
33092
+ };
32996
33093
  floriday_publish_horizon_weeks: {
32997
33094
  Args: never;
32998
33095
  Returns: number;
@@ -36060,6 +36157,14 @@ export type Database = {
36060
36157
  uitleg: string;
36061
36158
  }[];
36062
36159
  };
36160
+ logistics_install_check_207: {
36161
+ Args: never;
36162
+ Returns: {
36163
+ ok: boolean;
36164
+ punt: string;
36165
+ uitleg: string;
36166
+ }[];
36167
+ };
36063
36168
  logistics_is_beheer: {
36064
36169
  Args: never;
36065
36170
  Returns: boolean;
@@ -39626,6 +39731,20 @@ export type Database = {
39626
39731
  };
39627
39732
  Returns: Json;
39628
39733
  };
39734
+ pick_read_shared_cart_messages: {
39735
+ Args: {
39736
+ _cart_ids: string[];
39737
+ _queue_item_id: string;
39738
+ };
39739
+ Returns: Json;
39740
+ } | {
39741
+ Args: {
39742
+ _cart_ids: string[];
39743
+ _queue_item_id: string;
39744
+ p_device_key: string;
39745
+ };
39746
+ Returns: Json;
39747
+ };
39629
39748
  pick_read_station: {
39630
39749
  Args: {
39631
39750
  p_device_key: string;
@@ -40303,6 +40422,13 @@ export type Database = {
40303
40422
  };
40304
40423
  Returns: string;
40305
40424
  };
40425
+ pick_shared_cart_message: {
40426
+ Args: {
40427
+ _cart_id: string;
40428
+ _item: Database["public"]["Tables"]["pick_queue"]["Row"];
40429
+ };
40430
+ Returns: string;
40431
+ };
40306
40432
  pick_signal_station: {
40307
40433
  Args: {
40308
40434
  p_station: string;
@@ -41373,6 +41499,12 @@ export type Database = {
41373
41499
  };
41374
41500
  Returns: number;
41375
41501
  };
41502
+ refresh_floricode_record_counts: {
41503
+ Args: {
41504
+ p_resource?: string;
41505
+ };
41506
+ Returns: number;
41507
+ };
41376
41508
  refresh_floriday_delivery_locations: {
41377
41509
  Args: never;
41378
41510
  Returns: number;
@@ -43653,6 +43785,39 @@ export type Database = {
43653
43785
  };
43654
43786
  Returns: Json;
43655
43787
  };
43788
+ voorraad_correctie_1121: {
43789
+ Args: {
43790
+ p_uitvoeren?: boolean;
43791
+ };
43792
+ Returns: Json;
43793
+ };
43794
+ voorraad_correctie_1121_regels: {
43795
+ Args: never;
43796
+ Returns: {
43797
+ aantal_boekingen: number;
43798
+ fust_naam: string;
43799
+ fust_type_id: string;
43800
+ juist: number;
43801
+ netto_geboekt: number;
43802
+ order_item_id: string;
43803
+ order_number: string;
43804
+ reden: string;
43805
+ regel_bestaat: boolean;
43806
+ verschil: number;
43807
+ }[];
43808
+ };
43809
+ voorraad_correctie_1123: {
43810
+ Args: {
43811
+ p_uitvoeren?: boolean;
43812
+ };
43813
+ Returns: Json;
43814
+ };
43815
+ voorraad_correctie_1124: {
43816
+ Args: {
43817
+ p_uitvoeren?: boolean;
43818
+ };
43819
+ Returns: Json;
43820
+ };
43656
43821
  voorraad_correctie_status: {
43657
43822
  Args: {
43658
43823
  p_correctie?: string;
@@ -43685,6 +43850,17 @@ export type Database = {
43685
43850
  width_mm: number;
43686
43851
  }[];
43687
43852
  };
43853
+ voorraad_fust_juist: {
43854
+ Args: {
43855
+ p_order_item_id: string;
43856
+ };
43857
+ Returns: {
43858
+ aantal: number;
43859
+ bron: string;
43860
+ fust_key: string;
43861
+ fust_type_id: string;
43862
+ }[];
43863
+ };
43688
43864
  voorraad_hook_base_url: {
43689
43865
  Args: never;
43690
43866
  Returns: string;
@@ -43710,12 +43886,28 @@ export type Database = {
43710
43886
  Args: never;
43711
43887
  Returns: boolean;
43712
43888
  };
43889
+ voorraad_load_carriers: {
43890
+ Args: never;
43891
+ Returns: {
43892
+ code: string;
43893
+ naam: string;
43894
+ volgorde: number;
43895
+ }[];
43896
+ };
43713
43897
  voorraad_mark_floriday_sold_before_switch: {
43714
43898
  Args: {
43715
43899
  p_product_id: string;
43716
43900
  };
43717
43901
  Returns: number;
43718
43902
  };
43903
+ voorraad_order_geannuleerd: {
43904
+ Args: {
43905
+ p_cancelled_at: string;
43906
+ p_deleted_at: string;
43907
+ p_status: string;
43908
+ };
43909
+ Returns: boolean;
43910
+ };
43719
43911
  voorraad_production_enabled: {
43720
43912
  Args: never;
43721
43913
  Returns: boolean;