@flowselections/mailbox-orders 1.0.33 → 1.0.36

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.
@@ -1 +1 @@
1
- {"version":3,"file":"MailboxProposalsPage.d.ts","sourceRoot":"","sources":["../../src/components/MailboxProposalsPage.tsx"],"names":[],"mappings":"AA6GA,6EAA6E;AAC7E,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AA2CD,wBAAgB,oBAAoB,gCAubnC"}
1
+ {"version":3,"file":"MailboxProposalsPage.d.ts","sourceRoot":"","sources":["../../src/components/MailboxProposalsPage.tsx"],"names":[],"mappings":"AAgHA,6EAA6E;AAC7E,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AA2CD,wBAAgB,oBAAoB,gCAmcnC"}
@@ -4,7 +4,7 @@ import { useQuery, useQueryClient, useMutation } from "@tanstack/react-query";
4
4
  import { useServerFn } from "@tanstack/react-start";
5
5
  import { Button, Badge, Card, CardContent, CardHeader, CardTitle, Input, Label, Textarea, Switch, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Dialog, DialogContent, DialogHeader, DialogTitle, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, toast, } from "@flowselections/core";
6
6
  import { Check, X, Trash2, Plus, AlertTriangle, RefreshCw } from "lucide-react";
7
- import { listProposals, getProposalDetail, approveProposal, rejectProposal, listCustomersForPicker, createCustomerFromGroup, listProductsForPicker, listDeliveryLocationsForCustomer, listPickupLocations, listCarriersForPicker, getActiveOrdersMailbox, syncMailboxNow, refreshProposalsForAgentChange, reparseProposalNow, listBeladingOptionsForProducts, listAllowedLoadCarriers, getDeparturePreview, getAgreementPrices, countOutdatedProposals, } from "../lib/mailbox.functions.js";
7
+ import { listProposals, getProposalDetail, approveProposal, rejectProposal, getStickerDefaults, listCustomersForPicker, createCustomerFromGroup, listProductsForPicker, listDeliveryLocationsForCustomer, listPickupLocations, listCarriersForPicker, getActiveOrdersMailbox, syncMailboxNow, refreshProposalsForAgentChange, reparseProposalNow, listBeladingOptionsForProducts, listAllowedLoadCarriers, getDeparturePreview, getAgreementPrices, countOutdatedProposals, } from "../lib/mailbox.functions.js";
8
8
  import { normalizeUnitKind, toPlants, describeConversion, lineTotal, UNIT_KIND_LABEL, } from "../lib/mailbox-units.js";
9
9
  import { enabledLoadCarriers, normalizeAllowedLoadCarriers, EMPTY_LOAD_CARRIERS } from "../lib/load-carriers.js";
10
10
  import { listTemplateFields, listPlantTypesForPicker, listSuppliersForPicker, } from "../lib/mailbox-template.functions.js";
@@ -14,6 +14,7 @@ import { EmailPreview } from "./EmailPreview.js";
14
14
  import { TablePagination } from "./TablePagination.js";
15
15
  import { MailboxFilterBar, usePersistedState, normalizeText, matchesPeriod } from "./MailboxFilterBar.js";
16
16
  import { supabase } from "../integrations/supabase/client.js";
17
+ import { canOverrideLateSignup } from "../lib/verkoop-order.js";
17
18
  const beladingKey = (b) => `${b.plants_per_crate}x${b.crates_per_layer}x${b.layers_per_cart}|${b.crate_code ?? ""}|${b.carrier_code ?? ""}`;
18
19
  const beladingLabel = (b) => `${b.plants_per_crate} planten/fust · ${b.crates_per_layer} fusten/laag · ${b.layers_per_cart} lagen`;
19
20
  // Extra regel onder het label: fusten/kar + fusttype + kartype
