@flowselections/mailbox-orders 1.0.10 → 1.0.11

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 (44) hide show
  1. package/dist-lib/components/MailboxProposalsPage.d.ts +16 -0
  2. package/dist-lib/components/MailboxProposalsPage.d.ts.map +1 -1
  3. package/dist-lib/components/MailboxProposalsPage.js +101 -10
  4. package/dist-lib/integrations/supabase/client.d.ts +162 -4
  5. package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
  6. package/dist-lib/integrations/supabase/client.server.d.ts +162 -4
  7. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
  8. package/dist-lib/integrations/supabase/types.d.ts +163 -5
  9. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  10. package/dist-lib/integrations/supabase/types.js +12 -1
  11. package/dist-lib/lib/ai-config.server.d.ts +14 -0
  12. package/dist-lib/lib/ai-config.server.d.ts.map +1 -1
  13. package/dist-lib/lib/ai-config.server.js +32 -19
  14. package/dist-lib/lib/mailbox-ai.server.d.ts +7 -0
  15. package/dist-lib/lib/mailbox-ai.server.d.ts.map +1 -1
  16. package/dist-lib/lib/mailbox-ai.server.js +83 -38
  17. package/dist-lib/lib/mailbox-ingest.server.d.ts +13 -0
  18. package/dist-lib/lib/mailbox-ingest.server.d.ts.map +1 -1
  19. package/dist-lib/lib/mailbox-ingest.server.js +77 -12
  20. package/dist-lib/lib/mailbox.functions.d.ts +23 -5
  21. package/dist-lib/lib/mailbox.functions.d.ts.map +1 -1
  22. package/dist-lib/lib/mailbox.functions.js +97 -4
  23. package/package.json +2 -2
  24. package/dist-lib/components/CartAssignmentWizard.d.ts +0 -6
  25. package/dist-lib/components/CartAssignmentWizard.d.ts.map +0 -1
  26. package/dist-lib/components/CartAssignmentWizard.js +0 -199
  27. package/dist-lib/components/MailboxInboxPage.d.ts +0 -2
  28. package/dist-lib/components/MailboxInboxPage.d.ts.map +0 -1
  29. package/dist-lib/components/MailboxInboxPage.js +0 -120
  30. package/dist-lib/components/settings/ImapAccountsCard.d.ts +0 -2
  31. package/dist-lib/components/settings/ImapAccountsCard.d.ts.map +0 -1
  32. package/dist-lib/components/settings/ImapAccountsCard.js +0 -136
  33. package/dist-lib/components/settings/ImapProfilesCard.d.ts +0 -2
  34. package/dist-lib/components/settings/ImapProfilesCard.d.ts.map +0 -1
  35. package/dist-lib/components/settings/ImapProfilesCard.js +0 -101
  36. package/dist-lib/components/settings/MailboxSettingsCard.d.ts +0 -2
  37. package/dist-lib/components/settings/MailboxSettingsCard.d.ts.map +0 -1
  38. package/dist-lib/components/settings/MailboxSettingsCard.js +0 -85
  39. package/dist-lib/lib/imap.functions.d.ts +0 -32852
  40. package/dist-lib/lib/imap.functions.d.ts.map +0 -1
  41. package/dist-lib/lib/imap.functions.js +0 -235
  42. package/dist-lib/lib/mailbox-auto.server.d.ts +0 -9
  43. package/dist-lib/lib/mailbox-auto.server.d.ts.map +0 -1
  44. package/dist-lib/lib/mailbox-auto.server.js +0 -198
@@ -1,2 +1,18 @@
1
+ /** Klantoptie uit de gecombineerde lijst (lokaal + Twinfield + Floriday). */
2
+ export interface CustomerOption {
3
+ id: string;
4
+ group_key?: string;
5
+ is_local?: boolean;
6
+ company_name: string;
7
+ email?: string | null;
8
+ city?: string | null;
9
+ country?: string | null;
10
+ gln?: string | null;
11
+ street?: string | null;
12
+ house_number?: string | null;
13
+ postal_code?: string | null;
14
+ phone?: string | null;
15
+ providers?: string[];
16
+ }
1
17
  export declare function MailboxProposalsPage(): import("react").JSX.Element;
