@flowselections/floriday-klanten-module 1.0.9 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-lib/components/klanten/GroupedKlantDetail.d.ts +4 -0
- package/dist-lib/components/klanten/GroupedKlantDetail.d.ts.map +1 -0
- package/dist-lib/components/klanten/GroupedKlantDetail.js +152 -0
- package/dist-lib/components/klanten/KlantDetail.d.ts +4 -0
- package/dist-lib/components/klanten/KlantDetail.d.ts.map +1 -0
- package/dist-lib/components/klanten/KlantDetail.js +43 -0
- package/dist-lib/components/klanten/NetwerkPagina.d.ts +2 -0
- package/dist-lib/components/klanten/NetwerkPagina.d.ts.map +1 -0
- package/dist-lib/components/klanten/NetwerkPagina.js +23 -0
- package/dist-lib/components/klanten/NieuweKlant.d.ts +2 -0
- package/dist-lib/components/klanten/NieuweKlant.d.ts.map +1 -0
- package/dist-lib/components/klanten/NieuweKlant.js +57 -0
- package/dist-lib/index.d.ts +4 -0
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +4 -0
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +63 -3
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.d.ts +63 -3
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +63 -3
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +63 -3
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/accounting.functions.d.ts +189 -9
- package/dist-lib/lib/accounting.functions.d.ts.map +1 -1
- package/dist-lib/lib/customer-analytics.functions.d.ts +63 -3
- package/dist-lib/lib/customer-analytics.functions.d.ts.map +1 -1
- package/dist-lib/lib/customers.functions.d.ts +441 -21
- package/dist-lib/lib/customers.functions.d.ts.map +1 -1
- package/dist-lib/lib/delivery-locations.functions.d.ts +252 -12
- package/dist-lib/lib/delivery-locations.functions.d.ts.map +1 -1
- package/dist-lib/lib/external-customers.functions.d.ts +252 -12
- package/dist-lib/lib/external-customers.functions.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GroupedKlantDetail.d.ts","sourceRoot":"","sources":["../../../src/components/klanten/GroupedKlantDetail.tsx"],"names":[],"mappings":"AAoBA,wBAAgB,kBAAkB,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,+BA4MpE"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useNavigate } from "@tanstack/react-router";
|
|
3
|
+
import { useQuery } from "@tanstack/react-query";
|
|
4
|
+
import { useServerFn } from "@tanstack/react-start";
|
|
5
|
+
import { useState } from "react";
|
|
6
|
+
import { Card, CardContent, Badge, Button, Tabs, TabsList, TabsTrigger, TabsContent, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@flowselections/core";
|
|
7
|
+
import { ArrowLeft, Mail, Phone } from "lucide-react";
|
|
8
|
+
import { getGroupedCustomerDetail, } from "../../lib/external-customers.functions";
|
|
9
|
+
import { ProfileCard, KpiStrip, BadgeList, EmptyState, adaptGroupedToProfile, } from "../../components/klanten/KlantDetailLayout";
|
|
10
|
+
export function GroupedKlantDetail({ groupKey }) {
|
|
11
|
+
const navigate = useNavigate();
|
|
12
|
+
const get = useServerFn(getGroupedCustomerDetail);
|
|
13
|
+
const [tab, setTab] = useState("overview");
|
|
14
|
+
const { data, isLoading, error } = useQuery({
|
|
15
|
+
queryKey: ["grouped-customer", groupKey],
|
|
16
|
+
queryFn: () => get({ data: { groupKey } }),
|
|
17
|
+
});
|
|
18
|
+
if (isLoading)
|
|
19
|
+
return _jsx("main", { className: "p-6", children: "Laden..." });
|
|
20
|
+
if (error || !data) {
|
|
21
|
+
return (_jsxs("main", { className: "p-6 space-y-3", children: [_jsxs(Button, { variant: "ghost", size: "sm", onClick: () => navigate({ to: "/klanten" }), children: [_jsx(ArrowLeft, { className: "h-4 w-4 mr-2" }), " Terug naar klanten"] }), _jsx("p", { className: "text-sm text-destructive", children: error instanceof Error ? error.message : "Klant niet gevonden." })] }));
|
|
22
|
+
}
|
|
23
|
+
const g = data.group;
|
|
24
|
+
const providerMap = new Map(data.providers.map((p) => [p.provider, p]));
|
|
25
|
+
const sources = g.sources ?? [];
|
|
26
|
+
const profile = adaptGroupedToProfile(g);
|
|
27
|
+
const contacts = collectContacts(sources, providerMap);
|
|
28
|
+
const locations = collectLocations(sources, providerMap);
|
|
29
|
+
const segments = collectArray(sources, ["segments"]);
|
|
30
|
+
const tradeForms = collectArray(sources, ["trade_forms", "tradeForms"]);
|
|
31
|
+
const markets = collectArray(sources, ["markets"]);
|
|
32
|
+
const productGroups = collectArray(sources, ["product_groups", "productGroups"]);
|
|
33
|
+
const paymentMethods = collectArray(sources, ["payment_methods", "paymentMethods"]);
|
|
34
|
+
const activity = sources
|
|
35
|
+
.filter((s) => s.fetched_at)
|
|
36
|
+
.map((s) => ({
|
|
37
|
+
id: `${s.provider}-${s.external_id}`,
|
|
38
|
+
action: "sync",
|
|
39
|
+
created_at: s.fetched_at,
|
|
40
|
+
provider: providerMap.get(s.provider)?.label ?? s.provider,
|
|
41
|
+
}))
|
|
42
|
+
.sort((a, b) => +new Date(b.created_at) - +new Date(a.created_at));
|
|
43
|
+
return (_jsxs("main", { className: "p-6 max-w-7xl mx-auto space-y-4", children: [_jsx("div", { className: "flex items-center justify-between", children: _jsxs(Button, { variant: "ghost", size: "sm", onClick: () => navigate({ to: "/klanten" }), children: [_jsx(ArrowLeft, { className: "h-4 w-4 mr-2" }), " Terug naar klanten"] }) }), _jsxs("div", { className: "grid gap-6 lg:grid-cols-[340px_1fr]", children: [_jsx(ProfileCard, { profile: profile }), _jsxs("div", { className: "space-y-4 min-w-0", children: [_jsx(KpiStrip, { counts: {
|
|
44
|
+
contacts: contacts.length,
|
|
45
|
+
locations: locations.length,
|
|
46
|
+
assortment: 0,
|
|
47
|
+
orders: 0,
|
|
48
|
+
lastSync: g.fetched_at,
|
|
49
|
+
}, onSelect: setTab }), _jsxs(Tabs, { value: tab, onValueChange: setTab, children: [_jsxs(TabsList, { className: "flex-wrap", children: [_jsx(TabsTrigger, { value: "overview", children: "Overzicht" }), _jsxs(TabsTrigger, { value: "contacts", children: ["Contacten (", contacts.length, ")"] }), _jsxs(TabsTrigger, { value: "locations", children: ["Locaties (", locations.length, ")"] }), _jsx(TabsTrigger, { value: "assortment", children: "Assortiment (0)" }), _jsx(TabsTrigger, { value: "orders", children: "Bestellingen (0)" }), _jsx(TabsTrigger, { value: "trade", children: "Handel" }), _jsx(TabsTrigger, { value: "activity", children: "Activiteit" }), g.is_merged && sources.length > 1 && (_jsxs(TabsTrigger, { value: "sources", children: ["Bronnen (", sources.length, ")"] }))] }), _jsxs(TabsContent, { value: "overview", className: "space-y-4", children: [(segments.length || tradeForms.length || markets.length || productGroups.length) ? (_jsx(Card, { children: _jsxs(CardContent, { className: "pt-6 grid gap-4 md:grid-cols-2", children: [_jsx(BadgeList, { label: "Segmenten", items: segments }), _jsx(BadgeList, { label: "Handelsvorm", items: tradeForms }), _jsx(BadgeList, { label: "Afzetmarkten", items: markets }), _jsx(BadgeList, { label: "Productgroepen", items: productGroups })] }) })) : null, paymentMethods.length > 0 && (_jsx(Card, { children: _jsx(CardContent, { className: "pt-6", children: _jsx(BadgeList, { label: "Betaalmethoden", items: paymentMethods }) }) })), !segments.length && !tradeForms.length && !markets.length && !productGroups.length && !paymentMethods.length && (_jsx(EmptyState, { message: "Geen extra profielinformatie beschikbaar voor deze klant." }))] }), _jsx(TabsContent, { value: "contacts", children: contacts.length === 0 ? (_jsx(EmptyState, { message: "Geen contactpersonen beschikbaar via de koppeling." })) : (_jsx("div", { className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3", children: contacts.map((p, i) => (_jsx(Card, { children: _jsxs(CardContent, { className: "pt-6 space-y-2", children: [_jsx("div", { className: "font-semibold", children: p.full_name }), p.job_title && _jsx("div", { className: "text-sm text-muted-foreground", children: p.job_title }), p.phone && (_jsxs("a", { href: `tel:${p.phone}`, className: "text-sm flex items-center gap-2 hover:underline", children: [_jsx(Phone, { className: "h-3.5 w-3.5 text-muted-foreground" }), " ", p.phone] })), p.email && (_jsxs("a", { href: `mailto:${p.email}`, className: "text-sm flex items-center gap-2 hover:underline", children: [_jsx(Mail, { className: "h-3.5 w-3.5 text-muted-foreground" }), " ", p.email] })), _jsx(Badge, { variant: "secondary", children: p.source_label })] }) }, i))) })) }), _jsx(TabsContent, { value: "locations", children: locations.length === 0 ? (_jsx(EmptyState, { message: "Geen afleverlocaties beschikbaar via de koppeling." })) : (_jsx(Card, { children: _jsx(CardContent, { className: "p-0", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Adres" }), _jsx(TableHead, { children: "GLN" }), _jsx(TableHead, { children: "Postcode" }), _jsx(TableHead, { children: "Bron" })] }) }), _jsx(TableBody, { children: locations.map((l, i) => (_jsxs(TableRow, { children: [_jsxs(TableCell, { children: [_jsx("div", { className: "font-medium", children: l.name || l.address_line || "—" }), l.name && l.address_line && (_jsxs("div", { className: "text-xs text-muted-foreground", children: [l.address_line, ", ", l.city ?? ""] }))] }), _jsx(TableCell, { className: "font-mono text-sm", children: l.gln || "—" }), _jsx(TableCell, { className: "text-sm", children: [l.postal_code, l.country].filter(Boolean).join(" · ") }), _jsx(TableCell, { children: _jsx(Badge, { variant: "secondary", children: l.source_label }) })] }, i))) })] }) }) })) }), _jsx(TabsContent, { value: "assortment", children: _jsx(EmptyState, { message: "Assortiment is beschikbaar zodra de koppeling dit levert." }) }), _jsx(TabsContent, { value: "orders", children: _jsx(EmptyState, { message: "Bestellingen zijn beschikbaar zodra de koppeling dit levert." }) }), _jsx(TabsContent, { value: "trade", children: _jsx(EmptyState, { message: "Handelsinstellingen zijn niet beschikbaar via deze koppeling." }) }), _jsx(TabsContent, { value: "activity", children: _jsx(Card, { children: _jsx(CardContent, { className: "pt-6 space-y-2", children: activity.length === 0 ? (_jsx("p", { className: "text-sm text-muted-foreground", children: "Nog geen activiteit voor deze klant." })) : (activity.map((a) => (_jsxs("div", { className: "flex items-center justify-between text-sm border-l-2 border-primary pl-3 py-1", children: [_jsxs("span", { children: ["Bijgewerkt via ", _jsx("strong", { children: a.provider })] }), _jsx("span", { className: "text-xs text-muted-foreground", children: new Date(a.created_at).toLocaleString("nl-NL") })] }, a.id)))) }) }) }), g.is_merged && sources.length > 1 && (_jsx(TabsContent, { value: "sources", children: _jsx(CompareCard, { sources: sources, providerMap: providerMap }) }))] })] })] })] }));
|
|
50
|
+
}
|
|
51
|
+
function collectContacts(sources, providerMap) {
|
|
52
|
+
const out = [];
|
|
53
|
+
for (const s of sources) {
|
|
54
|
+
const label = providerMap.get(s.provider)?.label ?? s.provider;
|
|
55
|
+
const raw = s.raw ?? {};
|
|
56
|
+
const candidates = [];
|
|
57
|
+
if (raw.primaryContact)
|
|
58
|
+
candidates.push(raw.primaryContact);
|
|
59
|
+
if (Array.isArray(raw.contactPersons))
|
|
60
|
+
candidates.push(...raw.contactPersons);
|
|
61
|
+
if (Array.isArray(raw.contacts))
|
|
62
|
+
candidates.push(...raw.contacts);
|
|
63
|
+
if (candidates.length === 0 && s.contact_person) {
|
|
64
|
+
candidates.push({ name: s.contact_person, email: s.email, phone: s.phone });
|
|
65
|
+
}
|
|
66
|
+
for (const c of candidates) {
|
|
67
|
+
const full_name = c.fullName ?? c.name ?? [c.firstName, c.lastName].filter(Boolean).join(" ");
|
|
68
|
+
if (!full_name)
|
|
69
|
+
continue;
|
|
70
|
+
out.push({
|
|
71
|
+
full_name,
|
|
72
|
+
job_title: c.jobTitle ?? c.role ?? null,
|
|
73
|
+
email: c.email ?? c.emailAddress ?? null,
|
|
74
|
+
phone: c.phone ?? c.phoneNumber ?? null,
|
|
75
|
+
source_label: label,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return out;
|
|
80
|
+
}
|
|
81
|
+
function collectLocations(sources, providerMap) {
|
|
82
|
+
const out = [];
|
|
83
|
+
for (const s of sources) {
|
|
84
|
+
const label = providerMap.get(s.provider)?.label ?? s.provider;
|
|
85
|
+
const raw = s.raw ?? {};
|
|
86
|
+
const rawLocs = Array.isArray(raw.deliveryLocations)
|
|
87
|
+
? raw.deliveryLocations
|
|
88
|
+
: Array.isArray(raw.locations) ? raw.locations : [];
|
|
89
|
+
if (rawLocs.length > 0) {
|
|
90
|
+
for (const l of rawLocs) {
|
|
91
|
+
out.push({
|
|
92
|
+
name: l.name ?? null,
|
|
93
|
+
address_line: [l.street, l.houseNumber].filter(Boolean).join(" ") || l.addressLine || null,
|
|
94
|
+
city: l.city ?? null,
|
|
95
|
+
postal_code: l.postalCode ?? l.zipCode ?? null,
|
|
96
|
+
country: l.country ?? l.countryCode ?? null,
|
|
97
|
+
gln: l.gln ?? null,
|
|
98
|
+
source_label: label,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else if (s.street || s.city || s.postal_code) {
|
|
103
|
+
out.push({
|
|
104
|
+
name: null,
|
|
105
|
+
address_line: [s.street, s.house_number].filter(Boolean).join(" ") || null,
|
|
106
|
+
city: s.city,
|
|
107
|
+
postal_code: s.postal_code,
|
|
108
|
+
country: s.country,
|
|
109
|
+
gln: s.gln,
|
|
110
|
+
source_label: label,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return out;
|
|
115
|
+
}
|
|
116
|
+
function collectArray(sources, keys) {
|
|
117
|
+
const set = new Set();
|
|
118
|
+
for (const s of sources) {
|
|
119
|
+
for (const key of keys) {
|
|
120
|
+
const v = s.raw?.[key];
|
|
121
|
+
if (Array.isArray(v))
|
|
122
|
+
for (const x of v)
|
|
123
|
+
if (x)
|
|
124
|
+
set.add(String(x));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return Array.from(set);
|
|
128
|
+
}
|
|
129
|
+
function CompareCard({ sources, providerMap, }) {
|
|
130
|
+
const fields = [
|
|
131
|
+
{ key: "company_name", label: "Bedrijfsnaam" },
|
|
132
|
+
{ key: "commercial_name", label: "Handelsnaam" },
|
|
133
|
+
{ key: "contact_person", label: "Contactpersoon" },
|
|
134
|
+
{ key: "email", label: "E-mail" },
|
|
135
|
+
{ key: "phone", label: "Telefoon" },
|
|
136
|
+
{ key: "street", label: "Straat" },
|
|
137
|
+
{ key: "postal_code", label: "Postcode" },
|
|
138
|
+
{ key: "city", label: "Plaats" },
|
|
139
|
+
{ key: "country", label: "Land" },
|
|
140
|
+
{ key: "website", label: "Website" },
|
|
141
|
+
{ key: "vat_number", label: "BTW" },
|
|
142
|
+
{ key: "gln", label: "GLN" },
|
|
143
|
+
];
|
|
144
|
+
return (_jsx(Card, { children: _jsx(CardContent, { className: "pt-6 overflow-auto", children: _jsxs("table", { className: "w-full text-sm border-collapse", children: [_jsx("thead", { children: _jsxs("tr", { className: "border-b", children: [_jsx("th", { className: "text-left py-2 pr-3 text-xs font-medium uppercase text-muted-foreground", children: "Veld" }), sources.map((s) => (_jsx("th", { className: "text-left py-2 px-3 text-xs font-medium", children: providerMap.get(s.provider)?.label ?? s.provider }, s.provider)))] }) }), _jsx("tbody", { children: fields.map((f) => {
|
|
145
|
+
const values = sources.map((s) => s[f.key] ?? null);
|
|
146
|
+
const firstNonEmpty = values.find((v) => v != null && v !== "");
|
|
147
|
+
return (_jsxs("tr", { className: "border-b last:border-b-0", children: [_jsx("td", { className: "py-2 pr-3 text-muted-foreground align-top", children: f.label }), values.map((v, i) => {
|
|
148
|
+
const differs = v != null && v !== "" && firstNonEmpty != null && v !== firstNonEmpty;
|
|
149
|
+
return (_jsx("td", { className: `py-2 px-3 align-top ${differs ? "bg-muted/40 rounded" : ""}`, children: v && v !== "" ? v : _jsx("span", { className: "text-muted-foreground", children: "\u2014" }) }, i));
|
|
150
|
+
})] }, String(f.key)));
|
|
151
|
+
}) })] }) }) }));
|
|
152
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KlantDetail.d.ts","sourceRoot":"","sources":["../../../src/components/klanten/KlantDetail.tsx"],"names":[],"mappings":"AAsBA,wBAAgB,WAAW,CAAC,EAAE,EAAE,EAAE,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,+BAkPjD"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useNavigate } from "@tanstack/react-router";
|
|
3
|
+
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
4
|
+
import { useServerFn } from "@tanstack/react-start";
|
|
5
|
+
import { useState } from "react";
|
|
6
|
+
import { Card, CardContent, CardHeader, CardTitle, Badge, Button, toast, Tabs, TabsContent, TabsList, TabsTrigger, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from "@flowselections/core";
|
|
7
|
+
import { ArrowLeft, Trash2, Mail, Phone, Power, } from "lucide-react";
|
|
8
|
+
import { getCustomer, deleteCustomer, updateCustomer } from "../../lib/customers.functions";
|
|
9
|
+
import { ProfileCard, KpiStrip, BadgeList, EmptyState, ActivityItem, adaptLocalToProfile, } from "../../components/klanten/KlantDetailLayout";
|
|
10
|
+
import { DeliveryLocationsTab } from "../../components/klanten/DeliveryLocationsTab";
|
|
11
|
+
import { CustomerAnalyticsTab } from "../../components/klanten/CustomerAnalyticsTab";
|
|
12
|
+
export function KlantDetail({ id }) {
|
|
13
|
+
const navigate = useNavigate();
|
|
14
|
+
const qc = useQueryClient();
|
|
15
|
+
const get = useServerFn(getCustomer);
|
|
16
|
+
const del = useServerFn(deleteCustomer);
|
|
17
|
+
const upd = useServerFn(updateCustomer);
|
|
18
|
+
const [tab, setTab] = useState("overview");
|
|
19
|
+
const { data, isLoading } = useQuery({
|
|
20
|
+
queryKey: ["customer", id],
|
|
21
|
+
queryFn: () => get({ data: { id } }),
|
|
22
|
+
});
|
|
23
|
+
const delMut = useMutation({
|
|
24
|
+
mutationFn: () => del({ data: { id } }),
|
|
25
|
+
onSuccess: () => { toast.success("Verwijderd"); navigate({ to: "/klanten" }); },
|
|
26
|
+
});
|
|
27
|
+
const toggleActive = useMutation({
|
|
28
|
+
mutationFn: (active) => upd({ data: { id, is_active: active } }),
|
|
29
|
+
onSuccess: () => qc.invalidateQueries({ queryKey: ["customer", id] }),
|
|
30
|
+
});
|
|
31
|
+
if (isLoading)
|
|
32
|
+
return _jsx("main", { className: "p-6", children: "Laden..." });
|
|
33
|
+
if (!data)
|
|
34
|
+
return _jsx("main", { className: "p-6", children: "Klant niet gevonden" });
|
|
35
|
+
const c = data.customer;
|
|
36
|
+
return (_jsxs("main", { className: "p-6 max-w-7xl mx-auto space-y-4", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs(Button, { variant: "ghost", size: "sm", onClick: () => navigate({ to: "/klanten" }), children: [_jsx(ArrowLeft, { className: "h-4 w-4 mr-2" }), " Terug naar klanten"] }), _jsxs("div", { className: "flex gap-2", children: [_jsxs(Button, { variant: "outline", size: "sm", onClick: () => toggleActive.mutate(!c.is_active), children: [_jsx(Power, { className: "h-4 w-4 mr-2" }), c.is_active ? "Op inactief zetten" : "Activeren"] }), _jsxs(AlertDialog, { children: [_jsx(AlertDialogTrigger, { asChild: true, children: _jsxs(Button, { variant: "outline", size: "sm", children: [_jsx(Trash2, { className: "h-4 w-4 mr-2" }), " Verwijderen"] }) }), _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Klant verwijderen?" }), _jsxs(AlertDialogDescription, { children: ["Weet je zeker dat je ", _jsx("strong", { children: c.company_name }), " wilt verwijderen? Deze actie kan niet ongedaan worden gemaakt."] })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: "Annuleren" }), _jsx(AlertDialogAction, { onClick: () => delMut.mutate(), children: "Verwijderen" })] })] })] })] })] }), _jsxs("div", { className: "grid gap-6 lg:grid-cols-[340px_1fr]", children: [_jsx(ProfileCard, { profile: adaptLocalToProfile(c, data.contacts) }), _jsxs("div", { className: "space-y-4 min-w-0", children: [_jsx(KpiStrip, { counts: {
|
|
37
|
+
contacts: data.contacts.length,
|
|
38
|
+
locations: data.delivery_locations.length,
|
|
39
|
+
assortment: data.assortment.length,
|
|
40
|
+
orders: data.orders.length,
|
|
41
|
+
lastSync: c.last_synced_at,
|
|
42
|
+
}, onSelect: setTab }), _jsxs(Tabs, { value: tab, onValueChange: setTab, children: [_jsxs(TabsList, { className: "flex flex-wrap h-auto gap-1 mb-4", children: [_jsx(TabsTrigger, { value: "overview", children: "Overzicht" }), _jsx(TabsTrigger, { value: "dashboard", children: "Analyses" }), _jsxs(TabsTrigger, { value: "contacts", children: ["Contacten (", data.contacts.length, ")"] }), _jsxs(TabsTrigger, { value: "locations", children: ["Locaties (", data.delivery_locations.length, ")"] }), _jsxs(TabsTrigger, { value: "assortment", children: ["Assortiment (", data.assortment.length, ")"] }), _jsxs(TabsTrigger, { value: "orders", children: ["Bestellingen (", data.orders.length, ")"] }), _jsx(TabsTrigger, { value: "trade", children: "Handel" }), _jsx(TabsTrigger, { value: "activity", children: "Activiteit" })] }), _jsxs(TabsContent, { value: "overview", className: "space-y-4", children: [c.bio && (_jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx(CardTitle, { children: "Bio" }) }), _jsx(CardContent, { className: "text-sm whitespace-pre-wrap", children: c.bio })] })), (c.segments?.length || c.trade_forms?.length || c.markets?.length || c.product_groups?.length) ? (_jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx(CardTitle, { children: "Profiel" }) }), _jsxs(CardContent, { className: "grid gap-4 md:grid-cols-2", children: [_jsx(BadgeList, { label: "Segmenten", items: c.segments }), _jsx(BadgeList, { label: "Handelsvorm", items: c.trade_forms }), _jsx(BadgeList, { label: "Afzetmarkten", items: c.markets }), _jsx(BadgeList, { label: "Productgroepen", items: c.product_groups })] })] })) : null, (c.payment_methods?.length ?? 0) > 0 && (_jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx(CardTitle, { children: "Financi\u00EBle afhandeling" }) }), _jsx(CardContent, { children: _jsx(BadgeList, { label: "Betaalmethoden", items: c.payment_methods }) })] })), c.notes && (_jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx(CardTitle, { children: "Notities" }) }), _jsx(CardContent, { className: "text-sm whitespace-pre-wrap", children: c.notes })] })), !c.bio && !c.notes && !(c.segments?.length || c.trade_forms?.length || c.markets?.length || c.product_groups?.length) && !(c.payment_methods?.length) && (_jsx(EmptyState, { message: "Geen extra profielinformatie beschikbaar voor deze klant." }))] }), _jsx(TabsContent, { value: "contacts", children: data.contacts.length === 0 ? (_jsx(EmptyState, { message: "Geen contactpersonen gesynchroniseerd." })) : (_jsx("div", { className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3", children: data.contacts.map((p) => (_jsx(Card, { children: _jsxs(CardContent, { className: "pt-6 space-y-2", children: [_jsx("div", { className: "font-semibold", children: p.full_name }), p.job_title && _jsx("div", { className: "text-sm text-muted-foreground", children: p.job_title }), p.phone && (_jsxs("a", { href: `tel:${p.phone}`, className: "text-sm flex items-center gap-2 hover:underline", children: [_jsx(Phone, { className: "h-3.5 w-3.5 text-muted-foreground" }), " ", p.phone] })), p.email && (_jsxs("a", { href: `mailto:${p.email}`, className: "text-sm flex items-center gap-2 hover:underline", children: [_jsx(Mail, { className: "h-3.5 w-3.5 text-muted-foreground" }), " ", p.email] })), p.is_active ? _jsx(Badge, { children: "Actief" }) : _jsx(Badge, { variant: "secondary", children: "Inactief" })] }) }, p.id))) })) }), _jsx(TabsContent, { value: "trade", children: data.trade_settings.length === 0 ? (_jsx(EmptyState, { message: "Handelsinstellingen zijn (nog) niet beschikbaar via de Suppliers API voor deze klant." })) : (_jsx(Card, { children: _jsx(CardContent, { className: "pt-6 space-y-2", children: data.trade_settings.map((s) => (_jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Badge, { variant: s.is_active ? "default" : "secondary", children: s.is_active ? "Actief" : "Niet actief" }), _jsx("span", { className: "text-sm", children: s.setting_label })] }, s.id))) }) })) }), _jsx(TabsContent, { value: "locations", children: _jsx(DeliveryLocationsTab, { customerId: id }) }), _jsx(TabsContent, { value: "dashboard", children: _jsx(CustomerAnalyticsTab, { customerId: id }) }), _jsx(TabsContent, { value: "assortment", children: data.assortment.length === 0 ? (_jsx(EmptyState, { message: "Geen geselecteerd assortiment voor deze klant." })) : (_jsx(Card, { children: _jsx(CardContent, { className: "p-0", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Artikelnummer" }), _jsx(TableHead, { children: "Product" }), _jsx(TableHead, { children: "Groep" }), _jsx(TableHead, { children: "Prijs" })] }) }), _jsx(TableBody, { children: data.assortment.map((a) => (_jsxs(TableRow, { children: [_jsx(TableCell, { className: "font-mono text-xs", children: a.article_number || "—" }), _jsx(TableCell, { children: a.product_name }), _jsx(TableCell, { className: "text-sm text-muted-foreground", children: a.product_group || "—" }), _jsx(TableCell, { children: a.price != null ? `€ ${Number(a.price).toFixed(2)}${a.unit ? ` / ${a.unit}` : ""}` : "—" })] }, a.id))) })] }) }) })) }), _jsx(TabsContent, { value: "orders", children: _jsx(Card, { children: _jsx(CardContent, { className: "p-0", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Ordernummer" }), _jsx(TableHead, { children: "Datum" }), _jsx(TableHead, { children: "Status" }), _jsx(TableHead, { children: "Totaal" })] }) }), _jsx(TableBody, { children: data.orders.length === 0 ? (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 4, className: "text-center py-6 text-muted-foreground", children: "Geen bestellingen" }) })) : data.orders.map((o) => (_jsxs(TableRow, { children: [_jsx(TableCell, { children: o.order_number }), _jsx(TableCell, { children: o.order_date }), _jsx(TableCell, { children: _jsx(Badge, { children: o.status }) }), _jsx(TableCell, { children: o.total })] }, o.id))) })] }) }) }) }), _jsx(TabsContent, { value: "activity", children: _jsx(Card, { children: _jsx(CardContent, { className: "pt-6 space-y-2", children: data.audit.length === 0 ? (_jsx("p", { className: "text-sm text-muted-foreground", children: "Nog geen activiteit voor deze klant." })) : (data.audit.map((a) => _jsx(ActivityItem, { entry: a }, a.id))) }) }) })] })] })] })] }));
|
|
43
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NetwerkPagina.d.ts","sourceRoot":"","sources":["../../../src/components/klanten/NetwerkPagina.tsx"],"names":[],"mappings":"AAqBA,wBAAgB,aAAa,gCAyH5B"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Link } from "@tanstack/react-router";
|
|
3
|
+
import { useQuery } from "@tanstack/react-query";
|
|
4
|
+
import { useServerFn } from "@tanstack/react-start";
|
|
5
|
+
import { useState } from "react";
|
|
6
|
+
import { Input, Card, CardContent, Badge, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Switch, Label, } from "@flowselections/core";
|
|
7
|
+
import { ArrowLeft, Search } from "lucide-react";
|
|
8
|
+
import { listFloridayNetwork } from "../../lib/customers.functions";
|
|
9
|
+
export function NetwerkPagina() {
|
|
10
|
+
const [search, setSearch] = useState("");
|
|
11
|
+
const [hideUnknown, setHideUnknown] = useState(true);
|
|
12
|
+
const list = useServerFn(listFloridayNetwork);
|
|
13
|
+
const { data, isLoading } = useQuery({
|
|
14
|
+
queryKey: ["floriday-network", search],
|
|
15
|
+
queryFn: () => list({ data: { search } }),
|
|
16
|
+
});
|
|
17
|
+
const all = data?.organizations ?? [];
|
|
18
|
+
const orgs = hideUnknown
|
|
19
|
+
? all.filter((o) => o.organization_name && o.organization_name.trim() !== "")
|
|
20
|
+
: all;
|
|
21
|
+
const hiddenCount = all.length - orgs.length;
|
|
22
|
+
return (_jsxs("main", { className: "p-6 space-y-4", children: [_jsx("div", { className: "flex items-center justify-between gap-4", children: _jsxs("div", { children: [_jsxs(Link, { to: "/klanten", className: "text-sm text-muted-foreground hover:text-foreground inline-flex items-center gap-1", children: [_jsx(ArrowLeft, { className: "h-3 w-3" }), " Terug naar klanten"] }), _jsx("h1", { className: "text-2xl font-semibold mt-1", children: "Klanten toevoegen uit netwerk" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "Doorzoek alle organisaties die via het netwerk beschikbaar zijn." })] }) }), _jsxs("div", { className: "relative max-w-md", children: [_jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" }), _jsx(Input, { placeholder: "Zoek op organisatienaam of GLN...", value: search, onChange: (e) => setSearch(e.target.value), className: "pl-9" })] }), _jsxs("div", { className: "flex items-center gap-2 text-sm", children: [_jsx(Switch, { id: "hide-unknown", checked: hideUnknown, onCheckedChange: setHideUnknown }), _jsx(Label, { htmlFor: "hide-unknown", className: "cursor-pointer", children: "Verberg organisaties zonder naam" }), hideUnknown && hiddenCount > 0 ? (_jsxs("span", { className: "text-muted-foreground", children: ["(", hiddenCount, " verborgen)"] })) : null] }), _jsx(Card, { children: _jsx(CardContent, { className: "p-0", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: "Organisatie" }), _jsx(TableHead, { children: "GLN" }), _jsx(TableHead, { children: "Plaats" }), _jsx(TableHead, { children: "Land" }), _jsx(TableHead, { children: "Bijgewerkt" })] }) }), _jsx(TableBody, { children: isLoading ? (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 5, className: "text-center py-8 text-muted-foreground", children: "Laden..." }) })) : orgs.length === 0 ? (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 5, className: "text-center py-8 text-muted-foreground", children: "Geen organisaties gevonden." }) })) : (orgs.map((o) => (_jsxs(TableRow, { children: [_jsx(TableCell, { className: "font-medium", children: o.organization_name && o.organization_name.trim() !== "" ? (o.organization_name) : (_jsx("span", { className: "italic text-muted-foreground", children: "Onbekende organisatie" })) }), _jsx(TableCell, { children: o.gln ? (_jsx(Badge, { variant: "outline", children: o.gln })) : ("—") }), _jsx(TableCell, { children: o.city ?? "—" }), _jsx(TableCell, { children: o.country ?? "—" }), _jsx(TableCell, { className: "text-muted-foreground text-sm", children: new Date(o.fetched_at).toLocaleDateString("nl-NL") })] }, `${o.connection_id}-${o.organization_id}`)))) })] }) }) })] }));
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NieuweKlant.d.ts","sourceRoot":"","sources":["../../../src/components/klanten/NieuweKlant.tsx"],"names":[],"mappings":"AAgBA,wBAAgB,WAAW,gCA4H1B"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useNavigate } from "@tanstack/react-router";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { useForm } from "react-hook-form";
|
|
5
|
+
import { zodResolver } from "@hookform/resolvers/zod";
|
|
6
|
+
import { useMutation, useQuery } from "@tanstack/react-query";
|
|
7
|
+
import { useServerFn } from "@tanstack/react-start";
|
|
8
|
+
import { Button, Card, CardContent, CardHeader, CardTitle, Input, Label, Textarea, toast, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@flowselections/core";
|
|
9
|
+
import { ArrowLeft } from "lucide-react";
|
|
10
|
+
import { createCustomer, listCustomerClasses } from "../../lib/customers.functions";
|
|
11
|
+
import { customerCreateSchema } from "../../lib/customer-schemas";
|
|
12
|
+
export function NieuweKlant() {
|
|
13
|
+
const navigate = useNavigate();
|
|
14
|
+
const create = useServerFn(createCustomer);
|
|
15
|
+
const classesFn = useServerFn(listCustomerClasses);
|
|
16
|
+
const [dupes, setDupes] = useState([]);
|
|
17
|
+
const [pendingData, setPendingData] = useState(null);
|
|
18
|
+
const { data: classData } = useQuery({
|
|
19
|
+
queryKey: ["customer-classes"],
|
|
20
|
+
queryFn: () => classesFn({ data: undefined }),
|
|
21
|
+
});
|
|
22
|
+
const form = useForm({
|
|
23
|
+
resolver: zodResolver(customerCreateSchema),
|
|
24
|
+
defaultValues: {
|
|
25
|
+
company_name: "", vat_number: "", contact_person: "", email: "", phone: "",
|
|
26
|
+
street: "", house_number: "", postal_code: "", city: "", country: "Nederland",
|
|
27
|
+
customer_class: "", notes: "", is_active: true, force: false,
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
const mut = useMutation({
|
|
31
|
+
mutationFn: (data) => create({ data }),
|
|
32
|
+
onSuccess: (r) => {
|
|
33
|
+
if (!r.customer && r.duplicates?.length) {
|
|
34
|
+
setDupes(r.duplicates);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
toast.success("Klant aangemaakt");
|
|
38
|
+
navigate({ to: "/klanten/$id", params: { id: r.customer.id } });
|
|
39
|
+
},
|
|
40
|
+
onError: (e) => toast.error(e instanceof Error ? e.message : "Fout"),
|
|
41
|
+
});
|
|
42
|
+
const onSubmit = (values) => {
|
|
43
|
+
setPendingData(values);
|
|
44
|
+
mut.mutate(values);
|
|
45
|
+
};
|
|
46
|
+
const forceCreate = () => {
|
|
47
|
+
if (!pendingData)
|
|
48
|
+
return;
|
|
49
|
+
setDupes([]);
|
|
50
|
+
mut.mutate({ ...pendingData, force: true });
|
|
51
|
+
};
|
|
52
|
+
const fieldErr = (k) => form.formState.errors[k]?.message;
|
|
53
|
+
return (_jsxs("main", { className: "p-6 max-w-3xl mx-auto space-y-4", children: [_jsxs(Button, { variant: "ghost", size: "sm", onClick: () => navigate({ to: "/klanten" }), children: [_jsx(ArrowLeft, { className: "h-4 w-4 mr-2" }), " Terug"] }), _jsxs("form", { onSubmit: form.handleSubmit(onSubmit), children: [_jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx(CardTitle, { children: "Nieuwe klant" }) }), _jsxs(CardContent, { className: "grid grid-cols-2 gap-4", children: [_jsx(Field, { label: "Bedrijfsnaam *", error: fieldErr("company_name"), children: _jsx(Input, { ...form.register("company_name") }) }), _jsx(Field, { label: "BTW-nummer", error: fieldErr("vat_number"), children: _jsx(Input, { ...form.register("vat_number") }) }), _jsx(Field, { label: "Contactpersoon", error: fieldErr("contact_person"), children: _jsx(Input, { ...form.register("contact_person") }) }), _jsx(Field, { label: "E-mail *", error: fieldErr("email"), children: _jsx(Input, { type: "email", ...form.register("email") }) }), _jsx(Field, { label: "Telefoon", error: fieldErr("phone"), children: _jsx(Input, { ...form.register("phone") }) }), _jsx(Field, { label: "Klantklasse", children: _jsxs(Select, { onValueChange: (v) => form.setValue("customer_class", v), defaultValue: "", children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, { placeholder: "Kies klasse..." }) }), _jsx(SelectContent, { children: (classData?.classes ?? []).map((c) => _jsx(SelectItem, { value: c, children: c }, c)) })] }) }), _jsx(Field, { label: "Straat *", error: fieldErr("street"), children: _jsx(Input, { ...form.register("street") }) }), _jsx(Field, { label: "Huisnummer *", error: fieldErr("house_number"), children: _jsx(Input, { ...form.register("house_number") }) }), _jsx(Field, { label: "Postcode", error: fieldErr("postal_code"), children: _jsx(Input, { ...form.register("postal_code") }) }), _jsx(Field, { label: "Stad", error: fieldErr("city"), children: _jsx(Input, { ...form.register("city") }) }), _jsx(Field, { label: "Land *", error: fieldErr("country"), children: _jsx(Input, { ...form.register("country") }) }), _jsxs("div", { className: "col-span-2", children: [_jsx(Label, { children: "Notities" }), _jsx(Textarea, { ...form.register("notes") })] })] })] }), _jsxs("div", { className: "flex justify-end gap-2 mt-4", children: [_jsx(Button, { type: "button", variant: "outline", onClick: () => navigate({ to: "/klanten" }), children: "Annuleren" }), _jsx(Button, { type: "submit", disabled: mut.isPending, children: mut.isPending ? "Opslaan..." : "Klant aanmaken" })] })] }), _jsx(AlertDialog, { open: dupes.length > 0, onOpenChange: (o) => !o && setDupes([]), children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Mogelijke duplicaten gevonden" }), _jsx(AlertDialogDescription, { children: _jsx("ul", { className: "list-disc pl-5 space-y-1 mt-2", children: dupes.map((d) => _jsxs("li", { children: [_jsx("strong", { children: d.company_name }), " \u2014 ", d.reason] }, d.id + d.reason)) }) })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: "Annuleren" }), _jsx(AlertDialogAction, { onClick: forceCreate, children: "Toch aanmaken" })] })] }) })] }));
|
|
54
|
+
}
|
|
55
|
+
function Field({ label, error, children }) {
|
|
56
|
+
return (_jsxs("div", { className: "space-y-1.5", children: [_jsx(Label, { children: label }), children, error && _jsx("p", { className: "text-xs text-destructive", children: error })] }));
|
|
57
|
+
}
|
package/dist-lib/index.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import type { FlowModule } from "@flowselections/core";
|
|
2
2
|
export * from "./_core-safelist";
|
|
3
3
|
export { KlantenOverzicht } from "./components/klanten/KlantenOverzicht";
|
|
4
|
+
export { KlantDetail } from "./components/klanten/KlantDetail";
|
|
5
|
+
export { GroupedKlantDetail } from "./components/klanten/GroupedKlantDetail";
|
|
6
|
+
export { NetwerkPagina } from "./components/klanten/NetwerkPagina";
|
|
7
|
+
export { NieuweKlant } from "./components/klanten/NieuweKlant";
|
|
4
8
|
export declare const floridayKlantenModule: FlowModule;
|
|
5
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist-lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGvD,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGvD,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAC;AAE/D,eAAO,MAAM,qBAAqB,EAAE,UAYnC,CAAC"}
|
package/dist-lib/index.js
CHANGED
|
@@ -17,6 +17,10 @@ import { Users } from "lucide-react";
|
|
|
17
17
|
import { CustomerFieldsCard } from "./components/settings/CustomerFieldsCard";
|
|
18
18
|
export * from "./_core-safelist";
|
|
19
19
|
export { KlantenOverzicht } from "./components/klanten/KlantenOverzicht";
|
|
20
|
+
export { KlantDetail } from "./components/klanten/KlantDetail";
|
|
21
|
+
export { GroupedKlantDetail } from "./components/klanten/GroupedKlantDetail";
|
|
22
|
+
export { NetwerkPagina } from "./components/klanten/NetwerkPagina";
|
|
23
|
+
export { NieuweKlant } from "./components/klanten/NieuweKlant";
|
|
20
24
|
export const floridayKlantenModule = {
|
|
21
25
|
id: "customers",
|
|
22
26
|
name: "Klanten",
|
|
@@ -3899,6 +3899,24 @@ export declare const requireSupabaseAuth: import("@tanstack/start-client-core").
|
|
|
3899
3899
|
};
|
|
3900
3900
|
Relationships: [];
|
|
3901
3901
|
};
|
|
3902
|
+
floriday_order_number_map: {
|
|
3903
|
+
Row: {
|
|
3904
|
+
created_at: string;
|
|
3905
|
+
floriday_id: string;
|
|
3906
|
+
order_number: string;
|
|
3907
|
+
};
|
|
3908
|
+
Insert: {
|
|
3909
|
+
created_at?: string;
|
|
3910
|
+
floriday_id: string;
|
|
3911
|
+
order_number: string;
|
|
3912
|
+
};
|
|
3913
|
+
Update: {
|
|
3914
|
+
created_at?: string;
|
|
3915
|
+
floriday_id?: string;
|
|
3916
|
+
order_number?: string;
|
|
3917
|
+
};
|
|
3918
|
+
Relationships: [];
|
|
3919
|
+
};
|
|
3902
3920
|
floriday_packings_cache: {
|
|
3903
3921
|
Row: {
|
|
3904
3922
|
connection_id: string;
|
|
@@ -5744,6 +5762,24 @@ export declare const requireSupabaseAuth: import("@tanstack/start-client-core").
|
|
|
5744
5762
|
referencedColumns: ["id"];
|
|
5745
5763
|
}];
|
|
5746
5764
|
};
|
|
5765
|
+
order_number_counters: {
|
|
5766
|
+
Row: {
|
|
5767
|
+
last_value: number;
|
|
5768
|
+
updated_at: string;
|
|
5769
|
+
year: number;
|
|
5770
|
+
};
|
|
5771
|
+
Insert: {
|
|
5772
|
+
last_value?: number;
|
|
5773
|
+
updated_at?: string;
|
|
5774
|
+
year: number;
|
|
5775
|
+
};
|
|
5776
|
+
Update: {
|
|
5777
|
+
last_value?: number;
|
|
5778
|
+
updated_at?: string;
|
|
5779
|
+
year?: number;
|
|
5780
|
+
};
|
|
5781
|
+
Relationships: [];
|
|
5782
|
+
};
|
|
5747
5783
|
orders: {
|
|
5748
5784
|
Row: {
|
|
5749
5785
|
created_at: string;
|
|
@@ -5756,6 +5792,7 @@ export declare const requireSupabaseAuth: import("@tanstack/start-client-core").
|
|
|
5756
5792
|
notes: string | null;
|
|
5757
5793
|
order_date: string;
|
|
5758
5794
|
order_number: string;
|
|
5795
|
+
order_source: string;
|
|
5759
5796
|
status: string;
|
|
5760
5797
|
total: string;
|
|
5761
5798
|
updated_at: string;
|
|
@@ -5771,6 +5808,7 @@ export declare const requireSupabaseAuth: import("@tanstack/start-client-core").
|
|
|
5771
5808
|
notes?: string | null;
|
|
5772
5809
|
order_date?: string;
|
|
5773
5810
|
order_number: string;
|
|
5811
|
+
order_source?: string;
|
|
5774
5812
|
status?: string;
|
|
5775
5813
|
total?: string;
|
|
5776
5814
|
updated_at?: string;
|
|
@@ -5786,6 +5824,7 @@ export declare const requireSupabaseAuth: import("@tanstack/start-client-core").
|
|
|
5786
5824
|
notes?: string | null;
|
|
5787
5825
|
order_date?: string;
|
|
5788
5826
|
order_number?: string;
|
|
5827
|
+
order_source?: string;
|
|
5789
5828
|
status?: string;
|
|
5790
5829
|
total?: string;
|
|
5791
5830
|
updated_at?: string;
|
|
@@ -8620,6 +8659,15 @@ export declare const requireSupabaseAuth: import("@tanstack/start-client-core").
|
|
|
8620
8659
|
};
|
|
8621
8660
|
Returns: number;
|
|
8622
8661
|
};
|
|
8662
|
+
assign_floriday_order_numbers: {
|
|
8663
|
+
Args: {
|
|
8664
|
+
p_ids: string[];
|
|
8665
|
+
};
|
|
8666
|
+
Returns: {
|
|
8667
|
+
floriday_id: string;
|
|
8668
|
+
order_number: string;
|
|
8669
|
+
}[];
|
|
8670
|
+
};
|
|
8623
8671
|
call_exact_route: {
|
|
8624
8672
|
Args: {
|
|
8625
8673
|
path: string;
|
|
@@ -8829,6 +8877,12 @@ export declare const requireSupabaseAuth: import("@tanstack/start-client-core").
|
|
|
8829
8877
|
};
|
|
8830
8878
|
Returns: import("./types").Json;
|
|
8831
8879
|
};
|
|
8880
|
+
get_or_assign_floriday_order_number: {
|
|
8881
|
+
Args: {
|
|
8882
|
+
p_floriday_id: string;
|
|
8883
|
+
};
|
|
8884
|
+
Returns: string;
|
|
8885
|
+
};
|
|
8832
8886
|
get_room_busy_windows: {
|
|
8833
8887
|
Args: {
|
|
8834
8888
|
p_from: string;
|
|
@@ -8875,6 +8929,12 @@ export declare const requireSupabaseAuth: import("@tanstack/start-client-core").
|
|
|
8875
8929
|
Args: never;
|
|
8876
8930
|
Returns: boolean;
|
|
8877
8931
|
};
|
|
8932
|
+
next_order_number: {
|
|
8933
|
+
Args: {
|
|
8934
|
+
p_prefix: string;
|
|
8935
|
+
};
|
|
8936
|
+
Returns: string;
|
|
8937
|
+
};
|
|
8878
8938
|
next_work_order_number: {
|
|
8879
8939
|
Args: {
|
|
8880
8940
|
p_parent_work_order_id?: string;
|
|
@@ -8909,9 +8969,9 @@ export declare const requireSupabaseAuth: import("@tanstack/start-client-core").
|
|
|
8909
8969
|
refresh_floricode_derived_code_lists: {
|
|
8910
8970
|
Args: never;
|
|
8911
8971
|
Returns: {
|
|
8912
|
-
|
|
8913
|
-
|
|
8914
|
-
|
|
8972
|
+
environment: string;
|
|
8973
|
+
list_name: string;
|
|
8974
|
+
row_count: number;
|
|
8915
8975
|
}[];
|
|
8916
8976
|
};
|
|
8917
8977
|
reset_floriday_sync_cursor: {
|