@@ -316,6 +317,16 @@ export function MailboxProposalsPage() {
316
317
  } }, children: _jsx(DialogContent, { className: "max-w-[95vw] w-[95vw] h-[92vh] max-h-[92vh] p-0 flex flex-col overflow-hidden", children: !active ? (_jsxs("div", { className: "flex-1 flex flex-col items-center justify-center gap-2 text-sm text-muted-foreground", children: [_jsx(DialogTitle, { className: "text-base", children: "Bestelling" }), detailLoading ? "Bestelling laden…" : "Bestelling niet gevonden."] })) : (_jsxs(_Fragment, { children: [_jsxs(DialogHeader, { className: "px-6 pt-6 pb-3 shrink-0 border-b", children: [_jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsx(DialogTitle, { children: customerNameFor(activeSummary ?? active) }), _jsxs(Button, { type: "button", variant: "outline", size: "sm", className: "mr-8", disabled: reparseMutation.isPending, onClick: () => reparseMutation.mutate(active.id), children: [_jsx(RefreshCw, { className: `h-4 w-4 mr-2 ${reparseMutation.isPending ? "animate-spin" : ""}` }), reparseMutation.isPending ? "Analyseren…" : "Mail opnieuw analyseren"] })] }), reparseError && (_jsxs("div", { className: "mt-2 flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-sm text-destructive", children: [_jsx(AlertTriangle, { className: "h-4 w-4 mt-0.5 shrink-0" }), _jsx("span", { children: reparseError })] }))] }), _jsx("div", { className: "flex-1 min-h-0 overflow-hidden p-6", children: _jsx(ProposalEditor, { proposal: active, template: template, customers: customers, products: products, allowBackorder: allowBackorder, plantTypes: plantTypes, suppliers: suppliers, carriers: carriers, pickupLocations: pickupLocations, onApprove: async (payload) => {
317
318
  try {
318
319
  const res = await fetchApprove({ data: payload });
320
+ if (res?.ok === false) {
321
+ toast.error(res.message ?? "Verkoop heeft de bestelling geweigerd.");
322
+ return res;
323
+ }
324
+ if (res?.alreadyApproved) {
325
+ toast.info(`Er bestaat al een order voor dit voorstel (${res.orderNumber}).`);
326
+ qc.invalidateQueries({ queryKey: ["mailbox-proposals"] });
327
+ setActiveId(null);
328
+ return res;
329
+ }
319
330
  const shortages = Array.isArray(res?.shortages) ? res.shortages : [];
320
331
  toast.success("Bestelling aangemaakt — karindeling wordt automatisch aangemaakt in de Verkoop-module");
321
332
  if (shortages.length > 0) {
@@ -325,9 +336,11 @@ export function MailboxProposalsPage() {
325
336
  }
326
337
  qc.invalidateQueries({ queryKey: ["mailbox-proposals"] });
327
338
  setActiveId(null);
339
+ return res;
328
340
  }
329
341
  catch (e) {
330
342
  toast.error(e?.message ?? "Goedkeuren mislukt");
343
+ return { ok: false, reason: "other", message: e?.message ?? "Goedkeuren mislukt" };
331
344
  }
332
345
  }, onReject: async (reason) => {
333
346
  try {
@@ -598,7 +611,50 @@ function ProposalEditor({ proposal, template, customers, products, allowBackorde
598
611
  },
599
612
  });
600
613
  const agreements = agreementData?.prices ?? {};
601
- const [acceptNoPrice, setAcceptNoPrice] = useState(false);
614
+ // ─── Stickervinkje per regel ─────────────────────────────────────────────
615
+ const fetchStickers = useServerFn(getStickerDefaults);
616
+ const stickerProductIds = Array.from(new Set(lines.map((l) => l.product_id).filter(Boolean))).sort();
617
+ const { data: stickerData } = useQuery({
618
+ queryKey: ["mailbox-sticker-defaults", customerVal, stickerProductIds.join(",")],
619
+ queryFn: async () => {
620
+ try {
621
+ return await fetchStickers({ data: { customerId: isLocalCustomerId(customerVal) ? customerVal : null, productIds: stickerProductIds } });
622
+ }
623
+ catch {
624
+ return { available: false, defaults: {} };
625
+ }
626
+ },
627
+ });
628
+ const stickerAvailable = stickerData?.available === true;
629
+ const stickerDefaults = stickerData?.defaults ?? {};
630
+ useEffect(() => {
631
+ if (!stickerAvailable)
632
+ return;
633
+ let changed = false;
634
+ const next = lines.map((l) => {
635
+ if (l.product_id && (l.needs_sticker === null || l.needs_sticker === undefined) && l.product_id in stickerDefaults) {
636
+ changed = true;
637
+ return { ...l, needs_sticker: stickerDefaults[l.product_id] === true };
638
+ }
639
+ return l;
640
+ });
641
+ if (changed)
642
+ setLines(next);
643
+ // eslint-disable-next-line react-hooks/exhaustive-deps
644
+ }, [stickerData, lines]);
645
+ const stickerCustomerRef = useRef(customerVal);
646
+ useEffect(() => {
647
+ if (stickerCustomerRef.current === customerVal)
648
+ return;
649
+ stickerCustomerRef.current = customerVal;
650
+ setLines((prev) => prev.map((l) => ({ ...l, needs_sticker: undefined })));
651
+ }, [customerVal]);
652
+ const [lateReason, setLateReason] = useState("");
653
+ const [lateOpen, setLateOpen] = useState(false);
654
+ const [refusal, setRefusal] = useState(null);
655
+ const previewKind = preview?.chosen?.departed === true ? "departed" : "late_signup";
656
+ const lateOverride = lateOpen && canOverrideLateSignup(refusal?.kind ?? previewKind, lateReason);
657
+ useEffect(() => { setRefusal(null); setLateOpen(false); setLateReason(""); }, [deliveryVal, carrierVal, deliveryLocationVal]);
602
658
  const orderTotal = lines.reduce((sum, l) => sum + lineTotal(l.quantity ?? null, l.unit_price ?? null), 0);
603
659
  const linesWithoutPrice = lines.filter((l) => l.product_id && (l.unit_price === null || l.unit_price === undefined)).length;
604
660
  const euro = (n) => n.toLocaleString("nl-NL", { style: "currency", currency: "EUR" });
@@ -637,7 +693,7 @@ function ProposalEditor({ proposal, template, customers, products, allowBackorde
637
693
  toast.error("Kies een vervoerder.");
638
694
  return null;
639
695
  }
640
- if (!dateFeasible) {
696
+ if (!dateFeasible && !lateOverride) {
641
697
  toast.error(preview?.reason ? `Leverdatum niet haalbaar: ${preview.reason}` : "De leverdatum is nog niet gecontroleerd of niet haalbaar.");
642
698
  return null;
643
699
  }
@@ -651,6 +707,10 @@ function ProposalEditor({ proposal, template, customers, products, allowBackorde
651
707
  return null;
652
708
  }
653
709
  }
710
+ if (validLines.some((l) => l.unit_price === null || l.unit_price === undefined || l.unit_price <= 0)) {
711
+ toast.error("Vul bij elke regel een prijs per stuk in; Verkoop maakt geen order zonder prijs.");
712
+ return null;
713
+ }
654
714
  const cust = customers.find((c) => c.id === customerVal);
655
715
  return {
656
716
  proposalId: proposal.id,
@@ -668,13 +728,14 @@ function ProposalEditor({ proposal, template, customers, products, allowBackorde
668
728
  quantity: l.quantity,
669
729
  unit: "planten",
670
730
  unit_price: l.unit_price ?? null,
731
+ needs_sticker: stickerAvailable ? l.needs_sticker === true : undefined,
671
732
  belading: b ? { plants_per_crate: b.plants_per_crate, crates_per_layer: b.crates_per_layer, layers_per_cart: b.layers_per_cart } : null,
672
733
  };
673
734
  }),
674
735
  fieldValues: Object.entries(values).map(([field_key, value]) => ({ field_key, value })),
675
736
  customerReference: typeof values["reference"] === "string" ? values["reference"].trim() || null : null,
676
737
  momentKey: preview?.chosen?.momentKey ?? null,
677
- acceptMissingPrice: acceptNoPrice,
738
+ lateSignup: lateOverride ? { reason: lateReason.trim() } : null,
678
739
  };
679
740
  };
680
741
  // Stap 1: controleren → bevestigingsdialoog. Pas na bevestigen wordt de
@@ -690,8 +751,16 @@ function ProposalEditor({ proposal, template, customers, products, allowBackorde
690
751
  return;
691
752
  setSubmitting(true);
692
753
  try {
693
- await onApprove(payload);
754
+ const res = await onApprove(payload);
694
755
  setConfirmOpen(false);
756
+ setCheckedOk(false);
757
+ if (res?.ok === false) {
758
+ setRefusal({
759
+ kind: res.reason ?? "other",
760
+ message: String(res.message ?? "Verkoop heeft de bestelling geweigerd."),
761
+ nextDeliveryDate: res.nextDeliveryDate ?? null,
762
+ });
763
+ }
695
764
  }
696
765
  finally {
697
766
  setSubmitting(false);
@@ -748,8 +817,8 @@ function ProposalEditor({ proposal, template, customers, products, allowBackorde
748
817
  : "Kies vervoerder...", clearLabel: "\u2014 Geen \u2014", disabled: !deliveryLocationVal, options: carriers.map((c) => ({
749
818
  value: c.id,
750
819
  label: c.name + (c.is_default ? " (standaard)" : ""),
751
- })), onChange: (v) => setVal("carrier", v) }), selectedLocation?.carrier_id && carrierVal !== selectedLocation.carrier_id && (_jsx("div", { className: "text-xs text-muted-foreground", children: "Wijkt af van standaard vervoerder van deze locatie \u2014 geldt alleen voor deze bestelling." }))] }), _jsxs("div", { className: "space-y-1", children: [_jsxs(Label, { className: "flex items-center gap-2", children: ["Bezorgdatum ", _jsx("span", { className: "text-destructive", children: "*" })] }), _jsx(Input, { type: "date", value: deliveryVal ?? "", onChange: (e) => setVal("delivery_date", e.target.value || null) }), _jsx(ConfBadge, { meta: metaFor("delivery_date"), thresholds: thresholds }), !carrierVal || !deliveryLocationVal ? (_jsx("div", { className: "text-xs text-muted-foreground", children: "Kies een afleverlocatie en vervoerder; daarna controleren we of deze datum haalbaar is." })) : !deliveryVal ? (_jsx("div", { className: "text-xs text-muted-foreground", children: "De mail noemt geen datum. Kies zelf een datum." })) : previewLoading ? (_jsx("div", { className: "text-xs text-muted-foreground", children: "Haalbaarheid controleren\u2026" })) : previewError ? (_jsxs("div", { className: "text-xs text-destructive", children: ["De haalbaarheid kon niet worden gecontroleerd: ", previewError] })) : dateFeasible ? (_jsxs("div", { className: "rounded-md border border-emerald-200 bg-emerald-50 px-3 py-2 text-xs text-emerald-800", children: [fmtDate(deliveryVal), " is haalbaar.", preview?.chosen?.departureAt ? ` Ophaalmoment: ${fmtDateTime(preview.chosen.departureAt)}` : "", preview?.chosen?.signupDeadline ? ` (aanmelden tot ${fmtDateTime(preview.chosen.signupDeadline)}).` : "."] })) : (_jsxs("div", { className: "rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-xs space-y-2", children: [_jsxs("div", { className: "text-destructive", children: [fmtDate(deliveryVal), " is niet haalbaar", preview?.reason ? `: ${preview.reason}` : "."] }), preview?.firstFeasibleDeliveryDate && preview.firstFeasibleDeliveryDate !== deliveryVal && (_jsxs(Button, { size: "sm", variant: "outline", onClick: () => setVal("delivery_date", preview.firstFeasibleDeliveryDate), children: ["Gebruik ", fmtDate(preview.firstFeasibleDeliveryDate)] }))] }))] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Referentie klant" }), _jsx(Input, { value: typeof values["reference"] === "string" ? values["reference"] : "", placeholder: "Bijv. ordernummer van de klant", onChange: (e) => setVal("reference", e.target.value) }), _jsx(ConfBadge, { meta: metaFor("reference"), thresholds: thresholds })] }), otherFields.map(renderField)] }));
752
- })(), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: "Bestelregels" }), _jsxs("div", { className: "grid grid-cols-12 gap-2 text-xs text-muted-foreground px-1", children: [_jsx("div", { className: "col-span-4", children: "Product" }), _jsx("div", { className: "col-span-3", children: "Belading" }), _jsx("div", { className: "col-span-2", children: "Fusten" }), _jsx("div", { className: "col-span-2", children: "Prijs per stuk" }), _jsx("div", { className: "col-span-1" })] }), lines.map((line, idx) => {
820
+ })), onChange: (v) => setVal("carrier", v) }), selectedLocation?.carrier_id && carrierVal !== selectedLocation.carrier_id && (_jsx("div", { className: "text-xs text-muted-foreground", children: "Wijkt af van standaard vervoerder van deze locatie \u2014 geldt alleen voor deze bestelling." }))] }), _jsxs("div", { className: "space-y-1", children: [_jsxs(Label, { className: "flex items-center gap-2", children: ["Bezorgdatum ", _jsx("span", { className: "text-destructive", children: "*" })] }), _jsx(Input, { type: "date", value: deliveryVal ?? "", onChange: (e) => setVal("delivery_date", e.target.value || null) }), _jsx(ConfBadge, { meta: metaFor("delivery_date"), thresholds: thresholds }), !carrierVal || !deliveryLocationVal ? (_jsx("div", { className: "text-xs text-muted-foreground", children: "Kies een afleverlocatie en vervoerder; daarna controleren we of deze datum haalbaar is." })) : !deliveryVal ? (_jsx("div", { className: "text-xs text-muted-foreground", children: "De mail noemt geen datum. Kies zelf een datum." })) : previewLoading ? (_jsx("div", { className: "text-xs text-muted-foreground", children: "Haalbaarheid controleren\u2026" })) : previewError ? (_jsxs("div", { className: "text-xs text-destructive", children: ["De haalbaarheid kon niet worden gecontroleerd: ", previewError] })) : dateFeasible ? (_jsxs("div", { className: "rounded-md border border-emerald-200 bg-emerald-50 px-3 py-2 text-xs text-emerald-800", children: [fmtDate(deliveryVal), " is haalbaar.", preview?.chosen?.departureAt ? ` Ophaalmoment: ${fmtDateTime(preview.chosen.departureAt)}` : "", preview?.chosen?.signupDeadline ? ` (aanmelden tot ${fmtDateTime(preview.chosen.signupDeadline)}).` : "."] })) : (_jsxs("div", { className: "rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-xs space-y-2", children: [_jsxs("div", { className: "text-destructive", children: [fmtDate(deliveryVal), " is niet haalbaar", preview?.reason ? `: ${preview.reason}` : "."] }), preview?.firstFeasibleDeliveryDate && preview.firstFeasibleDeliveryDate !== deliveryVal && (_jsxs(Button, { size: "sm", variant: "outline", onClick: () => setVal("delivery_date", preview.firstFeasibleDeliveryDate), children: ["Gebruik ", fmtDate(preview.firstFeasibleDeliveryDate)] })), preview?.ok === true && previewKind === "late_signup" && (_jsx(LateSignupChoice, { open: lateOpen, setOpen: setLateOpen, reason: lateReason, setReason: setLateReason }))] }))] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Referentie klant" }), _jsx(Input, { value: typeof values["reference"] === "string" ? values["reference"] : "", placeholder: "Bijv. ordernummer van de klant", onChange: (e) => setVal("reference", e.target.value) }), _jsx(ConfBadge, { meta: metaFor("reference"), thresholds: thresholds })] }), otherFields.map(renderField)] }));
821
+ })(), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: "Bestelregels" }), _jsxs("div", { className: "grid grid-cols-12 gap-2 text-xs text-muted-foreground px-1", children: [_jsx("div", { className: "col-span-4", children: "Product" }), _jsx("div", { className: "col-span-3", children: "Belading" }), _jsx("div", { className: "col-span-2", children: "Fusten" }), _jsx("div", { className: "col-span-2", children: "Prijs per stuk" }), _jsx("div", { className: "col-span-1 text-center", children: stickerAvailable ? "Sticker" : "" })] }), lines.map((line, idx) => {
753
822
  const product = line.product_id ? products.find((p) => p.id === line.product_id) : null;
754
823
  const stdBelading = defaultBelading(product);
755
824
  const available = (line.product_id ? (Array.isArray(beladingByProduct[line.product_id]) ? beladingByProduct[line.product_id] : []) : []).map((b) => ({
@@ -867,14 +936,18 @@ function ProposalEditor({ proposal, template, customers, products, allowBackorde
867
936
  next[idx] = { ...next[idx], unit_price: ag.net_price, price_source: "afspraak" };
868
937
  setLines(next);
869
938
  }, children: "gebruiken" })] }))] }));