2
18
  //# sourceMappingURL=MailboxProposalsPage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MailboxProposalsPage.d.ts","sourceRoot":"","sources":["../../src/components/MailboxProposalsPage.tsx"],"names":[],"mappings":"AAqHA,wBAAgB,oBAAoB,gCAwYnC"}
1
+ {"version":3,"file":"MailboxProposalsPage.d.ts","sourceRoot":"","sources":["../../src/components/MailboxProposalsPage.tsx"],"names":[],"mappings":"AAyFA,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,gCAwYnC"}
@@ -5,7 +5,7 @@ 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
7
  import { computeEarliestDelivery, isValidDeliveryDate } from "../lib/delivery-date";
8
- import { listProposals, approveProposal, rejectProposal, listCustomersForPicker, listProductsForPicker, listDeliveryLocationsForCustomer, listPickupLocations, listCarriersForPicker, getOrderPickDays, getActiveOrdersMailbox, syncMailboxNow, getLastIngestRun, refreshProposalsForAgentChange, reparseProposalNow, listBeladingOptionsForProducts, listAllowedLoadCarriers, } from "../lib/mailbox.functions";
8
+ import { listProposals, approveProposal, rejectProposal, listCustomersForPicker, createCustomerFromGroup, listProductsForPicker, listDeliveryLocationsForCustomer, listPickupLocations, listCarriersForPicker, getOrderPickDays, getActiveOrdersMailbox, syncMailboxNow, getLastIngestRun, refreshProposalsForAgentChange, reparseProposalNow, listBeladingOptionsForProducts, listAllowedLoadCarriers, } from "../lib/mailbox.functions";
9
9
  import { enabledLoadCarriers, normalizeAllowedLoadCarriers, EMPTY_LOAD_CARRIERS } from "../lib/load-carriers";
10
10
  import { listTemplateFields, listPlantTypesForPicker, listSuppliersForPicker, } from "../lib/mailbox-template.functions";
11
11
  import { SearchableSelect } from "./SearchableSelect";
@@ -38,16 +38,24 @@ const beladingAllowedByEngine = (b, allowed) => {
38
38
  });
39
39
  };
40
40
  const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
41
+ /** Alleen een echte lokale klant kan aan een bestelling worden gekoppeld. */
42
+ const isLocalCustomerId = (v) => typeof v === "string" && UUID_RE.test(v);
43
+ const providerLabel = (p) => p === "local" ? "Lokaal" : p === "twinfield" ? "Twinfield" : p === "floriday" ? "Floriday" : p;
44
+ const customerHint = (c) => [c.email, c.city, (c.providers ?? []).map(providerLabel).join(" + ")]
45
+ .filter(Boolean).join(" · ");
41
46
  /**
42
- * Zet een klantwaarde (id óf door AI geschreven klantnaam) om naar een geldig
43
- * klant-id. Valt terug op de automatisch herkende klant van het voorstel.
47
+ * Zet een klantwaarde (id óf door AI geschreven klantnaam) om naar een geldige
48
+ * keuze uit de klantenlijst. Lokale klanten hebben voorrang.
44
49
  */
