@flowselections/floriday-afhandeling-module 1.0.13 → 1.0.15
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/afhandeling/AutoProcessStatus.d.ts +12 -0
- package/dist-lib/components/afhandeling/AutoProcessStatus.d.ts.map +1 -0
- package/dist-lib/components/afhandeling/AutoProcessStatus.js +103 -0
- package/dist-lib/components/afhandeling/ControleLijstPrint.d.ts +3 -1
- package/dist-lib/components/afhandeling/ControleLijstPrint.d.ts.map +1 -1
- package/dist-lib/components/afhandeling/ControleLijstPrint.js +41 -63
- package/dist-lib/components/afhandeling/DagDetailDialog.d.ts.map +1 -1
- package/dist-lib/components/afhandeling/DagDetailDialog.js +96 -4
- package/dist-lib/components/afhandeling/LeveringenPage.js +1 -1
- package/dist-lib/components/afhandeling/VervoerdersPage.d.ts.map +1 -1
- package/dist-lib/components/afhandeling/VervoerdersPage.js +2 -1
- package/dist-lib/components/afhandeling/WeekAgendaView.d.ts +3 -1
- package/dist-lib/components/afhandeling/WeekAgendaView.d.ts.map +1 -1
- package/dist-lib/components/afhandeling/WeekAgendaView.js +58 -17
- package/dist-lib/components/pickstation/PakbonTemplate.d.ts +2 -1
- package/dist-lib/components/pickstation/PakbonTemplate.d.ts.map +1 -1
- package/dist-lib/components/pickstation/PakbonTemplate.js +20 -17
- package/dist-lib/components/pickstation/PickstationPage.d.ts.map +1 -1
- package/dist-lib/components/pickstation/PickstationPage.js +57 -8
- package/dist-lib/components/settings/AfhandelingSettingsCard.d.ts.map +1 -1
- package/dist-lib/components/settings/AfhandelingSettingsCard.js +14 -2
- package/dist-lib/hooks/useOrderPlanning.d.ts.map +1 -1
- package/dist-lib/hooks/useOrderPlanning.js +28 -11
- package/dist-lib/index.d.ts +3 -0
- package/dist-lib/index.d.ts.map +1 -1
- package/dist-lib/index.js +3 -0
- package/dist-lib/integrations/supabase/auth-middleware.d.ts +605 -4
- package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.d.ts +605 -4
- package/dist-lib/integrations/supabase/client.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.server.d.ts +605 -4
- package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +613 -4
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/afhandelingSettings.functions.d.ts +1222 -8
- package/dist-lib/lib/afhandelingSettings.functions.d.ts.map +1 -1
- package/dist-lib/lib/afhandelingSettings.functions.js +28 -1
- package/dist-lib/lib/carrierPlanning.d.ts +25 -0
- package/dist-lib/lib/carrierPlanning.d.ts.map +1 -0
- package/dist-lib/lib/carrierPlanning.js +65 -0
- package/dist-lib/lib/carrierSignupMail.server.d.ts +0 -2
- package/dist-lib/lib/carrierSignupMail.server.d.ts.map +1 -1
- package/dist-lib/lib/carrierSignupMail.server.js +53 -216
- package/dist-lib/lib/carriers.functions.d.ts +3025 -20
- package/dist-lib/lib/carriers.functions.d.ts.map +1 -1
- package/dist-lib/lib/carriers.functions.js +5 -0
- package/dist-lib/lib/cartAssignments.functions.d.ts +3025 -20
- package/dist-lib/lib/cartAssignments.functions.d.ts.map +1 -1
- package/dist-lib/lib/cartControl.functions.d.ts +6050 -40
- package/dist-lib/lib/cartControl.functions.d.ts.map +1 -1
- package/dist-lib/lib/cartControl.functions.js +1 -1
- package/dist-lib/lib/cartRescheduling.d.ts.map +1 -1
- package/dist-lib/lib/cartRescheduling.js +8 -6
- package/dist-lib/lib/countries.d.ts +2 -0
- package/dist-lib/lib/countries.d.ts.map +1 -1
- package/dist-lib/lib/countries.js +51 -0
- package/dist-lib/lib/deliveryNotePrint.d.ts +26 -0
- package/dist-lib/lib/deliveryNotePrint.d.ts.map +1 -0
- package/dist-lib/lib/deliveryNotePrint.js +172 -0
- package/dist-lib/lib/floriday.functions.d.ts +613 -4
- package/dist-lib/lib/floriday.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday.functions.js +126 -8
- package/dist-lib/lib/floridayAutoProcess.d.ts +30 -0
- package/dist-lib/lib/floridayAutoProcess.d.ts.map +1 -0
- package/dist-lib/lib/floridayAutoProcess.js +70 -0
- package/dist-lib/lib/pickstationI18n.d.ts +46 -0
- package/dist-lib/lib/pickstationI18n.d.ts.map +1 -1
- package/dist-lib/lib/pickstationI18n.js +251 -0
- package/dist-lib/lib/pickstationOrders.server.d.ts.map +1 -1
- package/dist-lib/lib/pickstationOrders.server.js +55 -19
- package/dist-lib/lib/planning.d.ts +34 -0
- package/dist-lib/lib/planning.d.ts.map +1 -1
- package/dist-lib/lib/planning.js +84 -0
- package/package.json +2 -2
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type PickupMoment } from "./planning";
|
|
2
|
+
export interface CarrierPlanningInfo {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
is_default?: boolean | null;
|
|
6
|
+
sort_order?: number | null;
|
|
7
|
+
service_countries?: string[] | null;
|
|
8
|
+
service_provinces?: string[] | null;
|
|
9
|
+
service_cities?: string[] | null;
|
|
10
|
+
pickup_moments?: PickupMoment[] | unknown;
|
|
11
|
+
pickup_weekdays?: number[] | null;
|
|
12
|
+
delivery_weekdays?: number[] | null;
|
|
13
|
+
}
|
|
14
|
+
export interface CarrierOrderTarget {
|
|
15
|
+
carrierId?: string | null;
|
|
16
|
+
country?: string | null;
|
|
17
|
+
province?: string | null;
|
|
18
|
+
city?: string | null;
|
|
19
|
+
}
|
|
20
|
+
export declare function sanitizeWeekdays(input: unknown): number[];
|
|
21
|
+
export declare function normalizePickupMoments(raw: unknown): PickupMoment[];
|
|
22
|
+
export declare function carrierLeadDaysFromMoments(raw: unknown): number;
|
|
23
|
+
export declare function normalizePlanningCarriers<T extends CarrierPlanningInfo>(carriers: T[]): T[];
|
|
24
|
+
export declare function selectCarrierForTarget<T extends CarrierPlanningInfo>(carriers: T[], target: CarrierOrderTarget): T | null;
|
|
25
|
+
//# sourceMappingURL=carrierPlanning.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"carrierPlanning.d.ts","sourceRoot":"","sources":["../../src/lib/carrierPlanning.ts"],"names":[],"mappings":"AAEA,OAAO,EAAyB,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAItE,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACpC,iBAAiB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACpC,cAAc,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACjC,cAAc,CAAC,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC;IAC1C,eAAe,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAClC,iBAAiB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAUzD;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,YAAY,EAAE,CAanE;AAED,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAK/D;AAED,wBAAgB,yBAAyB,CAAC,CAAC,SAAS,mBAAmB,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAU3F;AAED,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,mBAAmB,EAClE,QAAQ,EAAE,CAAC,EAAE,EACb,MAAM,EAAE,kBAAkB,GACzB,CAAC,GAAG,IAAI,CAiCV"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { matchesServiceArea } from "./geo/euServiceAreas";
|
|
2
|
+
import { countryCode } from "./countries";
|
|
3
|
+
import { DEFAULT_PICKUP_MOMENT } from "./planning";
|
|
4
|
+
const DEFAULT_WEEKDAYS = [1, 2, 3, 4, 5];
|
|
5
|
+
export function sanitizeWeekdays(input) {
|
|
6
|
+
if (!Array.isArray(input))
|
|
7
|
+
return DEFAULT_WEEKDAYS;
|
|
8
|
+
const clean = Array.from(new Set(input
|
|
9
|
+
.map((n) => Math.floor(Number(n)))
|
|
10
|
+
.filter((n) => Number.isFinite(n) && n >= 1 && n <= 7))).sort((a, b) => a - b);
|
|
11
|
+
return clean.length > 0 ? clean : DEFAULT_WEEKDAYS;
|
|
12
|
+
}
|
|
13
|
+
export function normalizePickupMoments(raw) {
|
|
14
|
+
if (!Array.isArray(raw) || raw.length === 0)
|
|
15
|
+
return [DEFAULT_PICKUP_MOMENT];
|
|
16
|
+
return raw.map((m) => {
|
|
17
|
+
const r = (m ?? {});
|
|
18
|
+
return {
|
|
19
|
+
signup_days: Math.max(0, Math.floor(Number(r.signup_days ?? DEFAULT_PICKUP_MOMENT.signup_days) || 0)),
|
|
20
|
+
signup_time: String(r.signup_time ?? DEFAULT_PICKUP_MOMENT.signup_time),
|
|
21
|
+
pickup_days: Math.max(0, Math.floor(Number(r.pickup_days ?? DEFAULT_PICKUP_MOMENT.pickup_days) || 0)),
|
|
22
|
+
pickup_time: String(r.pickup_time ?? DEFAULT_PICKUP_MOMENT.pickup_time),
|
|
23
|
+
delivery_days: Math.max(0, Math.floor(Number(r.delivery_days ?? DEFAULT_PICKUP_MOMENT.delivery_days) || 0)),
|
|
24
|
+
delivery_time: String(r.delivery_time ?? DEFAULT_PICKUP_MOMENT.delivery_time),
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
export function carrierLeadDaysFromMoments(raw) {
|
|
29
|
+
return normalizePickupMoments(raw).reduce((max, moment) => Math.max(max, moment.signup_days, moment.pickup_days, moment.delivery_days), 0);
|
|
30
|
+
}
|
|
31
|
+
export function normalizePlanningCarriers(carriers) {
|
|
32
|
+
return carriers.map((carrier) => ({
|
|
33
|
+
...carrier,
|
|
34
|
+
service_countries: carrier.service_countries ?? [],
|
|
35
|
+
service_provinces: carrier.service_provinces ?? [],
|
|
36
|
+
service_cities: carrier.service_cities ?? [],
|
|
37
|
+
pickup_moments: normalizePickupMoments(carrier.pickup_moments),
|
|
38
|
+
pickup_weekdays: sanitizeWeekdays(carrier.pickup_weekdays),
|
|
39
|
+
delivery_weekdays: sanitizeWeekdays(carrier.delivery_weekdays),
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
export function selectCarrierForTarget(carriers, target) {
|
|
43
|
+
const normalized = normalizePlanningCarriers(carriers);
|
|
44
|
+
const sorted = [...normalized].sort((a, b) => (a.sort_order ?? 9999) - (b.sort_order ?? 9999));
|
|
45
|
+
if (target.carrierId) {
|
|
46
|
+
const explicit = sorted.find((carrier) => carrier.id === target.carrierId);
|
|
47
|
+
if (explicit)
|
|
48
|
+
return explicit;
|
|
49
|
+
}
|
|
50
|
+
const matchTarget = {
|
|
51
|
+
country: countryCode(target.country) ?? target.country ?? null,
|
|
52
|
+
province: target.province ?? null,
|
|
53
|
+
city: target.city ?? null,
|
|
54
|
+
};
|
|
55
|
+
for (const carrier of sorted) {
|
|
56
|
+
if (matchesServiceArea({
|
|
57
|
+
countries: carrier.service_countries ?? [],
|
|
58
|
+
provinces: carrier.service_provinces ?? [],
|
|
59
|
+
cities: carrier.service_cities ?? [],
|
|
60
|
+
}, matchTarget)) {
|
|
61
|
+
return carrier;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return sorted.find((carrier) => carrier.is_default) ?? sorted[0] ?? null;
|
|
65
|
+
}
|
|
@@ -37,7 +37,6 @@ export interface SignupMailOrderRow {
|
|
|
37
37
|
customerName: string;
|
|
38
38
|
deliveryType: string;
|
|
39
39
|
cartCount: number | null;
|
|
40
|
-
plantCount: number | null;
|
|
41
40
|
}
|
|
42
41
|
export interface SignupMailInput {
|
|
43
42
|
carrierName: string;
|
|
@@ -51,6 +50,5 @@ export declare function buildCarrierSignupMail(input: SignupMailInput): {
|
|
|
51
50
|
html: string;
|
|
52
51
|
text: string;
|
|
53
52
|
totalCarts: number;
|
|
54
|
-
totalPlants: number;
|
|
55
53
|
};
|
|
56
54
|
//# sourceMappingURL=carrierSignupMail.server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"carrierSignupMail.server.d.ts","sourceRoot":"","sources":["../../src/lib/carrierSignupMail.server.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,gBAAgB,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC5C,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC/B;AAGD,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"carrierSignupMail.server.d.ts","sourceRoot":"","sources":["../../src/lib/carrierSignupMail.server.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,gBAAgB,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC5C,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAC/B;AAGD,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,IAAI,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,IAAI,CAAC;IACrB,MAAM,EAAE,qBAAqB,EAAE,CAAC;CACjC;AAyBD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,eAAe,GAAG;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB,CAuDA"}
|
|
@@ -1,229 +1,66 @@
|
|
|
1
1
|
// Server-only HTML/text builder for carrier signup digest e-mails.
|
|
2
|
-
function
|
|
3
|
-
return
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
});
|
|
9
|
-
}
|
|
10
|
-
function fmtDateTime(d) {
|
|
11
|
-
return d.toLocaleString("nl-NL", {
|
|
12
|
-
weekday: "short",
|
|
13
|
-
day: "2-digit",
|
|
14
|
-
month: "short",
|
|
15
|
-
hour: "2-digit",
|
|
16
|
-
minute: "2-digit",
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
function fmtIsoDate(s) {
|
|
20
|
-
if (!s)
|
|
21
|
-
return "Onbekend";
|
|
22
|
-
const d = new Date(s);
|
|
23
|
-
if (Number.isNaN(d.getTime()))
|
|
24
|
-
return s;
|
|
25
|
-
return d.toLocaleDateString("nl-NL", { day: "2-digit", month: "long", year: "numeric" });
|
|
2
|
+
function escape(s) {
|
|
3
|
+
return String(s)
|
|
4
|
+
.replace(/&/g, "&")
|
|
5
|
+
.replace(/</g, "<")
|
|
6
|
+
.replace(/>/g, ">")
|
|
7
|
+
.replace(/"/g, """);
|
|
26
8
|
}
|
|
27
|
-
function
|
|
28
|
-
const
|
|
29
|
-
|
|
9
|
+
function fmtDdMmYyyy(d) {
|
|
10
|
+
const dd = String(d.getDate()).padStart(2, "0");
|
|
11
|
+
const mm = String(d.getMonth() + 1).padStart(2, "0");
|
|
12
|
+
const yy = d.getFullYear();
|
|
13
|
+
return `${dd}-${mm}-${yy}`;
|
|
30
14
|
}
|
|
31
|
-
function
|
|
15
|
+
function formatFullAddress(a) {
|
|
32
16
|
if (!a)
|
|
33
|
-
return
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
lines.push(`<strong>${escape(a.name)}</strong>`);
|
|
39
|
-
if (streetLine)
|
|
40
|
-
lines.push(escape(streetLine));
|
|
41
|
-
if (cityLine)
|
|
42
|
-
lines.push(escape(cityLine));
|
|
43
|
-
if (a.province && a.province.trim())
|
|
44
|
-
lines.push(escape(a.province));
|
|
45
|
-
if (a.country && a.country.trim())
|
|
46
|
-
lines.push(escape(a.country));
|
|
47
|
-
if (lines.length === 0)
|
|
48
|
-
return `<div style="color:#6b7280;">Onbekend</div>`;
|
|
49
|
-
return lines.map((l) => `<div>${l}</div>`).join("");
|
|
50
|
-
}
|
|
51
|
-
function renderDefinitionList(rows) {
|
|
52
|
-
return `<table style="border-collapse:collapse;font-size:13px;width:100%;">${rows
|
|
53
|
-
.map((r) => `
|
|
54
|
-
<tr>
|
|
55
|
-
<td style="padding:2px 12px 2px 0;color:#6b7280;width:140px;vertical-align:top;">${escape(r.label)}</td>
|
|
56
|
-
<td style="padding:2px 0;vertical-align:top;">${r.value}</td>
|
|
57
|
-
</tr>`)
|
|
58
|
-
.join("")}</table>`;
|
|
59
|
-
}
|
|
60
|
-
function renderItemsTable(items) {
|
|
61
|
-
if (!items || items.length === 0) {
|
|
62
|
-
return `<div style="color:#6b7280;font-size:13px;">Geen artikelen geregistreerd.</div>`;
|
|
63
|
-
}
|
|
64
|
-
const rows = items
|
|
65
|
-
.map((it) => `
|
|
66
|
-
<tr>
|
|
67
|
-
<td style="padding:6px 8px;border-bottom:1px solid #e5e7eb;">${escape(it.name)}</td>
|
|
68
|
-
<td style="padding:6px 8px;border-bottom:1px solid #e5e7eb;text-align:right;">${it.quantity ?? "—"}</td>
|
|
69
|
-
<td style="padding:6px 8px;border-bottom:1px solid #e5e7eb;">${escape(it.unit ?? "")}</td>
|
|
70
|
-
</tr>`)
|
|
71
|
-
.join("");
|
|
72
|
-
return `<table style="border-collapse:collapse;width:100%;font-size:13px;">
|
|
73
|
-
<thead><tr style="background:#f3f4f6;text-align:left;">
|
|
74
|
-
<th style="padding:6px 8px;">Artikel</th>
|
|
75
|
-
<th style="padding:6px 8px;text-align:right;width:90px;">Aantal</th>
|
|
76
|
-
<th style="padding:6px 8px;width:100px;">Eenheid</th>
|
|
77
|
-
</tr></thead>
|
|
78
|
-
<tbody>${rows}</tbody>
|
|
79
|
-
</table>`;
|
|
80
|
-
}
|
|
81
|
-
function renderOrderBlock(o) {
|
|
82
|
-
const orderRows = renderDefinitionList([
|
|
83
|
-
{ label: "Ordernummer", value: `<strong>${val(o.orderNumber)}</strong>` },
|
|
84
|
-
{ label: "Besteldatum", value: escape(fmtIsoDate(o.orderDate)) },
|
|
85
|
-
{ label: "Gewenste leverdatum", value: escape(fmtIsoDate(o.deliveryDate)) },
|
|
86
|
-
{ label: "Type levering", value: val(o.deliveryType) },
|
|
87
|
-
{ label: "Karren", value: String(o.cartCount ?? "—") },
|
|
88
|
-
{ label: "Planten", value: String(o.plantCount ?? "—") },
|
|
89
|
-
]);
|
|
90
|
-
const customerRows = renderDefinitionList([
|
|
91
|
-
{ label: "Klantnaam", value: val(o.customer.name) },
|
|
92
|
-
{ label: "E-mailadres", value: val(o.customer.email) },
|
|
93
|
-
]);
|
|
94
|
-
const pickupHtml = o.pickupLocations && o.pickupLocations.length > 0
|
|
95
|
-
? o.pickupLocations.map((p) => `<div>${escape(p)}</div>`).join("")
|
|
96
|
-
: `<div style="color:#6b7280;">Onbekend</div>`;
|
|
97
|
-
const notesHtml = o.notes && o.notes.trim()
|
|
98
|
-
? `<div style="background:#fffbeb;border:1px solid #fde68a;border-radius:6px;padding:10px 12px;font-size:13px;white-space:pre-wrap;">${escape(o.notes)}</div>`
|
|
99
|
-
: "";
|
|
100
|
-
return `
|
|
101
|
-
<div style="border:1px solid #e5e7eb;border-radius:8px;padding:16px;margin-bottom:20px;">
|
|
102
|
-
<h3 style="margin:0 0 12px 0;font-size:16px;">Order ${escape(o.orderNumber)}</h3>
|
|
103
|
-
|
|
104
|
-
<div style="margin-bottom:14px;">
|
|
105
|
-
<div style="font-weight:bold;font-size:13px;margin-bottom:6px;color:#111827;">Ordergegevens</div>
|
|
106
|
-
${orderRows}
|
|
107
|
-
</div>
|
|
108
|
-
|
|
109
|
-
<div style="margin-bottom:14px;">
|
|
110
|
-
<div style="font-weight:bold;font-size:13px;margin-bottom:6px;color:#111827;">Klantgegevens</div>
|
|
111
|
-
${customerRows}
|
|
112
|
-
</div>
|
|
113
|
-
|
|
114
|
-
<table style="width:100%;border-collapse:collapse;margin-bottom:14px;">
|
|
115
|
-
<tr>
|
|
116
|
-
<td style="vertical-align:top;width:50%;padding-right:8px;">
|
|
117
|
-
<div style="font-weight:bold;font-size:13px;margin-bottom:6px;color:#111827;">Afleverlocatie</div>
|
|
118
|
-
<div style="font-size:13px;">${renderAddress(o.deliveryLocation)}</div>
|
|
119
|
-
</td>
|
|
120
|
-
<td style="vertical-align:top;width:50%;padding-left:8px;">
|
|
121
|
-
<div style="font-weight:bold;font-size:13px;margin-bottom:6px;color:#111827;">Ophaallocatie</div>
|
|
122
|
-
<div style="font-size:13px;">${pickupHtml}</div>
|
|
123
|
-
</td>
|
|
124
|
-
</tr>
|
|
125
|
-
</table>
|
|
126
|
-
|
|
127
|
-
<div style="margin-bottom:14px;">
|
|
128
|
-
<div style="font-weight:bold;font-size:13px;margin-bottom:6px;color:#111827;">Bestelde artikelen</div>
|
|
129
|
-
${renderItemsTable(o.items)}
|
|
130
|
-
</div>
|
|
131
|
-
|
|
132
|
-
${notesHtml ? `<div><div style="font-weight:bold;font-size:13px;margin-bottom:6px;color:#111827;">Opmerkingen</div>${notesHtml}</div>` : ""}
|
|
133
|
-
</div>`;
|
|
17
|
+
return "—";
|
|
18
|
+
const street = [a.street, a.houseNumber].filter(Boolean).join(" ").trim();
|
|
19
|
+
const city = [a.postalCode, a.city].filter(Boolean).join(" ").trim();
|
|
20
|
+
const parts = [street, city].filter((v) => v && v.trim() !== "");
|
|
21
|
+
return parts.length > 0 ? parts.join(", ") : "—";
|
|
134
22
|
}
|
|
135
23
|
export function buildCarrierSignupMail(input) {
|
|
136
24
|
const totalCarts = input.orders.reduce((s, o) => s + (o.cartCount ?? 0), 0);
|
|
137
|
-
const
|
|
138
|
-
const subject = `Aanmelden karren ${input.carrierName} — ${input.pickupDate
|
|
139
|
-
const
|
|
25
|
+
const orderCount = input.orders.length;
|
|
26
|
+
const subject = `Aanmelden karren ${input.carrierName} — ${fmtDdMmYyyy(input.pickupDate)} ${input.pickupTime}`;
|
|
27
|
+
const rows = input.orders
|
|
140
28
|
.map((o) => `
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
29
|
+
<tr>
|
|
30
|
+
<td style="padding:6px 8px;border:1px solid #d1d5db;">${escape(o.orderNumber)}</td>
|
|
31
|
+
<td style="padding:6px 8px;border:1px solid #d1d5db;">${escape(o.customer.name)}</td>
|
|
32
|
+
<td style="padding:6px 8px;border:1px solid #d1d5db;">${escape(o.deliveryDate ?? "—")}</td>
|
|
33
|
+
<td style="padding:6px 8px;border:1px solid #d1d5db;text-align:right;">${o.cartCount ?? "—"}</td>
|
|
34
|
+
<td style="padding:6px 8px;border:1px solid #d1d5db;">${escape(formatFullAddress(o.deliveryLocation))}</td>
|
|
35
|
+
</tr>`)
|
|
148
36
|
.join("");
|
|
149
|
-
const orderBlocks = input.orders.map(renderOrderBlock).join("");
|
|
150
37
|
const html = `<!doctype html>
|
|
151
|
-
<html lang="nl"><body style="font-family:Arial,sans-serif;color:#111;
|
|
152
|
-
<
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
Aanmelddeadline: <strong>${escape(fmtDateTime(input.signupDeadline))}</strong>
|
|
157
|
-
</p>
|
|
38
|
+
<html lang="nl"><body style="font-family:Arial,sans-serif;color:#111;margin:0;padding:24px;">
|
|
39
|
+
<h2 style="margin:0 0 16px 0;">Aanmelden karren</h2>
|
|
40
|
+
<p style="margin:0 0 12px 0;">Beste ${escape(input.carrierName)},</p>
|
|
41
|
+
<p style="margin:0 0 12px 0;">Graag aanmelden voor ophalen op <strong>${fmtDdMmYyyy(input.pickupDate)} om ${escape(input.pickupTime)}</strong>.</p>
|
|
42
|
+
<p style="margin:0 0 16px 0;"><strong>${orderCount} order${orderCount === 1 ? "" : "s"} · ${totalCarts} karren</strong></p>
|
|
158
43
|
|
|
159
|
-
|
|
160
|
-
<
|
|
161
|
-
<
|
|
162
|
-
<th style="padding:6px 8px;">Order</th>
|
|
163
|
-
<th style="padding:6px 8px;">Klant</th>
|
|
164
|
-
<th style="padding:6px 8px;">
|
|
165
|
-
<th style="padding:6px 8px;text-align:right;">Karren</th>
|
|
166
|
-
<th style="padding:6px 8px;
|
|
167
|
-
</tr
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
<td style="padding:6px 8px;text-align:right;">${totalCarts}</td>
|
|
172
|
-
<td style="padding:6px 8px;text-align:right;">${totalPlants}</td>
|
|
173
|
-
</tr></tfoot>
|
|
174
|
-
</table>
|
|
175
|
-
|
|
176
|
-
${orderBlocks}
|
|
177
|
-
|
|
178
|
-
<p style="margin-top:16px;font-size:12px;color:#6b7280;">
|
|
179
|
-
Automatisch verzonden door Flowselections Afhandeling.
|
|
180
|
-
</p>
|
|
181
|
-
</div>
|
|
44
|
+
<table style="border-collapse:collapse;font-size:13px;">
|
|
45
|
+
<thead>
|
|
46
|
+
<tr style="background:#f3f4f6;text-align:left;">
|
|
47
|
+
<th style="padding:6px 8px;border:1px solid #d1d5db;">Order</th>
|
|
48
|
+
<th style="padding:6px 8px;border:1px solid #d1d5db;">Klant</th>
|
|
49
|
+
<th style="padding:6px 8px;border:1px solid #d1d5db;">Leverdatum</th>
|
|
50
|
+
<th style="padding:6px 8px;border:1px solid #d1d5db;text-align:right;">Karren</th>
|
|
51
|
+
<th style="padding:6px 8px;border:1px solid #d1d5db;">Plaats</th>
|
|
52
|
+
</tr>
|
|
53
|
+
</thead>
|
|
54
|
+
<tbody>${rows}</tbody>
|
|
55
|
+
</table>
|
|
182
56
|
</body></html>`;
|
|
183
|
-
const
|
|
184
|
-
.map((o) => {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
]
|
|
193
|
-
.filter((v) => v && String(v).trim())
|
|
194
|
-
.join(", ")
|
|
195
|
-
: "Onbekend";
|
|
196
|
-
const items = (o.items ?? [])
|
|
197
|
-
.map((it) => ` - ${it.name}: ${it.quantity ?? "-"} ${it.unit ?? ""}`.trim())
|
|
198
|
-
.join("\n");
|
|
199
|
-
return [
|
|
200
|
-
`Order ${o.orderNumber}`,
|
|
201
|
-
` Besteldatum: ${fmtIsoDate(o.orderDate)}`,
|
|
202
|
-
` Leverdatum: ${fmtIsoDate(o.deliveryDate)}`,
|
|
203
|
-
` Type: ${o.deliveryType}`,
|
|
204
|
-
` Karren: ${o.cartCount ?? "-"} | Planten: ${o.plantCount ?? "-"}`,
|
|
205
|
-
` Klant: ${o.customer.name}` +
|
|
206
|
-
(o.customer.email ? ` <${o.customer.email}>` : ""),
|
|
207
|
-
` Afleverlocatie: ${addr}`,
|
|
208
|
-
` Ophaallocatie: ${(o.pickupLocations ?? []).join(", ") || "Onbekend"}`,
|
|
209
|
-
items ? ` Artikelen:\n${items}` : ` Artikelen: -`,
|
|
210
|
-
o.notes ? ` Opmerkingen: ${o.notes}` : "",
|
|
211
|
-
]
|
|
212
|
-
.filter(Boolean)
|
|
213
|
-
.join("\n");
|
|
214
|
-
})
|
|
215
|
-
.join("\n\n");
|
|
216
|
-
const text = `Aanmelden karren — ${input.carrierName}\n` +
|
|
217
|
-
`Ophaalmoment: ${fmtDate(input.pickupDate)} ${input.pickupTime}\n` +
|
|
218
|
-
`Aanmelddeadline: ${fmtDateTime(input.signupDeadline)}\n\n` +
|
|
219
|
-
textOrders +
|
|
220
|
-
`\n\nTotaal: ${totalCarts} karren, ${totalPlants} planten.`;
|
|
221
|
-
return { subject, html, text, totalCarts, totalPlants };
|
|
222
|
-
}
|
|
223
|
-
function escape(s) {
|
|
224
|
-
return String(s)
|
|
225
|
-
.replace(/&/g, "&")
|
|
226
|
-
.replace(/</g, "<")
|
|
227
|
-
.replace(/>/g, ">")
|
|
228
|
-
.replace(/"/g, """);
|
|
57
|
+
const textRows = input.orders
|
|
58
|
+
.map((o) => `- ${o.orderNumber} | ${o.customer.name} | ${o.deliveryDate ?? "—"} | ${o.cartCount ?? "—"} karren | ${formatFullAddress(o.deliveryLocation)}`)
|
|
59
|
+
.join("\n");
|
|
60
|
+
const text = `Aanmelden karren\n\n` +
|
|
61
|
+
`Beste ${input.carrierName},\n\n` +
|
|
62
|
+
`Graag aanmelden voor ophalen op ${fmtDdMmYyyy(input.pickupDate)} om ${input.pickupTime}.\n\n` +
|
|
63
|
+
`${orderCount} order${orderCount === 1 ? "" : "s"} · ${totalCarts} karren\n\n` +
|
|
64
|
+
textRows;
|
|
65
|
+
return { subject, html, text, totalCarts };
|
|
229
66
|
}
|