@flowselections/floriday-klanten-module 1.0.45 → 1.0.48
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/BewerkKlant.d.ts.map +1 -1
- package/dist-lib/components/klanten/BewerkKlant.js +1 -1
- package/dist-lib/components/klanten/CustomerAnalyticsTab.d.ts.map +1 -1
- package/dist-lib/components/klanten/CustomerAnalyticsTab.js +2 -2
- package/dist-lib/components/klanten/FloridayNetworkStatus.d.ts +5 -0
- package/dist-lib/components/klanten/FloridayNetworkStatus.d.ts.map +1 -0
- package/dist-lib/components/klanten/FloridayNetworkStatus.js +18 -0
- package/dist-lib/components/klanten/KlantDetailLayout.d.ts +2 -0
- package/dist-lib/components/klanten/KlantDetailLayout.d.ts.map +1 -1
- package/dist-lib/components/klanten/KlantDetailLayout.js +6 -1
- package/dist-lib/components/klanten/KlantFormulier.d.ts +3 -1
- package/dist-lib/components/klanten/KlantFormulier.d.ts.map +1 -1
- package/dist-lib/components/klanten/KlantFormulier.js +16 -4
- package/dist-lib/components/klanten/KlantenOverzicht.d.ts.map +1 -1
- package/dist-lib/components/klanten/KlantenOverzicht.js +6 -5
- package/dist-lib/components/klanten/NetwerkPagina.d.ts.map +1 -1
- package/dist-lib/components/klanten/NetwerkPagina.js +9 -5
- package/dist-lib/components/klanten/NieuweKlant.d.ts.map +1 -1
- package/dist-lib/components/klanten/NieuweKlant.js +10 -7
- package/dist-lib/components/klanten/pricegroups/CustomerPickerDialog.d.ts.map +1 -1
- package/dist-lib/components/klanten/pricegroups/CustomerPickerDialog.js +10 -2
- package/dist-lib/components/klanten/pricegroups/PriceGroupsPage.d.ts.map +1 -1
- package/dist-lib/components/klanten/pricegroups/PriceGroupsPage.js +4 -7
- package/dist-lib/components/klanten/pricegroups/UnknownFloridayMembers.d.ts +11 -0
- package/dist-lib/components/klanten/pricegroups/UnknownFloridayMembers.d.ts.map +1 -0
- package/dist-lib/components/klanten/pricegroups/UnknownFloridayMembers.js +43 -0
- package/dist-lib/index.js +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +1470 -2
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.js +1 -0
- package/dist-lib/lib/customer-schemas.d.ts +2 -0
- package/dist-lib/lib/customer-schemas.d.ts.map +1 -1
- package/dist-lib/lib/customer-schemas.js +2 -0
- package/dist-lib/lib/customers.functions.d.ts +37 -0
- package/dist-lib/lib/customers.functions.d.ts.map +1 -1
- package/dist-lib/lib/customers.functions.js +49 -4
- package/dist-lib/lib/floriday-network-status.functions.d.ts +18 -0
- package/dist-lib/lib/floriday-network-status.functions.d.ts.map +1 -0
- package/dist-lib/lib/floriday-network-status.functions.js +41 -0
- package/dist-lib/lib/price-groups-local.functions.d.ts +42 -0
- package/dist-lib/lib/price-groups-local.functions.d.ts.map +1 -1
- package/dist-lib/lib/price-groups-local.functions.js +120 -1
- package/dist-lib/lib/twinfield-adopt.functions.d.ts +2 -0
- package/dist-lib/lib/twinfield-adopt.functions.d.ts.map +1 -1
- package/dist-lib/lib/vat-format.d.ts +17 -0
- package/dist-lib/lib/vat-format.d.ts.map +1 -0
- package/dist-lib/lib/vat-format.js +64 -0
- package/package.json +5 -5
|
@@ -2,6 +2,7 @@ import { z } from "zod";
|
|
|
2
2
|
export declare const customerCreateSchema: z.ZodObject<{
|
|
3
3
|
is_active: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
4
4
|
force: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
5
|
+
twinfield_create: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
5
6
|
ledger_account: z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>;
|
|
6
7
|
credit_limit: z.ZodDefault<z.ZodOptional<z.ZodCoercedNumber<unknown>>>;
|
|
7
8
|
send_reminder: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
@@ -70,6 +71,7 @@ export type CustomerCreateInput = z.infer<typeof customerCreateSchema>;
|
|
|
70
71
|
export declare const customerUpdateSchema: z.ZodObject<{
|
|
71
72
|
is_active: z.ZodOptional<z.ZodDefault<z.ZodOptional<z.ZodBoolean>>>;
|
|
72
73
|
force: z.ZodOptional<z.ZodDefault<z.ZodOptional<z.ZodBoolean>>>;
|
|
74
|
+
twinfield_create: z.ZodOptional<z.ZodDefault<z.ZodOptional<z.ZodBoolean>>>;
|
|
73
75
|
ledger_account: z.ZodOptional<z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>>;
|
|
74
76
|
credit_limit: z.ZodOptional<z.ZodDefault<z.ZodOptional<z.ZodCoercedNumber<unknown>>>>;
|
|
75
77
|
send_reminder: z.ZodOptional<z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"customer-schemas.d.ts","sourceRoot":"","sources":["../../src/lib/customer-schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"customer-schemas.d.ts","sourceRoot":"","sources":["../../src/lib/customer-schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAyQxB,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAsD,CAAC;AAExF,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEvE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyB7B,CAAC;AAEL,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAsDvE,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAyD,CAAC;AAE9F,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAG/B,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEvE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;iBAQ5B,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC"}
|
|
@@ -222,6 +222,8 @@ const customerCreateBaseSchema = z.object({
|
|
|
222
222
|
...accountingFields,
|
|
223
223
|
is_active: z.boolean().optional().default(true),
|
|
224
224
|
force: z.boolean().optional().default(false),
|
|
225
|
+
/** Ook als debiteur aanmaken in de actieve Twinfield-administratie (alleen bij aanmaken). */
|
|
226
|
+
twinfield_create: z.boolean().optional().default(true),
|
|
225
227
|
});
|
|
226
228
|
export const customerCreateSchema = customerCreateBaseSchema.superRefine(checkCustomer);
|
|
227
229
|
export const customerUpdateSchema = customerCreateBaseSchema
|
|
@@ -9,6 +9,35 @@ type TwinfieldDraft = {
|
|
|
9
9
|
country?: string | null;
|
|
10
10
|
vat_number?: string | null;
|
|
11
11
|
};
|
|
12
|
+
/** Naam en code van de actieve Twinfield-administratie, voor vinkje en knop. */
|
|
13
|
+
export declare const getActiveTwinfieldAdministration: import("@tanstack/start-client-core").OptionalFetcher<readonly [import("@tanstack/start-client-core").FunctionMiddlewareAfterServer<{}, unknown, undefined, {
|
|
14
|
+
supabase: import("../integrations/supabase/auth-middleware").AuthedSupabaseClient;
|
|
15
|
+
userId: string;
|
|
16
|
+
claims: import("@supabase/auth-js").JwtPayload;
|
|
17
|
+
}, undefined, undefined, undefined>], undefined, Promise<{
|
|
18
|
+
active: false;
|
|
19
|
+
code?: undefined;
|
|
20
|
+
name?: undefined;
|
|
21
|
+
} | {
|
|
22
|
+
active: true;
|
|
23
|
+
code: string;
|
|
24
|
+
name: string;
|
|
25
|
+
}>>;
|
|
26
|
+
/**
|
|
27
|
+
* Alsnog debiteur aanmaken voor een klant zonder Twinfield-code (na bevestiging).
|
|
28
|
+
* Zet het kenmerk aan; de wachtrijtrigger plant dan een aanmaakregel.
|
|
29
|
+
*/
|
|
30
|
+
export declare const createTwinfieldDebtorNow: import("@tanstack/start-client-core").RequiredFetcher<readonly [import("@tanstack/start-client-core").FunctionMiddlewareAfterServer<{}, unknown, undefined, {
|
|
31
|
+
supabase: import("../integrations/supabase/auth-middleware").AuthedSupabaseClient;
|
|
32
|
+
userId: string;
|
|
33
|
+
claims: import("@supabase/auth-js").JwtPayload;
|
|
34
|
+
}, undefined, undefined, undefined>], (input: {
|
|
35
|
+
id: string;
|
|
36
|
+
}) => {
|
|
37
|
+
id: string;
|
|
38
|
+
}, Promise<{
|
|
39
|
+
ok: true;
|
|
40
|
+
}>>;
|
|
12
41
|
export declare const precheckTwinfieldPush: import("@tanstack/start-client-core").RequiredFetcher<readonly [import("@tanstack/start-client-core").FunctionMiddlewareAfterServer<{}, unknown, undefined, {
|
|
13
42
|
supabase: import("../integrations/supabase/auth-middleware").AuthedSupabaseClient;
|
|
14
43
|
userId: string;
|
|
@@ -128,6 +157,7 @@ export declare const getCustomer: import("@tanstack/start-client-core").Required
|
|
|
128
157
|
twinfield_base_snapshot: import("../integrations/supabase/types").Json | null;
|
|
129
158
|
twinfield_base_version: number | null;
|
|
130
159
|
twinfield_code: string | null;
|
|
160
|
+
twinfield_create_on_insert: boolean;
|
|
131
161
|
twinfield_last_hash: string | null;
|
|
132
162
|
twinfield_missing_since: string | null;
|
|
133
163
|
twinfield_present: boolean;
|
|
@@ -221,6 +251,7 @@ export declare const createCustomer: import("@tanstack/start-client-core").Requi
|
|
|
221
251
|
}, undefined, undefined, undefined>], (input: CustomerCreateInput) => {
|
|
222
252
|
is_active: boolean;
|
|
223
253
|
force: boolean;
|
|
254
|
+
twinfield_create: boolean;
|
|
224
255
|
credit_limit: number;
|
|
225
256
|
send_reminder: "no" | "file" | "file_email";
|
|
226
257
|
payment_spec_method: "email" | "file";
|
|
@@ -357,6 +388,7 @@ export declare const createCustomer: import("@tanstack/start-client-core").Requi
|
|
|
357
388
|
twinfield_base_snapshot: import("../integrations/supabase/types").Json | null;
|
|
358
389
|
twinfield_base_version: number | null;
|
|
359
390
|
twinfield_code: string | null;
|
|
391
|
+
twinfield_create_on_insert: boolean;
|
|
360
392
|
twinfield_last_hash: string | null;
|
|
361
393
|
twinfield_missing_since: string | null;
|
|
362
394
|
twinfield_present: boolean;
|
|
@@ -380,6 +412,7 @@ export declare const updateCustomer: import("@tanstack/start-client-core").Optio
|
|
|
380
412
|
id: string;
|
|
381
413
|
is_active?: boolean | undefined;
|
|
382
414
|
force?: boolean | undefined;
|
|
415
|
+
twinfield_create?: boolean | undefined;
|
|
383
416
|
ledger_account?: string | undefined;
|
|
384
417
|
credit_limit?: number | undefined;
|
|
385
418
|
send_reminder?: "no" | "file" | "file_email" | undefined;
|
|
@@ -510,6 +543,7 @@ export declare const updateCustomer: import("@tanstack/start-client-core").Optio
|
|
|
510
543
|
twinfield_base_snapshot: import("../integrations/supabase/types").Json | null;
|
|
511
544
|
twinfield_base_version: number | null;
|
|
512
545
|
twinfield_code: string | null;
|
|
546
|
+
twinfield_create_on_insert: boolean;
|
|
513
547
|
twinfield_last_hash: string | null;
|
|
514
548
|
twinfield_missing_since: string | null;
|
|
515
549
|
twinfield_present: boolean;
|
|
@@ -549,11 +583,13 @@ export declare const listFloridayNetwork: import("@tanstack/start-client-core").
|
|
|
549
583
|
types?: string[];
|
|
550
584
|
includeExpired?: boolean;
|
|
551
585
|
limit?: number;
|
|
586
|
+
offset?: number;
|
|
552
587
|
}) => {
|
|
553
588
|
search: string;
|
|
554
589
|
types: string[];
|
|
555
590
|
includeExpired: boolean;
|
|
556
591
|
limit: number;
|
|
592
|
+
offset: number;
|
|
557
593
|
}, Promise<{
|
|
558
594
|
organizations: {
|
|
559
595
|
connection_id: any;
|
|
@@ -575,6 +611,7 @@ export declare const listFloridayNetwork: import("@tanstack/start-client-core").
|
|
|
575
611
|
}[];
|
|
576
612
|
total: number;
|
|
577
613
|
limit: number;
|
|
614
|
+
offset: number;
|
|
578
615
|
truncated: boolean;
|
|
579
616
|
}>>;
|
|
580
617
|
export declare const listCustomerClasses: import("@tanstack/start-client-core").OptionalFetcher<readonly [import("@tanstack/start-client-core").FunctionMiddlewareAfterServer<{}, unknown, undefined, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"customers.functions.d.ts","sourceRoot":"","sources":["../../src/lib/customers.functions.ts"],"names":[],"mappings":"AAIA,OAAO,EAKL,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAK5B,KAAK,cAAc,GAAG;IACpB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;
|
|
1
|
+
{"version":3,"file":"customers.functions.d.ts","sourceRoot":"","sources":["../../src/lib/customers.functions.ts"],"names":[],"mappings":"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"}
|
|
@@ -35,13 +35,46 @@ function checkTwinfieldReady(draft) {
|
|
|
35
35
|
async function getActiveTwinfieldConnection(supabase) {
|
|
36
36
|
const { data } = await supabase
|
|
37
37
|
.from("twinfield_connections")
|
|
38
|
-
.select("id, office_code, company_code, is_active")
|
|
38
|
+
.select("id, office_code, company_code, company_name, label, is_active")
|
|
39
39
|
.eq("is_active", true)
|
|
40
40
|
.order("connected_at", { ascending: false })
|
|
41
41
|
.limit(1)
|
|
42
42
|
.maybeSingle();
|
|
43
43
|
return data;
|
|
44
44
|
}
|
|
45
|
+
/** Naam en code van de actieve Twinfield-administratie, voor vinkje en knop. */
|
|
46
|
+
export const getActiveTwinfieldAdministration = createServerFn({ method: "POST" })
|
|
47
|
+
.middleware([requireSupabaseAuth])
|
|
48
|
+
.handler(async ({ context }) => {
|
|
49
|
+
const c = await getActiveTwinfieldConnection(context.supabase);
|
|
50
|
+
if (!c)
|
|
51
|
+
return { active: false };
|
|
52
|
+
const code = c.office_code ?? c.company_code ?? "";
|
|
53
|
+
const name = (c.company_name ?? c.label ?? "").trim();
|
|
54
|
+
return { active: true, code, name };
|
|
55
|
+
});
|
|
56
|
+
/**
|
|
57
|
+
* Alsnog debiteur aanmaken voor een klant zonder Twinfield-code (na bevestiging).
|
|
58
|
+
* Zet het kenmerk aan; de wachtrijtrigger plant dan een aanmaakregel.
|
|
59
|
+
*/
|
|
60
|
+
export const createTwinfieldDebtorNow = createServerFn({ method: "POST" })
|
|
61
|
+
.middleware([requireSupabaseAuth])
|
|
62
|
+
.inputValidator((input) => z.object({ id: z.string().uuid() }).parse(input))
|
|
63
|
+
.handler(async ({ data, context }) => {
|
|
64
|
+
const conn = await getActiveTwinfieldConnection(context.supabase);
|
|
65
|
+
if (!conn)
|
|
66
|
+
throw new Error("Er is geen actieve Twinfield-koppeling. Er is niets verstuurd.");
|
|
67
|
+
const { data: c } = await context.supabase
|
|
68
|
+
.from("customers").select("twinfield_code").eq("id", data.id).maybeSingle();
|
|
69
|
+
if (c?.twinfield_code)
|
|
70
|
+
throw new Error("Deze klant heeft al een debiteur in Twinfield.");
|
|
71
|
+
const { error } = await context.supabase
|
|
72
|
+
.from("customers").update({ twinfield_create_on_insert: true }).eq("id", data.id);
|
|
73
|
+
if (error)
|
|
74
|
+
throw new Error(friendlyError(error, "Debiteur aanmaken mislukt."));
|
|
75
|
+
await pushCustomerNow(data.id);
|
|
76
|
+
return { ok: true };
|
|
77
|
+
});
|
|
45
78
|
export const precheckTwinfieldPush = createServerFn({ method: "POST" })
|
|
46
79
|
.middleware([requireSupabaseAuth])
|
|
47
80
|
.inputValidator((input) => z.object({ draft: z.record(z.string(), z.any()).default({}) }).parse(input ?? { draft: {} }))
|
|
@@ -248,9 +281,17 @@ export const createCustomer = createServerFn({ method: "POST" })
|
|
|
248
281
|
const { loadCustomerDefaults } = await import("./twinfield-customer-defaults.server");
|
|
249
282
|
const defaults = await loadCustomerDefaults(supabase);
|
|
250
283
|
const number = await resolveFreeCustomerNumber(supabase, data.customer_number);
|
|
284
|
+
// Zonder actieve koppeling nooit versturen (fail closed).
|
|
285
|
+
const activeConn = await getActiveTwinfieldConnection(supabase);
|
|
286
|
+
const createInTwinfield = data.twinfield_create !== false && !!activeConn;
|
|
287
|
+
const { twinfield_create: _tc, ...rowInput } = data;
|
|
251
288
|
const { data: inserted, error } = await supabase
|
|
252
289
|
.from("customers")
|
|
253
|
-
.insert({
|
|
290
|
+
.insert({
|
|
291
|
+
...buildCustomerInsert(rowInput, defaults),
|
|
292
|
+
customer_number: number.value,
|
|
293
|
+
twinfield_create_on_insert: createInTwinfield,
|
|
294
|
+
})
|
|
254
295
|
.select("*")
|
|
255
296
|
.single();
|
|
256
297
|
if (error) {
|
|
@@ -383,6 +424,7 @@ export const listFloridayNetwork = createServerFn({ method: "POST" })
|
|
|
383
424
|
: ["CUSTOMER", "AGENT"],
|
|
384
425
|
includeExpired: !!input?.includeExpired,
|
|
385
426
|
limit: Math.min(Math.max(Number(input?.limit) || 500, 1), 2000),
|
|
427
|
+
offset: Math.max(Number(input?.offset) || 0, 0),
|
|
386
428
|
}))
|
|
387
429
|
.handler(async ({ data, context }) => {
|
|
388
430
|
const nowIso = new Date().toISOString();
|
|
@@ -390,7 +432,9 @@ export const listFloridayNetwork = createServerFn({ method: "POST" })
|
|
|
390
432
|
.from("floriday_network_cache")
|
|
391
433
|
.select("connection_id, organization_id, organization_name, gln, country, city, data, fetched_at", { count: "exact" })
|
|
392
434
|
.in("data->>organizationType", data.types)
|
|
393
|
-
.
|
|
435
|
+
.order("organization_name", { ascending: true, nullsFirst: false })
|
|
436
|
+
.order("organization_id", { ascending: true })
|
|
437
|
+
.range(data.offset, data.offset + data.limit - 1);
|
|
394
438
|
if (!data.includeExpired) {
|
|
395
439
|
q = q.or(`data->>endDate.is.null,data->>endDate.gt.${nowIso}`);
|
|
396
440
|
}
|
|
@@ -445,7 +489,8 @@ export const listFloridayNetwork = createServerFn({ method: "POST" })
|
|
|
445
489
|
organizations,
|
|
446
490
|
total: count ?? organizations.length,
|
|
447
491
|
limit: data.limit,
|
|
448
|
-
|
|
492
|
+
offset: data.offset,
|
|
493
|
+
truncated: (count ?? 0) > data.offset + organizations.length,
|
|
449
494
|
};
|
|
450
495
|
});
|
|
451
496
|
export const listCustomerClasses = createServerFn({ method: "POST" })
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type FloridayNetworkStatus = {
|
|
2
|
+
/** null = onbekend (geen actieve Floriday-koppeling). */
|
|
3
|
+
inNetwork: boolean | null;
|
|
4
|
+
endDate: string | null;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* "In je Floriday-netwerk": alleen lezen uit de caches van de Floriday-module, op organisatie-id.
|
|
8
|
+
* Ja = rij in floriday_connections_cache voor de actieve koppeling met dit customerOrganizationId
|
|
9
|
+
* en isDeleted = false.
|
|
10
|
+
*/
|
|
11
|
+
export declare const getFloridayNetworkStatus: import("@tanstack/start-client-core").OptionalFetcher<readonly [import("@tanstack/start-client-core").FunctionMiddlewareAfterServer<{}, unknown, undefined, {
|
|
12
|
+
supabase: import("../integrations/supabase/auth-middleware").AuthedSupabaseClient;
|
|
13
|
+
userId: string;
|
|
14
|
+
claims: import("@supabase/auth-js").JwtPayload;
|
|
15
|
+
}, undefined, undefined, undefined>], (input: unknown) => {
|
|
16
|
+
organizationId: string;
|
|
17
|
+
}, Promise<FloridayNetworkStatus>>;
|
|
18
|
+
//# sourceMappingURL=floriday-network-status.functions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"floriday-network-status.functions.d.ts","sourceRoot":"","sources":["../../src/lib/floriday-network-status.functions.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,qBAAqB,GAAG;IAClC,yDAAyD;IACzD,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,wBAAwB;;;;8CAEX,OAAO;;kCAgC7B,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { createServerFn } from "@tanstack/react-start";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { requireSupabaseAuth } from "../integrations/supabase/auth-middleware";
|
|
4
|
+
/**
|
|
5
|
+
* "In je Floriday-netwerk": alleen lezen uit de caches van de Floriday-module, op organisatie-id.
|
|
6
|
+
* Ja = rij in floriday_connections_cache voor de actieve koppeling met dit customerOrganizationId
|
|
7
|
+
* en isDeleted = false.
|
|
8
|
+
*/
|
|
9
|
+
export const getFloridayNetworkStatus = createServerFn({ method: "GET" })
|
|
10
|
+
.middleware([requireSupabaseAuth])
|
|
11
|
+
.inputValidator((input) => z.object({ organizationId: z.string().min(1).max(64) }).parse(input))
|
|
12
|
+
.handler(async ({ data, context }) => {
|
|
13
|
+
const sb = context.supabase;
|
|
14
|
+
const { data: conn } = await sb
|
|
15
|
+
.from("floriday_connections")
|
|
16
|
+
.select("id")
|
|
17
|
+
.eq("is_active", true)
|
|
18
|
+
.order("updated_at", { ascending: false })
|
|
19
|
+
.limit(1)
|
|
20
|
+
.maybeSingle();
|
|
21
|
+
let inNetwork = null;
|
|
22
|
+
if (conn?.id) {
|
|
23
|
+
const { data: rows, error } = await sb
|
|
24
|
+
.from("floriday_connections_cache")
|
|
25
|
+
.select("connection_id")
|
|
26
|
+
.eq("connection_id", conn.id)
|
|
27
|
+
.eq("data->>customerOrganizationId", data.organizationId)
|
|
28
|
+
.eq("data->>isDeleted", "false")
|
|
29
|
+
.limit(1);
|
|
30
|
+
inNetwork = error ? null : (rows ?? []).length > 0;
|
|
31
|
+
}
|
|
32
|
+
const { data: cust } = await sb
|
|
33
|
+
.from("floriday_customers_cache")
|
|
34
|
+
.select("data, fetched_at")
|
|
35
|
+
.eq("organization_id", data.organizationId)
|
|
36
|
+
.order("fetched_at", { ascending: false })
|
|
37
|
+
.limit(1)
|
|
38
|
+
.maybeSingle();
|
|
39
|
+
const end = cust?.data?.endDate;
|
|
40
|
+
return { inNetwork, endDate: typeof end === "string" && end.trim() ? end : null };
|
|
41
|
+
});
|
|
@@ -250,6 +250,8 @@ export type FloridayImportPreviewItem = {
|
|
|
250
250
|
name: string;
|
|
251
251
|
action: "create" | "update" | "deactivate";
|
|
252
252
|
customers: number;
|
|
253
|
+
/** lastModifiedDateTime uit Floriday. */
|
|
254
|
+
last_modified_in_floriday?: string | null;
|
|
253
255
|
};
|
|
254
256
|
export type FloridayImportResult = {
|
|
255
257
|
preview: boolean;
|
|
@@ -259,6 +261,7 @@ export type FloridayImportResult = {
|
|
|
259
261
|
deactivated: number;
|
|
260
262
|
membersLinked: number;
|
|
261
263
|
unmatchedOrganizations: string[];
|
|
264
|
+
unmatchedDetails: UnknownFloridayMember[];
|
|
262
265
|
};
|
|
263
266
|
export declare const importFloridayPriceGroups: import("@tanstack/start-client-core").OptionalFetcher<readonly [import("@tanstack/start-client-core").FunctionMiddlewareAfterServer<{}, unknown, undefined, {
|
|
264
267
|
supabase: import("../integrations/supabase/auth-middleware").AuthedSupabaseClient;
|
|
@@ -267,6 +270,45 @@ export declare const importFloridayPriceGroups: import("@tanstack/start-client-c
|
|
|
267
270
|
}, undefined, undefined, undefined>], (input: unknown) => {
|
|
268
271
|
preview: boolean;
|
|
269
272
|
}, Promise<FloridayImportResult>>;
|
|
273
|
+
export type UnknownFloridayMember = {
|
|
274
|
+
organization_id: string;
|
|
275
|
+
name: string;
|
|
276
|
+
commercial_name: string | null;
|
|
277
|
+
city: string | null;
|
|
278
|
+
/** Reden waarom deze klant niet is ingedeeld. */
|
|
279
|
+
reason: string;
|
|
280
|
+
/** Prijsgroepen (Floriday-id + naam) waarin deze organisatie in Floriday zit. */
|
|
281
|
+
groups: {
|
|
282
|
+
external_id: string;
|
|
283
|
+
name: string;
|
|
284
|
+
}[];
|
|
285
|
+
};
|
|
286
|
+
/** Floriday-leden van één prijsgroep die nog geen ERP-klant zijn (live uit de cache, niets vastgelegd). */
|
|
287
|
+
export declare const listUnknownFloridayMembers: import("@tanstack/start-client-core").OptionalFetcher<readonly [import("@tanstack/start-client-core").FunctionMiddlewareAfterServer<{}, unknown, undefined, {
|
|
288
|
+
supabase: import("../integrations/supabase/auth-middleware").AuthedSupabaseClient;
|
|
289
|
+
userId: string;
|
|
290
|
+
claims: import("@supabase/auth-js").JwtPayload;
|
|
291
|
+
}, undefined, undefined, undefined>], (input: unknown) => {
|
|
292
|
+
priceGroupId: string;
|
|
293
|
+
}, Promise<{
|
|
294
|
+
members: UnknownFloridayMember[];
|
|
295
|
+
lastModifiedInFloriday: string | null;
|
|
296
|
+
}>>;
|
|
297
|
+
/**
|
|
298
|
+
* "Toevoegen": maakt van een Floriday-organisatie een ERP-klant (bron Floriday, dus géén
|
|
299
|
+
* Twinfield-debiteur) en deelt die op klant-id in bij de prijsgroep.
|
|
300
|
+
*/
|
|
301
|
+
export declare const addFloridayMemberToPriceGroup: import("@tanstack/start-client-core").OptionalFetcher<readonly [import("@tanstack/start-client-core").FunctionMiddlewareAfterServer<{}, unknown, undefined, {
|
|
302
|
+
supabase: import("../integrations/supabase/auth-middleware").AuthedSupabaseClient;
|
|
303
|
+
userId: string;
|
|
304
|
+
claims: import("@supabase/auth-js").JwtPayload;
|
|
305
|
+
}, undefined, undefined, undefined>], (input: unknown) => {
|
|
306
|
+
organizationId: string;
|
|
307
|
+
priceGroupId: string;
|
|
308
|
+
}, Promise<{
|
|
309
|
+
customerId: string;
|
|
310
|
+
customerKey: string;
|
|
311
|
+
}>>;
|
|
270
312
|
export type PriceGroupItemPrice = {
|
|
271
313
|
trade_item_key: string;
|
|
272
314
|
price_per_piece: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"price-groups-local.functions.d.ts","sourceRoot":"","sources":["../../src/lib/price-groups-local.functions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,QAAA,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgBzB,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,MAAM,MAAM,aAAa,GAAG,eAAe,GAAG;IAC5C,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,uBAAuB;;;;0EAwBhC,CAAC;AAEL,eAAO,MAAM,qBAAqB;;;;8CAER,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoB7B,CAAC;AAEL,eAAO,MAAM,wBAAwB;;;;8CAEX,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgB7B,CAAC;AAEL,eAAO,MAAM,wBAAwB;;;;8CAEX,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAY7B,CAAC;AAEL,eAAO,MAAM,wBAAwB;;;;8CAEX,OAAO;;;;GAQ7B,CAAC;AAEL,eAAO,MAAM,0BAA0B;;;;8CAEb,OAAO;;;;GAO7B,CAAC;AAEL,eAAO,MAAM,oBAAoB;;;;8CAEP,OAAO;;;;;;GAqB7B,CAAC;AAKL,eAAO,MAAM,yBAAyB;;;;8CAEZ,OAAO;;;mBAUuB,MAAM,EAAE;YAAgB;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE;GAU1G,CAAC;AAEL,6EAA6E;AAC7E,eAAO,MAAM,kCAAkC;;;;8CAErB,OAAO;;;iBAgBC,MAAM,GAAG,IAAI;GAC3C,CAAC;AAEL,eAAO,MAAM,wBAAwB;;;;8CAEX,OAAO;;;;;GAyB7B,CAAC;AAML,MAAM,MAAM,yBAAyB,GAAG;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,YAAY,CAAC;IAC3C,SAAS,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"price-groups-local.functions.d.ts","sourceRoot":"","sources":["../../src/lib/price-groups-local.functions.ts"],"names":[],"mappings":"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"}
|
|
@@ -270,6 +270,7 @@ export const importFloridayPriceGroups = createServerFn({ method: "POST" })
|
|
|
270
270
|
}
|
|
271
271
|
const items = [];
|
|
272
272
|
const unmatched = new Set();
|
|
273
|
+
const unmatchedGroups = new Map();
|
|
273
274
|
const seen = new Set();
|
|
274
275
|
let created = 0;
|
|
275
276
|
let updated = 0;
|
|
@@ -321,6 +322,7 @@ export const importFloridayPriceGroups = createServerFn({ method: "POST" })
|
|
|
321
322
|
name: payload.name,
|
|
322
323
|
action: current ? "update" : "create",
|
|
323
324
|
customers: customerOrgIds.length,
|
|
325
|
+
last_modified_in_floriday: d.lastModifiedDateTime ?? null,
|
|
324
326
|
});
|
|
325
327
|
let groupId = current?.id ?? null;
|
|
326
328
|
if (current) {
|
|
@@ -350,8 +352,12 @@ export const importFloridayPriceGroups = createServerFn({ method: "POST" })
|
|
|
350
352
|
const key = orgToKey.get(orgId);
|
|
351
353
|
if (key)
|
|
352
354
|
keys.push(key);
|
|
353
|
-
else
|
|
355
|
+
else {
|
|
354
356
|
unmatched.add(orgId);
|
|
357
|
+
const list = unmatchedGroups.get(orgId) ?? [];
|
|
358
|
+
list.push({ external_id: externalId, name: payload.name });
|
|
359
|
+
unmatchedGroups.set(orgId, list);
|
|
360
|
+
}
|
|
355
361
|
}
|
|
356
362
|
membersLinked += keys.length;
|
|
357
363
|
if (!data.preview && groupId) {
|
|
@@ -379,6 +385,7 @@ export const importFloridayPriceGroups = createServerFn({ method: "POST" })
|
|
|
379
385
|
await sb.from("customer_price_groups").update({ is_active: false }).eq("id", row.id);
|
|
380
386
|
}
|
|
381
387
|
}
|
|
388
|
+
const unmatchedDetails = await describeUnknownOrganizations(sb, Array.from(unmatched), unmatchedGroups);
|
|
382
389
|
return {
|
|
383
390
|
preview: data.preview,
|
|
384
391
|
items,
|
|
@@ -387,8 +394,120 @@ export const importFloridayPriceGroups = createServerFn({ method: "POST" })
|
|
|
387
394
|
deactivated,
|
|
388
395
|
membersLinked,
|
|
389
396
|
unmatchedOrganizations: Array.from(unmatched),
|
|
397
|
+
unmatchedDetails,
|
|
398
|
+
};
|
|
399
|
+
});
|
|
400
|
+
/** Zoekt namen op in de Floriday-cache (alleen lezen, op organisatie-id). */
|
|
401
|
+
async function describeUnknownOrganizations(sb, orgIds, groupsByOrg) {
|
|
402
|
+
if (orgIds.length === 0)
|
|
403
|
+
return [];
|
|
404
|
+
const info = new Map();
|
|
405
|
+
for (let i = 0; i < orgIds.length; i += 200) {
|
|
406
|
+
const { data: rows } = await sb
|
|
407
|
+
.from("floriday_customers_cache")
|
|
408
|
+
.select("organization_id, name, data, fetched_at")
|
|
409
|
+
.in("organization_id", orgIds.slice(i, i + 200))
|
|
410
|
+
.order("fetched_at", { ascending: false });
|
|
411
|
+
for (const r of rows ?? [])
|
|
412
|
+
if (!info.has(r.organization_id))
|
|
413
|
+
info.set(r.organization_id, r);
|
|
414
|
+
}
|
|
415
|
+
return orgIds.map((org) => {
|
|
416
|
+
const r = info.get(org);
|
|
417
|
+
const d = (r?.data ?? {});
|
|
418
|
+
const addr = d.physicalAddress ?? d.mailingAddress ?? {};
|
|
419
|
+
const name = (d.name || r?.name || d.commercialName || "").toString().trim();
|
|
420
|
+
const commercial = (d.commercialName ?? "").toString().trim();
|
|
421
|
+
return {
|
|
422
|
+
organization_id: org,
|
|
423
|
+
name: name || `Floriday-organisatie ${org.slice(0, 8)}`,
|
|
424
|
+
commercial_name: commercial && commercial !== name ? commercial : null,
|
|
425
|
+
city: addr.city ?? null,
|
|
426
|
+
reason: r ? "Nog geen klant in het ERP" : "Niet gevonden in de Floriday-klantgegevens",
|
|
427
|
+
groups: groupsByOrg.get(org) ?? [],
|
|
428
|
+
};
|
|
429
|
+
}).sort((a, b) => a.name.localeCompare(b.name));
|
|
430
|
+
}
|
|
431
|
+
/** Floriday-leden van één prijsgroep die nog geen ERP-klant zijn (live uit de cache, niets vastgelegd). */
|
|
432
|
+
export const listUnknownFloridayMembers = createServerFn({ method: "GET" })
|
|
433
|
+
.middleware([requireSupabaseAuth])
|
|
434
|
+
.inputValidator((input) => z.object({ priceGroupId: z.string().uuid() }).parse(input))
|
|
435
|
+
.handler(async ({ data, context }) => {
|
|
436
|
+
const sb = context.supabase;
|
|
437
|
+
const { data: group, error } = await sb
|
|
438
|
+
.from("customer_price_groups")
|
|
439
|
+
.select("id, name, source, external_id")
|
|
440
|
+
.eq("id", data.priceGroupId)
|
|
441
|
+
.maybeSingle();
|
|
442
|
+
if (error)
|
|
443
|
+
throw new Error(error.message);
|
|
444
|
+
if (!group || group.source !== "floriday" || !group.external_id) {
|
|
445
|
+
return { members: [], lastModifiedInFloriday: null };
|
|
446
|
+
}
|
|
447
|
+
const { data: cache } = await sb
|
|
448
|
+
.from("floriday_price_groups_cache")
|
|
449
|
+
.select("data, fetched_at")
|
|
450
|
+
.eq("floriday_id", group.external_id)
|
|
451
|
+
.order("fetched_at", { ascending: false })
|
|
452
|
+
.limit(1)
|
|
453
|
+
.maybeSingle();
|
|
454
|
+
const d = (cache?.data ?? {});
|
|
455
|
+
const orgIds = (Array.isArray(d.customers) ? d.customers : []).filter((c) => typeof c === "string");
|
|
456
|
+
const known = await knownFloridayOrgs(sb, orgIds);
|
|
457
|
+
const unknown = orgIds.filter((o) => !known.has(o));
|
|
458
|
+
const groups = new Map(unknown.map((o) => [o, [{ external_id: String(group.external_id), name: String(group.name) }]]));
|
|
459
|
+
return {
|
|
460
|
+
members: await describeUnknownOrganizations(sb, unknown, groups),
|
|
461
|
+
lastModifiedInFloriday: d.lastModifiedDateTime ?? null,
|
|
390
462
|
};
|
|
391
463
|
});
|
|
464
|
+
/** Organisatie-id's die al als ERP-klant bestaan (op id, nooit op naam). */
|
|
465
|
+
async function knownFloridayOrgs(sb, orgIds) {
|
|
466
|
+
const out = new Set();
|
|
467
|
+
for (let i = 0; i < orgIds.length; i += 200) {
|
|
468
|
+
const { data: rows } = await sb
|
|
469
|
+
.from("customers")
|
|
470
|
+
.select("floriday_organization_id")
|
|
471
|
+
.in("floriday_organization_id", orgIds.slice(i, i + 200));
|
|
472
|
+
for (const r of rows ?? [])
|
|
473
|
+
if (r.floriday_organization_id)
|
|
474
|
+
out.add(String(r.floriday_organization_id));
|
|
475
|
+
}
|
|
476
|
+
return out;
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* "Toevoegen": maakt van een Floriday-organisatie een ERP-klant (bron Floriday, dus géén
|
|
480
|
+
* Twinfield-debiteur) en deelt die op klant-id in bij de prijsgroep.
|
|
481
|
+
*/
|
|
482
|
+
export const addFloridayMemberToPriceGroup = createServerFn({ method: "POST" })
|
|
483
|
+
.middleware([requireSupabaseAuth])
|
|
484
|
+
.inputValidator((input) => z.object({ organizationId: z.string().min(1).max(64), priceGroupId: z.string().uuid() }).parse(input))
|
|
485
|
+
.handler(async ({ data, context }) => {
|
|
486
|
+
const sb = context.supabase;
|
|
487
|
+
const { data: customerId, error } = await sb.rpc("promote_floriday_customer", { _org_id: data.organizationId });
|
|
488
|
+
if (error)
|
|
489
|
+
throw new Error(error.message);
|
|
490
|
+
// Debiteur alleen na bewuste bevestiging: kenmerk uit, zodat ook latere wijzigingen niets versturen.
|
|
491
|
+
await sb.from("customers").update({ twinfield_create_on_insert: false }).eq("id", customerId).is("twinfield_code", null);
|
|
492
|
+
// Klanten met een Floriday-organisatie-id krijgen in het overzicht altijd de sleutel fd:<org-id>.
|
|
493
|
+
const customerKey = `fd:${data.organizationId}`;
|
|
494
|
+
const { data: existing } = await sb
|
|
495
|
+
.from("customer_price_group_members")
|
|
496
|
+
.select("id")
|
|
497
|
+
.eq("price_group_id", data.priceGroupId)
|
|
498
|
+
.eq("customer_key", customerKey)
|
|
499
|
+
.maybeSingle();
|
|
500
|
+
if (!existing) {
|
|
501
|
+
const { error: insErr } = await sb.from("customer_price_group_members").insert({
|
|
502
|
+
price_group_id: data.priceGroupId,
|
|
503
|
+
customer_key: customerKey,
|
|
504
|
+
owner_id: context.userId,
|
|
505
|
+
});
|
|
506
|
+
if (insErr)
|
|
507
|
+
throw new Error(insErr.message);
|
|
508
|
+
}
|
|
509
|
+
return { customerId: String(customerId), customerKey };
|
|
510
|
+
});
|
|
392
511
|
export const listPriceGroupItemPrices = createServerFn({ method: "POST" })
|
|
393
512
|
.middleware([requireSupabaseAuth])
|
|
394
513
|
.inputValidator((input) => z.object({ priceGroupId: z.string().uuid() }).parse(input))
|
|
@@ -107,6 +107,7 @@ export declare const adoptTwinfieldCustomer: import("@tanstack/start-client-core
|
|
|
107
107
|
values: {
|
|
108
108
|
is_active: boolean;
|
|
109
109
|
force: boolean;
|
|
110
|
+
twinfield_create: boolean;
|
|
110
111
|
credit_limit: number;
|
|
111
112
|
send_reminder: "no" | "file" | "file_email";
|
|
112
113
|
payment_spec_method: "email" | "file";
|
|
@@ -243,6 +244,7 @@ export declare const adoptTwinfieldCustomer: import("@tanstack/start-client-core
|
|
|
243
244
|
twinfield_base_snapshot: import("../integrations/supabase/types").Json | null;
|
|
244
245
|
twinfield_base_version: number | null;
|
|
245
246
|
twinfield_code: string | null;
|
|
247
|
+
twinfield_create_on_insert: boolean;
|
|
246
248
|
twinfield_last_hash: string | null;
|
|
247
249
|
twinfield_missing_since: string | null;
|
|
248
250
|
twinfield_present: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"twinfield-adopt.functions.d.ts","sourceRoot":"","sources":["../../src/lib/twinfield-adopt.functions.ts"],"names":[],"mappings":"AAOA;;;;;;;GAOG;AAEH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oFAAoF;IACpF,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,GAAG,IAAI,CAAC;IACnD,WAAW,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5B,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,wBAAwB,EAAE,MAAM,CAAC;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,yEAAyE;IACzE,cAAc,EAAE,OAAO,CAAC;CACzB,CAAC;AAwEF;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,gBAAgB,CAkExE;AAgDD;;;;GAIG;AACH,eAAO,MAAM,wBAAwB;;;;8CAEX;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE;;;;aAYjB,MAAM;;;;;;;;;GAelD,CAAC;AAQL;;;GAGG;AACH,eAAO,MAAM,sBAAsB;;;;8CAET;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE
|
|
1
|
+
{"version":3,"file":"twinfield-adopt.functions.d.ts","sourceRoot":"","sources":["../../src/lib/twinfield-adopt.functions.ts"],"names":[],"mappings":"AAOA;;;;;;;GAOG;AAEH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oFAAoF;IACpF,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,GAAG,IAAI,CAAC;IACnD,WAAW,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5B,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,wBAAwB,EAAE,MAAM,CAAC;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,yEAAyE;IACzE,cAAc,EAAE,OAAO,CAAC;CACzB,CAAC;AAwEF;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,gBAAgB,CAkExE;AAgDD;;;;GAIG;AACH,eAAO,MAAM,wBAAwB;;;;8CAEX;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE;;;;aAYjB,MAAM;;;;;;;;;GAelD,CAAC;AAQL;;;GAGG;AACH,eAAO,MAAM,sBAAsB;;;;8CAET;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsF9E,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare function normalizeVat(v: string | null | undefined): string;
|
|
2
|
+
export type VatCheck = {
|
|
3
|
+
status: "empty";
|
|
4
|
+
} | {
|
|
5
|
+
status: "unchecked";
|
|
6
|
+
} | {
|
|
7
|
+
status: "valid";
|
|
8
|
+
} | {
|
|
9
|
+
status: "invalid";
|
|
10
|
+
message: string;
|
|
11
|
+
example?: string;
|
|
12
|
+
};
|
|
13
|
+
/** @param iso2 ISO-landcode van de klant (gebruik toIsoCountry voor een landnaam). */
|
|
14
|
+
export declare function checkVatFormat(vat: string | null | undefined, iso2: string | null | undefined): VatCheck;
|
|
15
|
+
/** Herkent een Twinfield-fout die over het btw-nummer (field4) gaat. */
|
|
16
|
+
export declare function isTwinfieldVatError(msg: string | null | undefined): boolean;
|
|
17
|
+
//# sourceMappingURL=vat-format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vat-format.d.ts","sourceRoot":"","sources":["../../src/lib/vat-format.ts"],"names":[],"mappings":"AAyCA,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAEjE;AAED,MAAM,MAAM,QAAQ,GAChB;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,GACnB;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,GACvB;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,GACnB;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7D,sFAAsF;AACtF,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,QAAQ,CAaxG;AAED,wEAAwE;AACxE,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAE3E"}
|