45
50
  function resolveCustomerId(raw, customers, fallbackId) {
46
- const list = Array.isArray(customers) ? customers : [];
51
+ const all = Array.isArray(customers) ? customers : [];
52
+ const list = [...all.filter((c) => c.is_local !== false), ...all.filter((c) => c.is_local === false)];
47
53
  if (typeof raw === "string" && raw.trim()) {
48
54
  const v = raw.trim();
49
55
  if (UUID_RE.test(v))
50
56
  return v;
57
+ if (v.startsWith("grp:") && list.some((c) => c.id === v))
58
+ return v;
51
59
  const norm = v.toLowerCase();
52
60
  const byName = list.find((c) => (c.company_name ?? "").trim().toLowerCase() === norm);
53
61
  if (byName)
@@ -387,10 +395,19 @@ function ProposalEditor({ proposal, template, customers, products, allowBackorde
387
395
  const deliveryVal = values["delivery_date"];
388
396
  const notesVal = values["notes"];
389
397
  const setVal = (key, v) => setValues((prev) => ({ ...prev, [key]: v }));
398
+ // Externe klant gekozen die nog niet lokaal bestaat → verplichte aanmaakdialoog.
399
+ const [newCustomer, setNewCustomer] = useState(null);
400
+ const handleSelectCustomer = (v) => {
401
+ setVal("customer", v);
402
+ if (v && !isLocalCustomerId(v)) {
403
+ const c = customers.find((x) => x.id === v) ?? null;
404
+ setNewCustomer(c);
405
+ }
406
+ };
390
407
  const fetchDeliveryLocations = useServerFn(listDeliveryLocationsForCustomer);
391
408
  const { data: deliveryLocData } = useQuery({
392
409
  queryKey: ["mailbox-delivery-locations", customerVal],
393
- enabled: !!customerVal,
410
+ enabled: isLocalCustomerId(customerVal),
394
411
  queryFn: async () => {
395
412
  try {
396
413
  return await fetchDeliveryLocations({ data: { customerId: customerVal } });
@@ -537,6 +554,11 @@ function ProposalEditor({ proposal, template, customers, products, allowBackorde
537
554
  toast.error(`Verplichte velden ontbreken: ${missing.map((m) => m.label).join(", ")}`);
538
555
  return null;
539
556
  }
557
+ if (customerVal && !isLocalCustomerId(customerVal)) {
558
+ toast.error("Maak deze klant eerst aan voordat je de bestelling verwerkt.");
559
+ setNewCustomer(customers.find((c) => c.id === customerVal) ?? null);
560
+ return null;
561
+ }
540
562
  if (!deliveryLocationVal) {
541
563
  toast.error("Selecteer een afleverlocatie.");
542
564
  return null;
@@ -603,12 +625,15 @@ function ProposalEditor({ proposal, template, customers, products, allowBackorde
603
625
  };
604
626
  const deliveryDateField = visibleFields.find((f) => f.key === "delivery_date");
605
627
  const otherFields = visibleFields.filter((f) => f.key !== "customer" && f.key !== "delivery_date");
606
- const renderField = (field) => (_jsx(DynamicField, { field: field, value: values[field.key], meta: fvMap[field.key], onChange: (v) => setVal(field.key, v), customers: customers, products: products, plantTypes: plantTypes, suppliers: suppliers }, field.key));
628
+ const renderField = (field) => (_jsx(DynamicField, { field: field, value: values[field.key], meta: fvMap[field.key], onChange: (v) => setVal(field.key, v), customers: customers, products: products, plantTypes: plantTypes, suppliers: suppliers, onSelectCustomer: handleSelectCustomer }, field.key));
629
+ const customerNotLocal = !!customerVal && !isLocalCustomerId(customerVal);
607
630
  const payload = (proposal.parsed_payload ?? {});
608
631
  const autoMatched = payload.auto_matched_customer === true;
609
632
  const matchWarning = typeof payload.auto_match_warning === "string" ? payload.auto_match_warning : null;
610
633
  const ai = (payload.ai ?? null);
611
- return (_jsxs(_Fragment, { children: [ai && ai.ok === false && (_jsxs("div", { className: "rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-800", children: ["AI kon deze mail niet uitlezen \u2014 vul de velden handmatig in.", ai.error ? ` (${ai.error})` : ""] })), matchWarning && (_jsx("div", { className: "rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-800", children: matchWarning })), customerField && renderField(customerField), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Locatie" }), _jsx(SearchableSelect, { value: deliveryLocationVal, placeholder: !customerVal
634
+ return (_jsxs(_Fragment, { children: [ai && ai.ok === false && (_jsx("div", { className: "rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-800", children: ai.retry_pending
635
+ ? "De AI-dienst was even bezet — we proberen deze mail automatisch opnieuw. Je kunt de velden intussen zelf invullen."
636
+ : "Deze mail is niet automatisch uitgelezen — vul de velden handmatig in." })), matchWarning && (_jsx("div", { className: "rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-800", children: matchWarning })), customerField && renderField(customerField), customerNotLocal && (_jsxs("div", { className: "rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-800 flex items-center justify-between gap-2", children: [_jsx("span", { children: "Deze klant bestaat nog niet lokaal. Maak de klant eerst aan." }), _jsx(Button, { size: "sm", variant: "outline", onClick: () => setNewCustomer(customers.find((c) => c.id === customerVal) ?? null), children: "Klant aanmaken" })] })), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { children: "Locatie" }), _jsx(SearchableSelect, { value: deliveryLocationVal, placeholder: !customerVal
612
637
  ? "Selecteer eerst een klant"
613
638
  : deliveryLocations.length
614
639
  ? "Kies locatie..."
@@ -742,9 +767,71 @@ function ProposalEditor({ proposal, template, customers, products, allowBackorde
742
767
  setConfirmOpen(o);
743
768
  if (!o)
744
769
  setCheckedOk(false);
745
- }, 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("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" })] })] }) })] })] })] }));
770
+ }, 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("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); } })] })] })] }));
771
+ }
772
+ /** Verplichte bevestiging: externe klant eerst als lokale klant aanmaken. */
773
+ function NewCustomerDialog({ candidate, onClose, onCreated, }) {
774
+ const qc = useQueryClient();
775
+ const createCustomer = useServerFn(createCustomerFromGroup);
776
+ const [form, setForm] = useState({});
777
+ const [busy, setBusy] = useState(false);
778
+ useEffect(() => {
779
+ if (!candidate)
780
+ return;
781
+ setForm({
782
+ companyName: candidate.company_name ?? "",
783
+ email: candidate.email ?? "",
784
+ street: candidate.street ?? "",
785
+ houseNumber: candidate.house_number ?? "",
786
+ postalCode: candidate.postal_code ?? "",
787
+ city: candidate.city ?? "",
788
+ country: candidate.country ?? "",
789
+ gln: candidate.gln ?? "",
790
+ phone: candidate.phone ?? "",
791
+ });
792
+ }, [candidate?.id]);
793
+ const set = (k, v) => setForm((p) => ({ ...p, [k]: v }));
794
+ const field = (k, label, required = false) => (_jsxs("div", { className: "space-y-1", children: [_jsxs(Label, { children: [label, required && _jsx("span", { className: "text-destructive", children: " *" })] }), _jsx(Input, { value: form[k] ?? "", onChange: (e) => set(k, e.target.value) })] }));
795
+ const submit = async () => {
796
+ if (!candidate)
797
+ return;
798
+ if (!(form["companyName"] ?? "").trim()) {
799
+ toast.error("Bedrijfsnaam is verplicht.");
800
+ return;
801
+ }
802
+ setBusy(true);
803
+ try {
804
+ const res = await createCustomer({
805
+ data: {
806
+ groupKey: candidate.group_key ?? candidate.id,
807
+ companyName: form["companyName"].trim(),
808
+ email: (form["email"] ?? "").trim() || null,
809
+ street: (form["street"] ?? "").trim() || null,
810
+ houseNumber: (form["houseNumber"] ?? "").trim() || null,
811
+ postalCode: (form["postalCode"] ?? "").trim() || null,
812
+ city: (form["city"] ?? "").trim() || null,
813
+ country: (form["country"] ?? "").trim() || null,
814
+ gln: (form["gln"] ?? "").trim() || null,
815
+ phone: (form["phone"] ?? "").trim() || null,
816
+ },
817
+ });
818
+ if (!res?.id)
819
+ throw new Error("Klant kon niet worden aangemaakt.");
820
+ await qc.invalidateQueries({ queryKey: ["mailbox-customers"] });
821
+ toast.success(res.created ? "Klant aangemaakt." : "Bestaande klant gekoppeld.");
822
+ onCreated(res.id);
823
+ }
824
+ catch (e) {
825
+ toast.error(e?.message ?? "Aanmaken mislukt.");
826
+ }
827
+ finally {
828
+ setBusy(false);
829
+ }
830
+ };
831
+ return (_jsx(Dialog, { open: !!candidate, onOpenChange: (o) => { if (!o)
832
+ onClose(); }, children: _jsxs(DialogContent, { className: "max-w-xl", children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: "Nieuwe klant aanmaken" }) }), _jsxs("p", { className: "text-sm text-muted-foreground", children: ["Deze klant bestaat alleen in ", (candidate?.providers ?? []).map(providerLabel).join(" + ") || "een externe bron", ". Controleer de gegevens en maak de klant aan voordat je de bestelling verwerkt."] }), _jsxs("div", { className: "grid grid-cols-2 gap-3 py-2", children: [field("companyName", "Bedrijfsnaam", true), field("email", "E-mail"), field("street", "Straat"), field("houseNumber", "Huisnummer"), field("postalCode", "Postcode"), field("city", "Plaats"), field("country", "Land"), field("gln", "GLN"), field("phone", "Telefoon")] }), _jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { className: "flex-1", disabled: busy, onClick: submit, children: busy ? "Bezig…" : "Klant aanmaken en koppelen" }), _jsx(Button, { variant: "outline", disabled: busy, onClick: onClose, children: "Annuleren" })] })] }) }));
746
833
  }
