@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.
Files changed (48) hide show
  1. package/dist-lib/components/klanten/BewerkKlant.d.ts.map +1 -1
  2. package/dist-lib/components/klanten/BewerkKlant.js +1 -1
  3. package/dist-lib/components/klanten/CustomerAnalyticsTab.d.ts.map +1 -1
  4. package/dist-lib/components/klanten/CustomerAnalyticsTab.js +2 -2
  5. package/dist-lib/components/klanten/FloridayNetworkStatus.d.ts +5 -0
  6. package/dist-lib/components/klanten/FloridayNetworkStatus.d.ts.map +1 -0
  7. package/dist-lib/components/klanten/FloridayNetworkStatus.js +18 -0
  8. package/dist-lib/components/klanten/KlantDetailLayout.d.ts +2 -0
  9. package/dist-lib/components/klanten/KlantDetailLayout.d.ts.map +1 -1
  10. package/dist-lib/components/klanten/KlantDetailLayout.js +6 -1
  11. package/dist-lib/components/klanten/KlantFormulier.d.ts +3 -1
  12. package/dist-lib/components/klanten/KlantFormulier.d.ts.map +1 -1
  13. package/dist-lib/components/klanten/KlantFormulier.js +16 -4
  14. package/dist-lib/components/klanten/KlantenOverzicht.d.ts.map +1 -1
  15. package/dist-lib/components/klanten/KlantenOverzicht.js +6 -5
  16. package/dist-lib/components/klanten/NetwerkPagina.d.ts.map +1 -1
  17. package/dist-lib/components/klanten/NetwerkPagina.js +9 -5
  18. package/dist-lib/components/klanten/NieuweKlant.d.ts.map +1 -1
  19. package/dist-lib/components/klanten/NieuweKlant.js +10 -7
  20. package/dist-lib/components/klanten/pricegroups/CustomerPickerDialog.d.ts.map +1 -1
  21. package/dist-lib/components/klanten/pricegroups/CustomerPickerDialog.js +10 -2
  22. package/dist-lib/components/klanten/pricegroups/PriceGroupsPage.d.ts.map +1 -1
  23. package/dist-lib/components/klanten/pricegroups/PriceGroupsPage.js +4 -7
  24. package/dist-lib/components/klanten/pricegroups/UnknownFloridayMembers.d.ts +11 -0
  25. package/dist-lib/components/klanten/pricegroups/UnknownFloridayMembers.d.ts.map +1 -0
  26. package/dist-lib/components/klanten/pricegroups/UnknownFloridayMembers.js +43 -0
  27. package/dist-lib/index.js +1 -1
  28. package/dist-lib/integrations/supabase/types.d.ts +1470 -2
  29. package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
  30. package/dist-lib/integrations/supabase/types.js +1 -0
  31. package/dist-lib/lib/customer-schemas.d.ts +2 -0
  32. package/dist-lib/lib/customer-schemas.d.ts.map +1 -1
  33. package/dist-lib/lib/customer-schemas.js +2 -0
  34. package/dist-lib/lib/customers.functions.d.ts +37 -0
  35. package/dist-lib/lib/customers.functions.d.ts.map +1 -1
  36. package/dist-lib/lib/customers.functions.js +49 -4
  37. package/dist-lib/lib/floriday-network-status.functions.d.ts +18 -0
  38. package/dist-lib/lib/floriday-network-status.functions.d.ts.map +1 -0
  39. package/dist-lib/lib/floriday-network-status.functions.js +41 -0
  40. package/dist-lib/lib/price-groups-local.functions.d.ts +42 -0
  41. package/dist-lib/lib/price-groups-local.functions.d.ts.map +1 -1
  42. package/dist-lib/lib/price-groups-local.functions.js +120 -1
  43. package/dist-lib/lib/twinfield-adopt.functions.d.ts +2 -0
  44. package/dist-lib/lib/twinfield-adopt.functions.d.ts.map +1 -1
  45. package/dist-lib/lib/vat-format.d.ts +17 -0
  46. package/dist-lib/lib/vat-format.d.ts.map +1 -0
  47. package/dist-lib/lib/vat-format.js +64 -0
  48. package/package.json +5 -5
@@ -39,6 +39,7 @@ export const Constants = {
39
39
  "veilingbon",
40
40
  "afleverbrief",
41
41
  "veilingbrief",
42
+ "traysticker",
42
43
  ],
43
44
  doc_orientation: ["portrait", "landscape"],
44
45
  exact_env: ["staging", "live"],
@@ -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;AAuQxB,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"}
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;AAkCF,eAAO,MAAM,qBAAqB;;;;8CAER;IAAE,KAAK,EAAE,cAAc,CAAA;CAAE,KACiD;IAC9F,KAAK,EAAE,cAAc,CAAC;CACvB;;;;;;GAaD,CAAC;AAGL,eAAO,MAAM,aAAa;;;;8CAEA,gBAAgB;;;;;;;;;;GAiDtC,CAAC;AAEL,eAAO,MAAM,WAAW;;;;8CAEE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8EpC,CAAC;AAwDL,eAAO,MAAM,cAAc;;;;8CAED,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YApDlB,MAAM;sBAAgB,MAAM;gBAAU,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsGnE,CAAC;AAEL,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAmCS,MAAM;aAAO,MAAM;gBAAU,MAAM;;GAwDnE,CAAC;AAEL,eAAO,MAAM,cAAc;;;;8CAED;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE;;;;GAQpC,CAAC;AAEL,eAAO,MAAM,mBAAmB;;;;8CAGpB;IACN,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+ED,CAAC;AAEL,eAAO,MAAM,mBAAmB;;;;;aAQQ,MAAM,EAAE;GAO5C,CAAC;AAEL,eAAO,MAAM,mBAAmB;;;;8CAEN,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAM9B,MAAM;aACN,MAAM;YACP,MAAM;YACN,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;GAqCtE,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({ ...buildCustomerInsert(data, defaults), customer_number: number.value })
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
- .limit(data.limit);
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
- truncated: (count ?? 0) > organizations.length,
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;CACnB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,yBAAyB,EAAE,CAAC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,sBAAsB,EAAE,MAAM,EAAE,CAAC;CAClC,CAAC;AA2BF,eAAO,MAAM,yBAAyB;;;;8CAEZ,OAAO;;iCA6J7B,CAAC;AAML,MAAM,MAAM,mBAAmB,GAAG;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,wBAAwB;;;;8CAEX,OAAO;;;YAGuB,mBAAmB,EAAE;GAazE,CAAC;AAEL,eAAO,MAAM,sBAAsB;;;;8CAET,OAAO;;;;;;;;;;;GA+C7B,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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsF9E,CAAC"}
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"}