870
- })()] }), _jsx(Button, { variant: "ghost", size: "icon", className: "col-span-1", onClick: () => setLines(lines.filter((_, i) => i !== idx)), children: _jsx(Trash2, { className: "h-4 w-4" }) })] }, idx));
871
- }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setLines([...lines, { product_id: null, raw_product_text: "", quantity: 1, unit: "stuks", belading: null }]), children: [_jsx(Plus, { className: "h-3 w-3 mr-1" }), " Regel toevoegen"] }), _jsxs("div", { className: "flex justify-between border-t pt-2 text-sm", children: [_jsx("span", { className: "text-muted-foreground", children: "Totaal" }), _jsx("span", { className: "font-medium", children: euro(orderTotal) })] }), linesWithoutPrice > 0 && (_jsxs("div", { className: "rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-800", children: ["Geen prijs bekend voor ", linesWithoutPrice, " regel(s). Vul een prijs in of bevestig straks dat je zonder prijs doorgaat."] }))] }), _jsxs("div", { className: "flex gap-2 pt-2", children: [_jsxs(Button, { className: "flex-1", onClick: handleApprove, children: [_jsx(Check, { className: "h-4 w-4 mr-1" }), " Controleren & bevestigen"] }), _jsxs(Button, { variant: "destructive", onClick: () => onReject(notesVal || ""), children: [_jsx(X, { className: "h-4 w-4 mr-1" }), " Afwijzen"] })] }), _jsx(Dialog, { open: confirmOpen, onOpenChange: (o) => {
939
+ })()] }), _jsxs("div", { className: "col-span-1 flex flex-col items-center gap-1", children: [stickerAvailable && (_jsxs("label", { className: "flex flex-col items-center text-[11px] text-muted-foreground cursor-pointer", title: "Sticker nodig op deze orderregel", children: [_jsx("input", { type: "checkbox", "aria-label": "Sticker", checked: line.needs_sticker === true, onChange: (e) => {
940
+ const next = [...lines];
941
+ next[idx] = { ...next[idx], needs_sticker: e.target.checked };
942
+ setLines(next);
943
+ } }), "Sticker"] })), _jsx(Button, { variant: "ghost", size: "icon", onClick: () => setLines(lines.filter((_, i) => i !== idx)), children: _jsx(Trash2, { className: "h-4 w-4" }) })] })] }, idx));
944
+ }), _jsxs(Button, { variant: "outline", size: "sm", onClick: () => setLines([...lines, { product_id: null, raw_product_text: "", quantity: 1, unit: "stuks", belading: null }]), children: [_jsx(Plus, { className: "h-3 w-3 mr-1" }), " Regel toevoegen"] }), _jsxs("div", { className: "flex justify-between border-t pt-2 text-sm", children: [_jsx("span", { className: "text-muted-foreground", children: "Totaal" }), _jsx("span", { className: "font-medium", children: euro(orderTotal) })] }), linesWithoutPrice > 0 && (_jsxs("div", { className: "rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-800", children: ["Geen prijs bekend voor ", linesWithoutPrice, " regel(s). Vul een prijs in; zonder prijs kan de bestelling niet worden aangemaakt."] }))] }), refusal && (_jsxs("div", { className: "rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-sm space-y-2", children: [_jsx("div", { className: "font-medium text-destructive", children: "Bestelling niet aangemaakt \u2014 het voorstel blijft open." }), _jsx("div", { className: "text-destructive", children: refusal.message }), _jsx("div", { className: "flex flex-wrap gap-2", children: refusal.nextDeliveryDate && refusal.nextDeliveryDate !== deliveryVal && (_jsxs(Button, { size: "sm", variant: "outline", onClick: () => setVal("delivery_date", refusal.nextDeliveryDate), children: ["Volgend haalbaar moment: ", fmtDate(refusal.nextDeliveryDate)] })) }), refusal.kind === "late_signup" && (_jsx(LateSignupChoice, { open: lateOpen, setOpen: setLateOpen, reason: lateReason, setReason: setLateReason }))] })), _jsxs("div", { className: "flex gap-2 pt-2", children: [_jsxs(Button, { className: "flex-1", onClick: handleApprove, children: [_jsx(Check, { className: "h-4 w-4 mr-1" }), " Controleren & bevestigen"] }), _jsxs(Button, { variant: "destructive", onClick: () => onReject(notesVal || ""), children: [_jsx(X, { className: "h-4 w-4 mr-1" }), " Afwijzen"] })] }), _jsx(Dialog, { open: confirmOpen, onOpenChange: (o) => {
872
945
  if (submitting)
873
946
  return;
874
947
  setConfirmOpen(o);
875
948
  if (!o)
876
949
  setCheckedOk(false);
877
- }, children: _jsxs(DialogContent, { className: "max-w-lg", children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: "Bestelling bevestigen" }) }), _jsxs("div", { className: "space-y-3 text-sm", children: [_jsx("p", { className: "text-muted-foreground", children: "De bestelling wordt pas aangemaakt in Bestellingen nadat je hem hebt gecontroleerd en bevestigd." }), _jsxs("div", { className: "rounded-md border p-3 space-y-1", children: [_jsxs("div", { children: [_jsx("span", { className: "text-muted-foreground", children: "Klant:" }), " ", customers.find((c) => c.id === customerVal)?.company_name ?? "-"] }), _jsxs("div", { children: [_jsx("span", { className: "text-muted-foreground", children: "Bezorgdatum:" }), " ", deliveryVal || "-"] }), _jsxs("div", { children: [_jsx("span", { className: "text-muted-foreground", children: "Bestelregels:" }), " ", lines.filter((l) => l.product_id && (l.quantity ?? 0) > 0).length] }), _jsxs("div", { children: [_jsx("span", { className: "text-muted-foreground", children: "Referentie:" }), " ", values["reference"] || "-"] }), _jsxs("div", { children: [_jsx("span", { className: "text-muted-foreground", children: "Totaal:" }), " ", euro(orderTotal)] })] }), linesWithoutPrice > 0 && (_jsxs("label", { className: "flex items-start gap-2 cursor-pointer rounded-md border border-amber-200 bg-amber-50 p-2 text-amber-800", children: [_jsx("input", { type: "checkbox", className: "mt-1", checked: acceptNoPrice, onChange: (e) => setAcceptNoPrice(e.target.checked) }), _jsxs("span", { children: ["Geen prijs bekend voor ", linesWithoutPrice, " regel(s). Ik wil toch zonder prijs bevestigen."] })] })), _jsxs("label", { className: "flex items-start gap-2 cursor-pointer", children: [_jsx("input", { type: "checkbox", className: "mt-1", checked: checkedOk, onChange: (e) => setCheckedOk(e.target.checked) }), _jsx("span", { children: "Ik heb deze bestelling gecontroleerd en de gegevens kloppen." })] })] }), _jsxs("div", { className: "flex gap-2 pt-2", children: [_jsxs(Button, { className: "flex-1", disabled: !checkedOk || submitting || (linesWithoutPrice > 0 && !acceptNoPrice), onClick: handleConfirm, children: [_jsx(Check, { className: "h-4 w-4 mr-1" }), submitting ? "Bezig…" : "Bevestigen en bestelling aanmaken"] }), _jsx(Button, { variant: "outline", disabled: submitting, onClick: () => setConfirmOpen(false), children: "Annuleren" })] })] }) }), _jsx(NewCustomerDialog, { candidate: newCustomer, onClose: () => setNewCustomer(null), onCreated: (id) => { setNewCustomer(null); setVal("customer", id); } })] })] })] }));
950
+ }, children: _jsxs(DialogContent, { className: "max-w-lg", children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: "Bestelling bevestigen" }) }), _jsxs("div", { className: "space-y-3 text-sm", children: [_jsx("p", { className: "text-muted-foreground", children: "De bestelling wordt pas aangemaakt in Bestellingen nadat je hem hebt gecontroleerd en bevestigd." }), _jsxs("div", { className: "rounded-md border p-3 space-y-1", children: [_jsxs("div", { children: [_jsx("span", { className: "text-muted-foreground", children: "Klant:" }), " ", customers.find((c) => c.id === customerVal)?.company_name ?? "-"] }), _jsxs("div", { children: [_jsx("span", { className: "text-muted-foreground", children: "Bezorgdatum:" }), " ", deliveryVal || "-"] }), _jsxs("div", { children: [_jsx("span", { className: "text-muted-foreground", children: "Bestelregels:" }), " ", lines.filter((l) => l.product_id && (l.quantity ?? 0) > 0).length] }), _jsxs("div", { children: [_jsx("span", { className: "text-muted-foreground", children: "Referentie:" }), " ", values["reference"] || "-"] }), _jsxs("div", { children: [_jsx("span", { className: "text-muted-foreground", children: "Totaal:" }), " ", euro(orderTotal)] })] }), lateOverride && (_jsxs("div", { className: "rounded-md border border-amber-200 bg-amber-50 p-2 text-amber-800", children: ["Je maakt de order toch aan na de aanmeldtijd. Reden: ", lateReason.trim()] })), _jsxs("label", { className: "flex items-start gap-2 cursor-pointer", children: [_jsx("input", { type: "checkbox", className: "mt-1", checked: checkedOk, onChange: (e) => setCheckedOk(e.target.checked) }), _jsx("span", { children: "Ik heb deze bestelling gecontroleerd en de gegevens kloppen." })] })] }), _jsxs("div", { className: "flex gap-2 pt-2", children: [_jsxs(Button, { className: "flex-1", disabled: !checkedOk || submitting, onClick: handleConfirm, children: [_jsx(Check, { className: "h-4 w-4 mr-1" }), submitting ? "Bezig…" : "Bevestigen en bestelling aanmaken"] }), _jsx(Button, { variant: "outline", disabled: submitting, onClick: () => setConfirmOpen(false), children: "Annuleren" })] })] }) }), _jsx(NewCustomerDialog, { candidate: newCustomer, onClose: () => setNewCustomer(null), onCreated: (id) => { setNewCustomer(null); setVal("customer", id); } })] })] })] }));
878
951
  }