747
- function DynamicField({ field, value, meta, onChange, customers, products, plantTypes, suppliers, }) {
834
+ function DynamicField({ field, value, meta, onChange, customers, products, plantTypes, suppliers, onSelectCustomer, }) {
748
835
  const reviewClass = meta?.needs_review ? "border-yellow-500 ring-1 ring-yellow-500/40 rounded-md p-2" : "";
749
836
  const label = (_jsxs(Label, { className: "flex items-center gap-2", children: [field.label, field.required && _jsx("span", { className: "text-destructive", children: "*" }), meta?.needs_review && (_jsx(Badge, { variant: "outline", className: "text-xs border-yellow-500 text-yellow-700", children: "Controleren" })), typeof meta?.ai_confidence === "number" && (_jsxs("span", { className: "text-xs text-muted-foreground", children: [Math.round(meta.ai_confidence * 100), "%"] }))] }));
750
837
  const renderControl = () => {
@@ -769,7 +856,11 @@ function DynamicField({ field, value, meta, onChange, customers, products, plant
769
856
  }) }));
770
857
  }
771
858
  case "customer":
772
- return (_jsx(SearchableSelect, { value: value ?? null, placeholder: "Kies klant...", options: customers.map((c) => ({ value: c.id, label: c.company_name, hint: c.email })), onChange: onChange }));
859
+ return (_jsx(SearchableSelect, { value: value ?? null, placeholder: "Kies klant...", options: customers.map((c) => ({
860
+ value: c.id,
861
+ label: c.company_name + (c.is_local === false ? " (nog niet aangemaakt)" : ""),
862
+ hint: customerHint(c),
863
+ })), onChange: (v) => (onSelectCustomer ? onSelectCustomer(v) : onChange(v)) }));
773
864
  case "product":
774
865
  return (_jsx(SearchableSelect, { value: value ?? null, placeholder: "Kies product...", options: products.map((p) => ({ value: p.id, label: p.product })), onChange: onChange }));
775
866
  case "plant_type":
@@ -1683,7 +1683,7 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
1683
1683
  city: string | null;
1684
1684
  country: string | null;
1685
1685
  created_at: string;
1686
- customer_id: string | null;
1686
+ customer_id: string;
1687
1687
  external_key: string | null;
1688
1688
  external_provider: string | null;
1689
1689
  floriday_location_id: string | null;
@@ -1707,7 +1707,7 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
1707
1707
  city?: string | null;
1708
1708
  country?: string | null;
1709
1709
  created_at?: string;
1710
- customer_id?: string | null;
1710
+ customer_id: string;
1711
1711
  external_key?: string | null;
1712
1712
  external_provider?: string | null;
1713
1713
  floriday_location_id?: string | null;
@@ -1731,7 +1731,7 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
1731
1731
  city?: string | null;
1732
1732
  country?: string | null;
1733
1733
  created_at?: string;
1734
- customer_id?: string | null;
1734
+ customer_id?: string;
1735
1735
  external_key?: string | null;
1736
1736
  external_provider?: string | null;
1737
1737
  floriday_location_id?: string | null;
@@ -12356,22 +12356,27 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
12356
12356
  created_at: string;
12357
12357
  documentnaam: string;
12358
12358
  documenttype: Database["public"]["Enums"]["doc_layout_type"];
12359
+ extern_job_id: string | null;
12359
12360
  foutmelding: string | null;
12360
12361
  gebruiker_id: string | null;
12361
12362
  gebruiker_naam: string;
12362
12363
  gestart_op: string | null;
12363
12364
  id: string;
12365
+ idempotentie_sleutel: string | null;
12364
12366
  is_herprint: boolean;