879
952
  /** Verplichte bevestiging: externe klant eerst als lokale klant aanmaken. */
880
953
  function NewCustomerDialog({ candidate, onClose, onCreated, }) {
@@ -992,3 +1065,9 @@ function ConfBadge({ meta, thresholds, }) {
992
1065
  : "border-destructive/40 bg-destructive/5 text-destructive";
993
1066
  return (_jsxs("span", { className: `inline-flex items-center rounded border px-1.5 py-0.5 text-[11px] ${cls}`, children: [Math.round(c * 100), "% \u00B7 ", meta.source] }));
994
1067
  }
1068
+ function LateSignupChoice({ open, setOpen, reason, setReason }) {
1069
+ if (!open) {
1070
+ return (_jsx(Button, { size: "sm", variant: "outline", onClick: () => setOpen(true), children: "Toch aanmaken" }));
1071
+ }
1072
+ return (_jsxs("div", { className: "space-y-1", children: [_jsxs(Label, { className: "text-xs", children: ["Reden om toch aan te maken na de aanmeldtijd ", _jsx("span", { className: "text-destructive", children: "*" })] }), _jsx(Textarea, { rows: 2, value: reason, placeholder: "Bijv. afgestemd met de vervoerder", onChange: (e) => setReason(e.target.value) }), _jsx("div", { className: "text-[11px] text-muted-foreground", children: "Wie, wanneer en de reden worden op de order vastgelegd. Daarna \"Controleren & bevestigen\"." }), _jsx(Button, { size: "sm", variant: "ghost", onClick: () => { setOpen(false); setReason(""); }, children: "Annuleren" })] }));
1073
+ }
@@ -606,24 +606,36 @@ export type Database = {
606
606
  ai_modules: {
607
607
  Row: {
608
608
  ai_enabled: boolean;
609
+ ai_source: string;
609
610
  created_at: string;
611
+ declared_ai: boolean;
610
612
  id: string;
613
+ is_in_use: boolean;
614
+ last_declared_at: string | null;
611
615
  module_key: string;
612
616
  module_name: string;
613
617
  updated_at: string;
614
618
  };
615
619
  Insert: {
616
620
  ai_enabled?: boolean;
621
+ ai_source?: string;
617
622
  created_at?: string;
623
+ declared_ai?: boolean;
618
624
  id?: string;
625
+ is_in_use?: boolean;
626
+ last_declared_at?: string | null;
619
627
  module_key: string;
620
628
  module_name: string;
621
629
  updated_at?: string;
622
630
  };
623
631
  Update: {
624
632
  ai_enabled?: boolean;
633
+ ai_source?: string;
625
634
  created_at?: string;
635
+ declared_ai?: boolean;
626
636
  id?: string;
637
+ is_in_use?: boolean;
638
+ last_declared_at?: string | null;
627
639
  module_key?: string;
628
640
  module_name?: string;
629
641
  updated_at?: string;
@@ -15687,7 +15699,7 @@ export type Database = {
15687
15699
  name: string;
15688
15700
  produced_stock: number;
15689
15701
  product_code: string;
15690
- tenant_id: string;
15702
+ tenant_id: string | null;
15691
15703
  updated_at: string;
15692
15704
  };
15693
15705
  Insert: {
@@ -15698,7 +15710,7 @@ export type Database = {
15698
15710
  name: string;
15699
15711
  produced_stock?: number;
15700
15712
  product_code: string;
15701
- tenant_id: string;
15713
+ tenant_id?: string | null;
15702
15714
  updated_at?: string;
15703
15715
  };
15704
15716
  Update: {
@@ -15709,7 +15721,7 @@ export type Database = {
15709
15721
  name?: string;
15710
15722
  produced_stock?: number;
15711
15723
  product_code?: string;
15712
- tenant_id?: string;
15724
+ tenant_id?: string | null;
15713
15725
  updated_at?: string;
15714
15726
  };
15715
15727
  Relationships: [];
@@ -17504,6 +17516,7 @@ export type Database = {
17504
17516
  created_at: string;
17505
17517
  id: string;
17506
17518
  layers_per_cart: number | null;
17519
+ needs_sticker: boolean;
17507
17520
  order_id: string;
17508
17521
  packing_locked_at: string | null;
17509
17522
  packing_locked_by: string | null;
@@ -17523,6 +17536,7 @@ export type Database = {
17523
17536
  created_at?: string;
17524
17537
  id?: string;
17525
17538
  layers_per_cart?: number | null;
17539
+ needs_sticker?: boolean;
17526
17540
  order_id: string;
17527
17541
  packing_locked_at?: string | null;
17528
17542
  packing_locked_by?: string | null;
@@ -17542,6 +17556,7 @@ export type Database = {
17542
17556
  created_at?: string;
17543
17557
  id?: string;
17544
17558
  layers_per_cart?: number | null;
17559
+ needs_sticker?: boolean;
17545
17560
  order_id?: string;
17546
17561
  packing_locked_at?: string | null;
17547
17562
  packing_locked_by?: string | null;
@@ -20998,7 +21013,7 @@ export type Database = {
20998
21013
  parent_trade_item_floriday_id: string | null;
20999
21014
  quantity: number;
21000
21015
  sort_order: number;
21001
- tenant_id: string;
21016
+ tenant_id: string | null;
21002
21017
  unit: string;
21003
21018
  updated_at: string;
21004
21019
  };
@@ -21011,7 +21026,7 @@ export type Database = {
21011
21026
  parent_trade_item_floriday_id?: string | null;
21012
21027
  quantity?: number;
21013
21028
  sort_order?: number;
21014
- tenant_id: string;
21029
+ tenant_id?: string | null;
21015
21030
  unit?: string;
21016
21031
  updated_at?: string;
21017
21032
  };
@@ -21024,7 +21039,7 @@ export type Database = {
21024
21039
  parent_trade_item_floriday_id?: string | null;
21025
21040
  quantity?: number;
21026
21041
  sort_order?: number;
21027
- tenant_id?: string;
21042
+ tenant_id?: string | null;
21028
21043
  unit?: string;
21029
21044
  updated_at?: string;
21030
21045
  };
@@ -21057,7 +21072,7 @@ export type Database = {
21057
21072
  parent_trade_item_floriday_id: string | null;
21058
21073
  quantity: number;
21059
21074
  sort_order: number;
21060
- tenant_id: string;
21075
+ tenant_id: string | null;
21061
21076
  unit: string;
21062
21077
  updated_at: string;
21063
21078
  };
@@ -21072,7 +21087,7 @@ export type Database = {
21072
21087
  parent_trade_item_floriday_id?: string | null;
21073
21088
  quantity?: number;
21074
21089
  sort_order?: number;
21075
- tenant_id: string;
21090
+ tenant_id?: string | null;
21076
21091
  unit?: string;
21077
21092
  updated_at?: string;
21078
21093
  };
@@ -21087,7 +21102,7 @@ export type Database = {
21087
21102
  parent_trade_item_floriday_id?: string | null;
21088
21103
  quantity?: number;
21089
21104
  sort_order?: number;
21090
- tenant_id?: string;
21105
+ tenant_id?: string | null;
21091
21106
  unit?: string;
21092
21107
  updated_at?: string;
21093
21108
  };
@@ -21267,7 +21282,7 @@ export type Database = {
21267
21282
  id: string;
21268
21283
  is_active: boolean;
21269
21284
  name: string;
21270
- tenant_id: string;
21285
+ tenant_id: string | null;
21271
21286
  updated_at: string;
21272
21287
  };
21273
21288
  Insert: {
@@ -21278,7 +21293,7 @@ export type Database = {
21278
21293
  id?: string;
21279
21294
  is_active?: boolean;
21280
21295
  name: string;
21281
- tenant_id: string;
21296
+ tenant_id?: string | null;
21282
21297
  updated_at?: string;
21283
21298
  };
21284
21299
  Update: {
@@ -21289,7 +21304,7 @@ export type Database = {
21289
21304
  id?: string;
21290
21305
  is_active?: boolean;
21291
21306
  name?: string;
21292
- tenant_id?: string;
21307
+ tenant_id?: string | null;
21293
21308
  updated_at?: string;
21294
21309
  };
21295
21310
  Relationships: [
@@ -21324,7 +21339,7 @@ export type Database = {
21324
21339
  packages_per_layer: number | null;
21325
21340
  packing_configuration_id: string;
21326
21341
  product_id: string | null;
21327
- tenant_id: string;
21342
+ tenant_id: string | null;
21328
21343
  trade_item_floriday_id: string | null;
21329
21344
  units_per_package: number | null;
21330
21345
  updated_at: string;
@@ -21343,7 +21358,7 @@ export type Database = {
21343
21358
  packages_per_layer?: number | null;
21344
21359
  packing_configuration_id?: string;
21345
21360
  product_id?: string | null;
21346
- tenant_id: string;
21361
+ tenant_id?: string | null;
21347
21362
  trade_item_floriday_id?: string | null;
21348
21363
  units_per_package?: number | null;
21349
21364
  updated_at?: string;
@@ -21362,7 +21377,7 @@ export type Database = {
21362
21377
  packages_per_layer?: number | null;
21363
21378
  packing_configuration_id?: string;
21364
21379
  product_id?: string | null;
21365
- tenant_id?: string;
21380
+ tenant_id?: string | null;
21366
21381
  trade_item_floriday_id?: string | null;
21367
21382
  units_per_package?: number | null;
21368
21383
  updated_at?: string;
@@ -24625,6 +24640,10 @@ export type Database = {
24625
24640
  superseded_at: string | null;
24626
24641
  updated_at: string;
24627
24642
  user_id: string;
24643
+ write_enabled: boolean;
24644
+ write_enabled_at: string | null;
24645
+ write_enabled_by: string | null;
24646
+ write_enabled_reason: string | null;
24628
24647
  };
24629
24648
  Insert: {
24630
24649
  account_key?: string | null;
@@ -24651,6 +24670,10 @@ export type Database = {
24651
24670
  superseded_at?: string | null;
24652
24671
  updated_at?: string;
24653
24672
  user_id: string;
24673
+ write_enabled?: boolean;
24674
+ write_enabled_at?: string | null;
24675
+ write_enabled_by?: string | null;
24676
+ write_enabled_reason?: string | null;
24654
24677
  };
24655
24678
  Update: {
24656
24679
  account_key?: string | null;
@@ -24677,6 +24700,10 @@ export type Database = {
24677
24700
  superseded_at?: string | null;
24678
24701
  updated_at?: string;
24679
24702
  user_id?: string;
24703
+ write_enabled?: boolean;
24704
+ write_enabled_at?: string | null;
24705
+ write_enabled_by?: string | null;
24706
+ write_enabled_reason?: string | null;
24680
24707
  };
24681
24708
  Relationships: [];
24682
24709
  };
@@ -25565,6 +25592,21 @@ export type Database = {
25565
25592
  };
25566
25593
  Relationships: [];
25567
25594
  };
25595
+ twinfield_schema_upgrades: {
25596
+ Row: {
25597
+ applied_at: string;
25598
+ key: string;
25599
+ };
25600
+ Insert: {
25601
+ applied_at?: string;
25602
+ key: string;
25603
+ };
25604
+ Update: {
25605
+ applied_at?: string;
25606
+ key?: string;
25607
+ };
25608
+ Relationships: [];
25609
+ };
25568
25610
  twinfield_session_cache: {
25569
25611
  Row: {
25570
25612
  cluster: string;
@@ -29681,6 +29723,26 @@ export type Database = {
29681
29723
  Args: never;
29682
29724
  Returns: Json;
29683
29725
  };
29726
+ ai_is_admin: {
29727
+ Args: {
29728
+ _uid: string;
29729
+ };
29730
+ Returns: boolean;
29731
+ };
29732
+ ai_register_consumers: {
29733
+ Args: {
29734
+ _full_list?: boolean;
29735
+ _modules: Json;
29736
+ _source?: string;
29737
+ };
29738
+ Returns: Json;
29739
+ };
29740
+ ai_register_runtime_consumer: {
29741
+ Args: {
29742
+ _module_key: string;
29743
+ };
29744
+ Returns: boolean;
29745
+ };
29684
29746
  ai_usage_by_module: {
29685
29747
  Args: {
29686
29748
  _from: string;
@@ -31836,10 +31898,25 @@ export type Database = {
31836
31898
  };
31837
31899
  Returns: boolean;
31838
31900
  };
31901
+ klanten_auto_promote_status: {
31902
+ Args: never;
31903
+ Returns: Json;
31904
+ };
31839
31905
  klanten_install_check: {
31840
31906
  Args: never;
31841
31907
  Returns: Json;
31842
31908
  };
31909
+ klanten_promote_round: {
31910
+ Args: never;
31911
+ Returns: Json;
31912
+ };
31913
+ klanten_set_auto_promote: {
31914
+ Args: {
31915
+ p_kind: string;
31916
+ p_on: boolean;
31917
+ };
31918
+ Returns: Json;
31919
+ };
31843
31920
  layout_print_document: {
31844
31921
  Args: {
31845
31922
  _documentnaam: string;
@@ -36605,6 +36682,17 @@ export type Database = {
36605
36682
  };
36606
36683
  Returns: string;
36607
36684
  };
36685
+ productontwerp_can_write: {
36686
+ Args: never;
36687
+ Returns: boolean;
36688
+ };
36689
+ productontwerp_create_missing_products: {
36690
+ Args: {
36691
+ p_items: Json;
36692
+ p_run_id: string;
36693
+ };
36694
+ Returns: Json;
36695
+ };
36608
36696
  productontwerp_export: {
36609
36697
  Args: never;
36610
36698
  Returns: Json;
@@ -36616,12 +36704,38 @@ export type Database = {
36616
36704
  };
36617
36705
  Returns: Json;
36618
36706
  };
36707
+ productontwerp_nl_error: {
36708
+ Args: {
36709
+ p_detail: string;
36710
+ p_msg: string;
36711
+ p_state: string;
36712
+ };
36713
+ Returns: string;
36714
+ };
36619
36715
  productontwerp_product_ref: {
36620
36716
  Args: {
36621
36717
  p_id: string;
36622
36718
  };
36623
36719
  Returns: Json;
36624
36720
  };
36721
+ productontwerp_queue_count: {
36722
+ Args: never;
36723
+ Returns: number;
36724
+ };
36725
+ productontwerp_rollback_created_products: {
36726
+ Args: {
36727
+ p_run_id: string;
36728
+ };
36729
+ Returns: Json;
36730
+ };
36731
+ productontwerp_unique_group_name: {
36732
+ Args: {
36733
+ p_article: string;
36734
+ p_base: string;
36735
+ p_used: string[];
36736
+ };
36737
+ Returns: string;
36738
+ };
36625
36739
  promote_floriday_customer: {
36626
36740
  Args: {
36627
36741
  _org_id: string;
@@ -37824,6 +37938,12 @@ export type Database = {
37824
37938
  };
37825
37939
  Returns: boolean;
37826
37940
  };
37941
+ twinfield_cancel_queue_item: {
37942
+ Args: {
37943
+ p_id: string;
37944
+ };
37945
+ Returns: boolean;
37946
+ };
37827
37947
  twinfield_connection_offices: {
37828
37948
  Args: never;
37829
37949
  Returns: {
@@ -37853,6 +37973,19 @@ export type Database = {
37853
37973
  };
37854
37974
  Returns: Json;
37855
37975
  };
37976
+ twinfield_gated_queue: {
37977
+ Args: {
37978
+ p_connection_id: string;
37979
+ };
37980
+ Returns: {
37981
+ action: string;
37982
+ created_at: string;
37983
+ customer_id: string;
37984
+ id: string;
37985
+ payload: Json;
37986
+ status: string;
37987
+ }[];
37988
+ };
37856
37989
  twinfield_handle_administration_change: {
37857
37990
  Args: {
37858
37991
  _administration_code: string;
@@ -37860,6 +37993,10 @@ export type Database = {
37860
37993
  };
37861
37994
  Returns: undefined;
37862
37995
  };
37996
+ twinfield_is_admin: {
37997
+ Args: never;
37998
+ Returns: boolean;
37999
+ };
37863
38000
  twinfield_prune_push_queue: {
37864
38001
  Args: never;
37865
38002
  Returns: number;
@@ -37871,6 +38008,13 @@ export type Database = {
37871
38008
  };
37872
38009
  Returns: Json;
37873
38010
  };
38011
+ twinfield_set_write_enabled: {
38012
+ Args: {
38013
+ p_connection_id: string;
38014
+ p_enabled: boolean;
38015
+ };
38016
+ Returns: Json;
38017
+ };
37874
38018
  twinfield_sync_apply: {
37875
38019
  Args: {
37876
38020
  _base: Json;
@@ -37907,6 +38051,12 @@ export type Database = {
37907
38051
  };
37908
38052
  Returns: Json;
37909
38053
  };
38054
+ twinfield_write_allowed: {
38055
+ Args: {
38056
+ p_connection_id: string;
38057
+ };
38058
+ Returns: boolean;
38059
+ };
37910
38060
  upsert_auto_fulfillment_log: {
37911
38061
  Args: {
37912
38062
  p_connection_id: string;