12365
12367
  kopieen: number;
12366
12368
  layout_id: string | null;
12367
12369
  opgepakt_op: string | null;
12368
12370
  paginas: number;
12369
12371
  payload: import("./types").Json;
12372
+ pdf_base64: string | null;
12373
+ pdf_url: string | null;
12370
12374
  pogingen: number;
12371
12375
  printer_id: string | null;
12372
12376
  render_html: string | null;
12373
12377
  status: Database["public"]["Enums"]["print_job_status"];
12374
12378
  updated_at: string;
12379
+ volgende_poging: string | null;
12375
12380
  voltooid_op: string | null;
12376
12381
  };
12377
12382
  Insert: {
@@ -12380,22 +12385,27 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
12380
12385
  created_at?: string;
12381
12386
  documentnaam?: string;
12382
12387
  documenttype?: Database["public"]["Enums"]["doc_layout_type"];
12388
+ extern_job_id?: string | null;
12383
12389
  foutmelding?: string | null;
12384
12390
  gebruiker_id?: string | null;
12385
12391
  gebruiker_naam?: string;
12386
12392
  gestart_op?: string | null;
12387
12393
  id?: string;
12394
+ idempotentie_sleutel?: string | null;
12388
12395
  is_herprint?: boolean;
12389
12396
  kopieen?: number;
12390
12397
  layout_id?: string | null;
12391
12398
  opgepakt_op?: string | null;
12392
12399
  paginas?: number;
12393
12400
  payload?: import("./types").Json;
12401
+ pdf_base64?: string | null;
12402
+ pdf_url?: string | null;
12394
12403
  pogingen?: number;
12395
12404
  printer_id?: string | null;
12396
12405
  render_html?: string | null;
12397
12406
  status?: Database["public"]["Enums"]["print_job_status"];
12398
12407
  updated_at?: string;
12408
+ volgende_poging?: string | null;
12399
12409
  voltooid_op?: string | null;
12400
12410
  };
12401
12411
  Update: {
@@ -12404,22 +12414,27 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
12404
12414
  created_at?: string;
12405
12415
  documentnaam?: string;
12406
12416
  documenttype?: Database["public"]["Enums"]["doc_layout_type"];
12417
+ extern_job_id?: string | null;
12407
12418
  foutmelding?: string | null;
12408
12419
  gebruiker_id?: string | null;
12409
12420
  gebruiker_naam?: string;
12410
12421
  gestart_op?: string | null;
12411
12422
  id?: string;
12423
+ idempotentie_sleutel?: string | null;
12412
12424
  is_herprint?: boolean;
12413
12425
  kopieen?: number;
12414
12426
  layout_id?: string | null;
12415
12427
  opgepakt_op?: string | null;
12416
12428
  paginas?: number;
12417
12429
  payload?: import("./types").Json;
12430
+ pdf_base64?: string | null;
12431
+ pdf_url?: string | null;
12418
12432
  pogingen?: number;
12419
12433
  printer_id?: string | null;
12420
12434
  render_html?: string | null;
12421
12435
  status?: Database["public"]["Enums"]["print_job_status"];
12422
12436
  updated_at?: string;
12437
+ volgende_poging?: string | null;
12423
12438
  voltooid_op?: string | null;
12424
12439
  };
12425
12440
  Relationships: [{
@@ -12442,6 +12457,36 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
12442
12457
  referencedColumns: ["id"];
12443
12458
  }];
12444
12459
  };
12460
+ print_queue_runners: {
12461
+ Row: {
12462
+ actief: boolean;
12463
+ basis_url: string;
12464
+ created_at: string;
12465
+ id: string;
12466
+ laatst_gezien: string;
12467
+ tick_sleutel: string;
12468
+ updated_at: string;
12469
+ };
12470
+ Insert: {
12471
+ actief?: boolean;
12472
+ basis_url: string;
12473
+ created_at?: string;
12474
+ id?: string;
12475
+ laatst_gezien?: string;
12476
+ tick_sleutel?: string;
12477
+ updated_at?: string;
12478
+ };
12479
+ Update: {
12480
+ actief?: boolean;
12481
+ basis_url?: string;
12482
+ created_at?: string;
12483
+ id?: string;
12484
+ laatst_gezien?: string;
12485
+ tick_sleutel?: string;
12486
+ updated_at?: string;
12487
+ };
12488
+ Relationships: [];
12489
+ };
12445
12490
  print_rules: {
12446
12491
  Row: {
12447
12492
  actief: boolean;
@@ -12602,6 +12647,7 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
12602
12647
  agent_id: string | null;
12603
12648
  created_at: string;
12604
12649
  driver: string;
12650
+ extern_printer_id: string | null;
12605
12651
  id: string;
12606
12652
  ip_adres: string | null;
12607
12653
  laatst_gezien: string | null;
@@ -12623,6 +12669,7 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
12623
12669
  agent_id?: string | null;
12624
12670
  created_at?: string;
12625
12671
  driver?: string;
12672
+ extern_printer_id?: string | null;
12626
12673
  id?: string;
12627
12674
  ip_adres?: string | null;
12628
12675
  laatst_gezien?: string | null;
@@ -12644,6 +12691,7 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
12644
12691
  agent_id?: string | null;
12645
12692
  created_at?: string;
12646
12693
  driver?: string;
12694
+ extern_printer_id?: string | null;
12647
12695
  id?: string;
12648
12696
  ip_adres?: string | null;
12649
12697
  laatst_gezien?: string | null;
@@ -18248,6 +18296,46 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
18248
18296
  };
18249
18297
  Returns: import("./types").Json;
18250
18298
  };
18299
+ claim_cloud_print_jobs: {
18300
+ Args: {
18301
+ _max?: number;
18302
+ };
18303
+ Returns: {
18304
+ agent_id: string | null;
18305
+ bron_job_id: string | null;
18306
+ created_at: string;
18307
+ documentnaam: string;
18308
+ documenttype: Database["public"]["Enums"]["doc_layout_type"];
18309
+ extern_job_id: string | null;
18310
+ foutmelding: string | null;
18311
+ gebruiker_id: string | null;
18312
+ gebruiker_naam: string;
18313
+ gestart_op: string | null;
18314
+ id: string;
18315
+ idempotentie_sleutel: string | null;
18316
+ is_herprint: boolean;
18317
+ kopieen: number;
18318
+ layout_id: string | null;
18319
+ opgepakt_op: string | null;
18320
+ paginas: number;
18321
+ payload: import("./types").Json;
18322
+ pdf_base64: string | null;
18323
+ pdf_url: string | null;
18324
+ pogingen: number;
18325
+ printer_id: string | null;
18326
+ render_html: string | null;
18327
+ status: Database["public"]["Enums"]["print_job_status"];
18328
+ updated_at: string;
18329
+ volgende_poging: string | null;
18330
+ voltooid_op: string | null;
18331
+ }[];
18332
+ SetofOptions: {
18333
+ from: "*";
18334
+ to: "print_jobs";
18335
+ isOneToOne: false;
18336
+ isSetofReturn: true;
18337
+ };
18338
+ };
18251
18339
  claim_floriday_stock_queue: {
18252
18340
  Args: {
18253
18341
  p_limit?: number;
@@ -18338,22 +18426,27 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
18338
18426
  created_at: string;
18339
18427
  documentnaam: string;
18340
18428
  documenttype: Database["public"]["Enums"]["doc_layout_type"];
18429
+ extern_job_id: string | null;
18341
18430
  foutmelding: string | null;
18342
18431
  gebruiker_id: string | null;
18343
18432
  gebruiker_naam: string;
18344
18433
  gestart_op: string | null;
18345
18434
  id: string;
18435
+ idempotentie_sleutel: string | null;
18346
18436
  is_herprint: boolean;
18347
18437
  kopieen: number;
18348
18438
  layout_id: string | null;
18349
18439
  opgepakt_op: string | null;
18350
18440
  paginas: number;
18351
18441
  payload: import("./types").Json;
18442
+ pdf_base64: string | null;
18443
+ pdf_url: string | null;
18352
18444
  pogingen: number;
18353
18445
  printer_id: string | null;
18354
18446
  render_html: string | null;
18355
18447
  status: Database["public"]["Enums"]["print_job_status"];
18356
18448
  updated_at: string;
18449
+ volgende_poging: string | null;
18357
18450
  voltooid_op: string | null;
18358
18451
  }[];
18359
18452
  SetofOptions: {
@@ -19715,6 +19808,15 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
19715
19808
  };
19716
19809
  Returns: string;
19717
19810
  };
19811
+ pick_active_printers: {
19812
+ Args: never;
19813
+ Returns: {
19814
+ id: string;
19815
+ locatie: string;
19816
+ naam: string;
19817
+ online: boolean;
19818
+ }[];
19819
+ };
19718
19820
  pick_claim_document: {
19719
19821
  Args: {
19720
19822
  _queue_item_id: string;
@@ -19901,6 +20003,52 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
19901
20003
  };
19902
20004
  Returns: undefined;
19903
20005
  };
20006
+ pick_reset_print: {
20007
+ Args: {
20008
+ _queue_item_id: string;
20009
+ _session_id: string;
20010
+ };
20011
+ Returns: {
20012
+ announced_at: string;
20013
+ assigned_user_id: string | null;
20014
+ barcode: string | null;
20015
+ cancelled_at: string | null;
20016
+ cart_count: number;
20017
+ completed_at: string | null;
20018
+ country_code: string | null;
20019
+ created_at: string;
20020
+ customer_name: string | null;
20021
+ delivery_address: string | null;
20022
+ document_number: string | null;
20023
+ document_type_id: string | null;
20024
+ due_at: string | null;
20025
+ id: string;
20026
+ is_urgent: boolean;
20027
+ line_count: number;
20028
+ order_number: string | null;
20029
+ order_type: string | null;
20030
+ payload: import("./types").Json;
20031
+ print_count: number;
20032
+ print_job_id: string | null;
20033
+ printed_at: string | null;
20034
+ printed_by: string | null;
20035
+ printer_id: string | null;
20036
+ priority: number;
20037
+ reference: string | null;
20038
+ route: string | null;
20039
+ screen_id: string | null;
20040
+ station_id: string | null;
20041
+ status_id: string | null;
20042
+ updated_at: string;
20043
+ warnings: import("./types").Json;
20044
+ };
20045
+ SetofOptions: {
20046
+ from: "*";
20047
+ to: "pick_queue";
20048
+ isOneToOne: true;
20049
+ isSetofReturn: false;
20050
+ };
20051
+ };
19904
20052
  pick_station_dashboard: {
19905
20053
  Args: never;
19906
20054
  Returns: {
@@ -20091,6 +20239,12 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
20091
20239
  };
20092
20240
  Returns: import("./types").Json;
20093
20241
  };
20242
+ ruim_print_jobs_op: {
20243
+ Args: {
20244
+ _bewaar_dagen?: number;
20245
+ };
20246
+ Returns: number;
20247
+ };
20094
20248
  run_floriday_continuous_stock_sync: {
20095
20249
  Args: never;
20096
20250
  Returns: undefined;
@@ -20099,6 +20253,10 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
20099
20253
  Args: never;
20100
20254
  Returns: undefined;
20101
20255
  };
20256
+ run_print_queue_ticks: {
20257
+ Args: never;
20258
+ Returns: number;
20259
+ };
20102
20260
  run_twinfield_queue_tick: {
20103
20261
  Args: never;
20104
20262
  Returns: undefined;
@@ -20535,7 +20693,7 @@ export declare const supabase: import("@supabase/supabase-js").SupabaseClient<Da
20535
20693
  };
20536
20694
  Enums: {
20537
20695
  ai_import_status: "nieuw" | "verwerken" | "bevestigen" | "klaar" | "mislukt";
20538
- app_role: "admin" | "planner" | "monteur" | "administratie" | "ai_admin";
20696
+ app_role: "admin" | "planner" | "monteur" | "administratie" | "ai_admin" | "manager" | "warehouse" | "sales" | "developer" | "receptie";
20539
20697
  doc_layout_type: "pakbon" | "factuur" | "offerte" | "orderbevestiging" | "etiket" | "verzendlabel" | "productlabel" | "barcode_label" | "magazijnlijst" | "controlelijst" | "transportdocument" | "vrij" | "sticker" | "productiebon";
20540
20698
  doc_orientation: "portrait" | "landscape";
20541
20699
  exact_env: "staging" | "live";