@flowselections/floriday-verkoop-module 1.0.94 → 1.0.100
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/verkoop/AnalyticsCards.d.ts +1 -1
- package/dist-lib/components/verkoop/AnalyticsCards.d.ts.map +1 -1
- package/dist-lib/components/verkoop/CartAssignmentWizard.d.ts +1 -1
- package/dist-lib/components/verkoop/CartAssignmentWizard.d.ts.map +1 -1
- package/dist-lib/components/verkoop/CartLayersDialog.d.ts +1 -1
- package/dist-lib/components/verkoop/CartLayersDialog.d.ts.map +1 -1
- package/dist-lib/components/verkoop/ConfirmDialog.d.ts +11 -0
- package/dist-lib/components/verkoop/ConfirmDialog.d.ts.map +1 -0
- package/dist-lib/components/verkoop/ConfirmDialog.js +10 -0
- package/dist-lib/components/verkoop/CreateOrderPage.d.ts +1 -1
- package/dist-lib/components/verkoop/CreateOrderPage.d.ts.map +1 -1
- package/dist-lib/components/verkoop/CreateOrderPage.js +111 -48
- package/dist-lib/components/verkoop/DiagnoseConnectionDialog.d.ts +1 -1
- package/dist-lib/components/verkoop/DiagnoseConnectionDialog.d.ts.map +1 -1
- package/dist-lib/components/verkoop/EditLocalOrderDialog.d.ts +1 -1
- package/dist-lib/components/verkoop/EditLocalOrderDialog.d.ts.map +1 -1
- package/dist-lib/components/verkoop/EngineBufferCard.d.ts +1 -1
- package/dist-lib/components/verkoop/EngineBufferCard.d.ts.map +1 -1
- package/dist-lib/components/verkoop/FloridayStageLine.d.ts +2 -2
- package/dist-lib/components/verkoop/FloridayStageLine.d.ts.map +1 -1
- package/dist-lib/components/verkoop/InvoiceTimingSettings.d.ts +1 -1
- package/dist-lib/components/verkoop/InvoiceTimingSettings.d.ts.map +1 -1
- package/dist-lib/components/verkoop/OrderAfleverbrievenCard.d.ts +1 -1
- package/dist-lib/components/verkoop/OrderAfleverbrievenCard.d.ts.map +1 -1
- package/dist-lib/components/verkoop/OrderCarrierPicker.d.ts +1 -1
- package/dist-lib/components/verkoop/OrderCarrierPicker.d.ts.map +1 -1
- package/dist-lib/components/verkoop/OrderControlStatusCard.d.ts +1 -1
- package/dist-lib/components/verkoop/OrderControlStatusCard.d.ts.map +1 -1
- package/dist-lib/components/verkoop/OrderKarindelingCard.d.ts +1 -1
- package/dist-lib/components/verkoop/OrderKarindelingCard.d.ts.map +1 -1
- package/dist-lib/components/verkoop/OrderKarindelingCard.js +28 -2
- package/dist-lib/components/verkoop/OrderLinePackingCard.d.ts +1 -1
- package/dist-lib/components/verkoop/OrderLinePackingCard.d.ts.map +1 -1
- package/dist-lib/components/verkoop/OrderPickupMomentPicker.d.ts +1 -1
- package/dist-lib/components/verkoop/OrderPickupMomentPicker.d.ts.map +1 -1
- package/dist-lib/components/verkoop/OrderPickupMomentPicker.js +2 -1
- package/dist-lib/components/verkoop/OrderShipmentsCard.d.ts +1 -1
- package/dist-lib/components/verkoop/OrderShipmentsCard.d.ts.map +1 -1
- package/dist-lib/components/verkoop/OrderShipmentsCard.js +16 -13
- package/dist-lib/components/verkoop/PlanCoverageBadge.d.ts +1 -1
- package/dist-lib/components/verkoop/PlanCoverageBadge.d.ts.map +1 -1
- package/dist-lib/components/verkoop/PlanCoverageBadge.js +7 -5
- package/dist-lib/components/verkoop/ProductDimensionsSettings.d.ts +1 -1
- package/dist-lib/components/verkoop/ProductDimensionsSettings.d.ts.map +1 -1
- package/dist-lib/components/verkoop/SalesOrderDetailPage.d.ts +1 -1
- package/dist-lib/components/verkoop/SalesOrderDetailPage.d.ts.map +1 -1
- package/dist-lib/components/verkoop/SalesOrderDetailPage.js +6 -6
- package/dist-lib/components/verkoop/SalesOrderDetailView.d.ts +1 -1
- package/dist-lib/components/verkoop/SalesOrderDetailView.d.ts.map +1 -1
- package/dist-lib/components/verkoop/SalesOrderDetailView.js +2 -1
- package/dist-lib/components/verkoop/SalesOrdersFilterPanel.d.ts +1 -1
- package/dist-lib/components/verkoop/SalesOrdersFilterPanel.d.ts.map +1 -1
- package/dist-lib/components/verkoop/SalesOrdersFilters.d.ts +1 -1
- package/dist-lib/components/verkoop/SalesOrdersFilters.d.ts.map +1 -1
- package/dist-lib/components/verkoop/SalesOrdersTable.d.ts +2 -1
- package/dist-lib/components/verkoop/SalesOrdersTable.d.ts.map +1 -1
- package/dist-lib/components/verkoop/SalesOrdersTable.js +1 -1
- package/dist-lib/components/verkoop/SearchableSelect.d.ts +1 -1
- package/dist-lib/components/verkoop/SearchableSelect.d.ts.map +1 -1
- package/dist-lib/components/verkoop/StockConsumptionAlertsBanner.d.ts +1 -1
- package/dist-lib/components/verkoop/StockConsumptionAlertsBanner.d.ts.map +1 -1
- package/dist-lib/components/verkoop/VerkoopOrdersPage.d.ts +1 -1
- package/dist-lib/components/verkoop/VerkoopOrdersPage.d.ts.map +1 -1
- package/dist-lib/components/verkoop/WeekCalendar.d.ts +1 -1
- package/dist-lib/components/verkoop/WeekCalendar.d.ts.map +1 -1
- package/dist-lib/integrations/supabase/client.js +1 -1
- package/dist-lib/integrations/supabase/client.server.js +1 -1
- package/dist-lib/integrations/supabase/types.d.ts +352 -0
- package/dist-lib/integrations/supabase/types.d.ts.map +1 -1
- package/dist-lib/lib/carrier-availability.d.ts +0 -28
- package/dist-lib/lib/carrier-availability.d.ts.map +1 -1
- package/dist-lib/lib/carrier-availability.js +3 -141
- package/dist-lib/lib/cart-replan.functions.d.ts +5 -0
- package/dist-lib/lib/cart-replan.functions.d.ts.map +1 -1
- package/dist-lib/lib/cart-replan.functions.js +25 -1
- package/dist-lib/lib/create-order.functions.d.ts +8 -0
- package/dist-lib/lib/create-order.functions.d.ts.map +1 -1
- package/dist-lib/lib/create-order.functions.js +110 -54
- package/dist-lib/lib/departure-preview.check.d.ts +2 -0
- package/dist-lib/lib/departure-preview.check.d.ts.map +1 -0
- package/dist-lib/lib/departure-preview.check.js +60 -0
- package/dist-lib/lib/departure-preview.d.ts +71 -0
- package/dist-lib/lib/departure-preview.d.ts.map +1 -0
- package/dist-lib/lib/departure-preview.functions.d.ts +14 -0
- package/dist-lib/lib/departure-preview.functions.d.ts.map +1 -0
- package/dist-lib/lib/departure-preview.functions.js +18 -0
- package/dist-lib/lib/departure-preview.js +133 -0
- package/dist-lib/lib/departure-preview.server.d.ts +11 -0
- package/dist-lib/lib/departure-preview.server.d.ts.map +1 -0
- package/dist-lib/lib/departure-preview.server.js +32 -0
- package/dist-lib/lib/floriday-external-fulfillment.check.d.ts +2 -0
- package/dist-lib/lib/floriday-external-fulfillment.check.d.ts.map +1 -0
- package/dist-lib/lib/floriday-external-fulfillment.check.js +21 -0
- package/dist-lib/lib/floriday-external-fulfillment.d.ts +19 -0
- package/dist-lib/lib/floriday-external-fulfillment.d.ts.map +1 -0
- package/dist-lib/lib/floriday-external-fulfillment.js +24 -0
- package/dist-lib/lib/floriday-external-fulfillment.server.d.ts +5 -0
- package/dist-lib/lib/floriday-external-fulfillment.server.d.ts.map +1 -0
- package/dist-lib/lib/floriday-external-fulfillment.server.js +110 -0
- package/dist-lib/lib/floriday-fulfillment-status.server.d.ts +2 -0
- package/dist-lib/lib/floriday-fulfillment-status.server.d.ts.map +1 -1
- package/dist-lib/lib/floriday-fulfillment-status.server.js +3 -0
- package/dist-lib/lib/floriday-line-key.check.d.ts +2 -0
- package/dist-lib/lib/floriday-line-key.check.d.ts.map +1 -0
- package/dist-lib/lib/floriday-line-key.check.js +31 -0
- package/dist-lib/lib/floriday-line-key.d.ts +12 -0
- package/dist-lib/lib/floriday-line-key.d.ts.map +1 -0
- package/dist-lib/lib/floriday-line-key.js +20 -0
- package/dist-lib/lib/floriday-mirror.functions.d.ts.map +1 -1
- package/dist-lib/lib/floriday-mirror.functions.js +38 -2
- package/dist-lib/lib/invoice-timing.server.d.ts +3 -1
- package/dist-lib/lib/invoice-timing.server.d.ts.map +1 -1
- package/dist-lib/lib/invoice-timing.server.js +3 -2
- package/dist-lib/lib/logistics-engine.functions.d.ts +1 -1
- package/dist-lib/lib/module-version.d.ts +2 -0
- package/dist-lib/lib/module-version.d.ts.map +1 -0
- package/dist-lib/lib/module-version.js +3 -0
- package/dist-lib/lib/order-cart-count.server.d.ts +8 -0
- package/dist-lib/lib/order-cart-count.server.d.ts.map +1 -0
- package/dist-lib/lib/order-cart-count.server.js +69 -0
- package/dist-lib/lib/order-departure.server.d.ts +1 -0
- package/dist-lib/lib/order-departure.server.d.ts.map +1 -1
- package/dist-lib/lib/order-departure.server.js +16 -4
- package/dist-lib/lib/order-pickup.functions.d.ts +4 -0
- package/dist-lib/lib/order-pickup.functions.d.ts.map +1 -1
- package/dist-lib/lib/order-pickup.functions.js +7 -0
- package/dist-lib/lib/plan-coverage.d.ts +13 -1
- package/dist-lib/lib/plan-coverage.d.ts.map +1 -1
- package/dist-lib/lib/plan-coverage.js +20 -1
- package/dist-lib/lib/salesorders-list.server.d.ts.map +1 -1
- package/dist-lib/lib/salesorders-list.server.js +8 -7
- package/dist-lib/lib/salesorders-mapping.d.ts +7 -0
- package/dist-lib/lib/salesorders-mapping.d.ts.map +1 -1
- package/dist-lib/lib/salesorders.functions.d.ts.map +1 -1
- package/dist-lib/lib/salesorders.functions.js +10 -0
- package/dist-lib/lib/tradeitems.functions.d.ts +1117 -12
- package/dist-lib/lib/tradeitems.functions.d.ts.map +1 -1
- package/dist-lib/lib/useBufferEvents.d.ts +2 -2
- package/dist-lib/lib/useBufferEvents.d.ts.map +1 -1
- package/dist-lib/lib/useLocalSalesOrderDetailQuery.d.ts +2 -2
- package/dist-lib/lib/useLocalSalesOrderDetailQuery.d.ts.map +1 -1
- package/dist-lib/lib/useSalesOrderDetailQuery.d.ts +1 -1
- package/dist-lib/lib/useSalesOrderDetailQuery.d.ts.map +1 -1
- package/dist-lib/lib/useSalesOrdersQuery.d.ts +1 -1
- package/dist-lib/lib/useSalesOrdersQuery.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist-lib/components/floriday/FlorydaySyncHealthBanner.d.ts +0 -9
- package/dist-lib/components/floriday/FlorydaySyncHealthBanner.d.ts.map +0 -1
- package/dist-lib/components/floriday/FlorydaySyncHealthBanner.js +0 -26
- package/dist-lib/components/karindeling/AfmetingenTab.d.ts +0 -6
- package/dist-lib/components/karindeling/AfmetingenTab.d.ts.map +0 -1
- package/dist-lib/components/karindeling/AfmetingenTab.js +0 -128
- package/dist-lib/components/karindeling/KarindelingPage.d.ts +0 -2
- package/dist-lib/components/karindeling/KarindelingPage.d.ts.map +0 -1
- package/dist-lib/components/karindeling/KarindelingPage.js +0 -102
- package/dist-lib/components/ui/dropdown-menu.d.ts +0 -9
- package/dist-lib/components/ui/dropdown-menu.d.ts.map +0 -1
- package/dist-lib/components/ui/dropdown-menu.js +0 -14
- package/dist-lib/components/verkoop/AutoFulfillmentStatusCard.d.ts +0 -4
- package/dist-lib/components/verkoop/AutoFulfillmentStatusCard.d.ts.map +0 -1
- package/dist-lib/components/verkoop/AutoFulfillmentStatusCard.js +0 -95
- package/dist-lib/components/verkoop/CreateOrderDialog.d.ts +0 -5
- package/dist-lib/components/verkoop/CreateOrderDialog.d.ts.map +0 -1
- package/dist-lib/components/verkoop/CreateOrderDialog.js +0 -33
- package/dist-lib/lib/cron/mirror-floriday-orders.d.ts +0 -4
- package/dist-lib/lib/cron/mirror-floriday-orders.d.ts.map +0 -1
- package/dist-lib/lib/cron/mirror-floriday-orders.js +0 -23
- package/dist-lib/lib/cron/push-order-statuses.d.ts +0 -4
- package/dist-lib/lib/cron/push-order-statuses.d.ts.map +0 -1
- package/dist-lib/lib/cron/push-order-statuses.js +0 -23
- package/dist-lib/lib/floriday/floriday.server.d.ts +0 -14
- package/dist-lib/lib/floriday/floriday.server.d.ts.map +0 -1
- package/dist-lib/lib/floriday/floriday.server.js +0 -92
- package/dist-lib/lib/floriday/sales-orders.functions.d.ts +0 -4736
- package/dist-lib/lib/floriday/sales-orders.functions.d.ts.map +0 -1
- package/dist-lib/lib/floriday/sales-orders.functions.js +0 -193
- package/dist-lib/lib/floriday-auto-fulfillment.functions.d.ts +0 -77581
- package/dist-lib/lib/floriday-auto-fulfillment.functions.d.ts.map +0 -1
- package/dist-lib/lib/floriday-auto-fulfillment.functions.js +0 -65
- package/dist-lib/lib/floriday-auto-fulfillment.server.d.ts +0 -21
- package/dist-lib/lib/floriday-auto-fulfillment.server.d.ts.map +0 -1
- package/dist-lib/lib/floriday-auto-fulfillment.server.js +0 -352
- package/dist-lib/lib/floriday-status-sync.server.d.ts +0 -14
- package/dist-lib/lib/floriday-status-sync.server.d.ts.map +0 -1
- package/dist-lib/lib/floriday-status-sync.server.js +0 -130
|
@@ -15,35 +15,7 @@ export type CarrierAvailability = {
|
|
|
15
15
|
delivery_weekdays?: number[] | null;
|
|
16
16
|
pickup_moments?: PickupMoment[] | null;
|
|
17
17
|
};
|
|
18
|
-
export type EarliestDelivery = {
|
|
19
|
-
/** Leverdatum als YYYY-MM-DD. */
|
|
20
|
-
deliveryISO: string;
|
|
21
|
-
/** Ophaal-/aanmelddag als YYYY-MM-DD. */
|
|
22
|
-
pickupISO: string;
|
|
23
|
-
/** Uiterste aanmeldmoment dat hierbij hoort (ISO-datum + tijd), indien bekend. */
|
|
24
|
-
signupDeadlineISO: string | null;
|
|
25
|
-
signupTime: string | null;
|
|
26
|
-
/** Aanlevertijd van het gekozen moment, bv. "20:00". */
|
|
27
|
-
deliveryTime: string | null;
|
|
28
|
-
};
|
|
29
18
|
export declare function toISODate(d: Date): string;
|
|
30
19
|
/** "20:00:00" / "20:00" -> "20:00"; leeg -> null. */
|
|
31
20
|
export declare function normalizeTime(t: string | null | undefined): string | null;
|
|
32
|
-
/**
|
|
33
|
-
* Eerst mogelijke leverdatum.
|
|
34
|
-
*
|
|
35
|
-
* - Een ophaaldag telt alleen mee als het bijbehorende aanmeldmoment nog niet
|
|
36
|
-
* verstreken is (aanmelddeadline = ophaaldag − signup_days op signup_time).
|
|
37
|
-
* - Ophaaldag moet in pickup_weekdays vallen, leverdag in delivery_weekdays.
|
|
38
|
-
* - `pickDays` (interne orderpicktijd) is de minimale voorlooptijd tot de ophaaldag.
|
|
39
|
-
*/
|
|
40
|
-
export declare function computeEarliestDelivery(carrier: CarrierAvailability | null | undefined, pickDays: number, now?: Date, horizonDays?: number): EarliestDelivery;
|
|
41
|
-
/** "Nu" in Europe/Amsterdam als lokale Date — voor servercode die in UTC draait. */
|
|
42
|
-
export declare function nowInAmsterdam(base?: Date): Date;
|
|
43
|
-
/**
|
|
44
|
-
* Aanlevertijd die hoort bij een (al vastgelegde) leverdatum van een order.
|
|
45
|
-
* Kiest het aanmeldmoment dat op die datum uitkomt; bij meerdere momenten het
|
|
46
|
-
* moment dat het laatst nog haalbaar was op het referentiemoment (besteltijd).
|
|
47
|
-
*/
|
|
48
|
-
export declare function resolveDeliveryTimeForDate(carrier: CarrierAvailability | null | undefined, deliveryISO: string, reference?: Date): string | null;
|
|
49
21
|
//# sourceMappingURL=carrier-availability.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"carrier-availability.d.ts","sourceRoot":"","sources":["../../src/lib/carrier-availability.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"carrier-availability.d.ts","sourceRoot":"","sources":["../../src/lib/carrier-availability.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,YAAY,GAAG;IACzB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,2BAA2B,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,eAAe,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAClC,iBAAiB,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACpC,cAAc,CAAC,EAAE,YAAY,EAAE,GAAG,IAAI,CAAC;CACxC,CAAC;AAEF,wBAAgB,SAAS,CAAC,CAAC,EAAE,IAAI,GAAG,MAAM,CAEzC;AAED,qDAAqD;AACrD,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAIzE"}
|
|
@@ -1,26 +1,9 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// exact hetzelfde antwoord geven.
|
|
1
|
+
// Gegevens van de vervoerder (pickup_moments). Hier wordt niets berekend:
|
|
2
|
+
// ophaalmomenten, werkdagen, tijdzone en de eerst haalbare leverdatum komen
|
|
3
|
+
// van de Logistiek Engine (logistics_departure_preview / logistics_order_departure).
|
|
5
4
|
export function toISODate(d) {
|
|
6
5
|
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
7
6
|
}
|
|
8
|
-
function addDays(d, n) {
|
|
9
|
-
const c = new Date(d.getTime());
|
|
10
|
-
c.setDate(c.getDate() + n);
|
|
11
|
-
return c;
|
|
12
|
-
}
|
|
13
|
-
/** ISO-weekdag: maandag = 1 … zondag = 7. */
|
|
14
|
-
function isoWeekday(d) {
|
|
15
|
-
return d.getDay() === 0 ? 7 : d.getDay();
|
|
16
|
-
}
|
|
17
|
-
function parseTime(t, fallback) {
|
|
18
|
-
const s = (t ?? fallback) || fallback;
|
|
19
|
-
const m = /^(\d{1,2}):(\d{2})/.exec(String(s));
|
|
20
|
-
if (!m)
|
|
21
|
-
return [23, 59];
|
|
22
|
-
return [Number(m[1]), Number(m[2])];
|
|
23
|
-
}
|
|
24
7
|
/** "20:00:00" / "20:00" -> "20:00"; leeg -> null. */
|
|
25
8
|
export function normalizeTime(t) {
|
|
26
9
|
const m = /^(\d{1,2}):(\d{2})/.exec(String(t ?? "").trim());
|
|
@@ -28,124 +11,3 @@ export function normalizeTime(t) {
|
|
|
28
11
|
return null;
|
|
29
12
|
return `${String(Number(m[1])).padStart(2, "0")}:${m[2]}`;
|
|
30
13
|
}
|
|
31
|
-
function allowsWeekday(list, d) {
|
|
32
|
-
if (!Array.isArray(list) || list.length === 0)
|
|
33
|
-
return true;
|
|
34
|
-
return list.map(Number).includes(isoWeekday(d));
|
|
35
|
-
}
|
|
36
|
-
function momentsOf(carrier) {
|
|
37
|
-
const raw = Array.isArray(carrier.pickup_moments) ? carrier.pickup_moments : [];
|
|
38
|
-
if (raw.length > 0)
|
|
39
|
-
return raw;
|
|
40
|
-
// Terugval op de losse signup_time-velden.
|
|
41
|
-
const times = [carrier.signup_time_1, carrier.signup_time_2].filter(Boolean);
|
|
42
|
-
if (times.length > 0) {
|
|
43
|
-
return times.map((t) => ({
|
|
44
|
-
signup_time: t,
|
|
45
|
-
signup_days: carrier.signup_days_before_delivery ?? 0,
|
|
46
|
-
delivery_days: carrier.delivery_days ?? 0,
|
|
47
|
-
}));
|
|
48
|
-
}
|
|
49
|
-
// Geen aanmeldmomenten bekend: één moment zonder deadline.
|
|
50
|
-
return [{ signup_time: null, signup_days: carrier.signup_days_before_delivery ?? 0, delivery_days: carrier.delivery_days ?? 0 }];
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Eerst mogelijke leverdatum.
|
|
54
|
-
*
|
|
55
|
-
* - Een ophaaldag telt alleen mee als het bijbehorende aanmeldmoment nog niet
|
|
56
|
-
* verstreken is (aanmelddeadline = ophaaldag − signup_days op signup_time).
|
|
57
|
-
* - Ophaaldag moet in pickup_weekdays vallen, leverdag in delivery_weekdays.
|
|
58
|
-
* - `pickDays` (interne orderpicktijd) is de minimale voorlooptijd tot de ophaaldag.
|
|
59
|
-
*/
|
|
60
|
-
export function computeEarliestDelivery(carrier, pickDays, now = new Date(), horizonDays = 90) {
|
|
61
|
-
const lead = Math.max(0, Number(pickDays) || 0);
|
|
62
|
-
const today = new Date(now.getTime());
|
|
63
|
-
today.setHours(0, 0, 0, 0);
|
|
64
|
-
const carrierDeliveryDays = Math.max(0, Number(carrier?.delivery_days ?? 0) || 0);
|
|
65
|
-
if (!carrier) {
|
|
66
|
-
const d = addDays(today, lead);
|
|
67
|
-
return { deliveryISO: toISODate(d), pickupISO: toISODate(d), signupDeadlineISO: null, signupTime: null, deliveryTime: null };
|
|
68
|
-
}
|
|
69
|
-
const moments = momentsOf(carrier);
|
|
70
|
-
let best = null;
|
|
71
|
-
for (let i = lead; i <= horizonDays; i++) {
|
|
72
|
-
const pickupDate = addDays(today, i);
|
|
73
|
-
if (!allowsWeekday(carrier.pickup_weekdays, pickupDate))
|
|
74
|
-
continue;
|
|
75
|
-
for (const m of moments) {
|
|
76
|
-
const signupDays = Math.max(0, Number(m.signup_days ?? carrier.signup_days_before_delivery ?? 0) || 0);
|
|
77
|
-
const signupDate = addDays(pickupDate, -signupDays);
|
|
78
|
-
let deadlineISO = null;
|
|
79
|
-
if (m.signup_time) {
|
|
80
|
-
const [hh, mm] = parseTime(m.signup_time, "23:59");
|
|
81
|
-
const deadline = new Date(signupDate.getTime());
|
|
82
|
-
deadline.setHours(hh, mm, 0, 0);
|
|
83
|
-
if (deadline.getTime() <= now.getTime())
|
|
84
|
-
continue; // aanmeldmoment verstreken
|
|
85
|
-
deadlineISO = `${toISODate(signupDate)}T${String(hh).padStart(2, "0")}:${String(mm).padStart(2, "0")}`;
|
|
86
|
-
}
|
|
87
|
-
else if (signupDate.getTime() < today.getTime()) {
|
|
88
|
-
continue;
|
|
89
|
-
}
|
|
90
|
-
const deliveryDays = Math.max(0, Number(m.delivery_days ?? carrierDeliveryDays) || 0);
|
|
91
|
-
const deliveryDate = addDays(pickupDate, deliveryDays);
|
|
92
|
-
if (!allowsWeekday(carrier.delivery_weekdays, deliveryDate))
|
|
93
|
-
continue;
|
|
94
|
-
const candidate = {
|
|
95
|
-
deliveryISO: toISODate(deliveryDate),
|
|
96
|
-
pickupISO: toISODate(pickupDate),
|
|
97
|
-
signupDeadlineISO: deadlineISO,
|
|
98
|
-
signupTime: m.signup_time ?? null,
|
|
99
|
-
deliveryTime: normalizeTime(m.delivery_time),
|
|
100
|
-
};
|
|
101
|
-
if (!best ||
|
|
102
|
-
candidate.deliveryISO < best.deliveryISO ||
|
|
103
|
-
(candidate.deliveryISO === best.deliveryISO &&
|
|
104
|
-
(candidate.deliveryTime ?? "99:99") < (best.deliveryTime ?? "99:99"))) {
|
|
105
|
-
best = candidate;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
if (best)
|
|
109
|
-
break; // eerste geldige ophaaldag bepaalt de vroegste levering
|
|
110
|
-
}
|
|
111
|
-
if (best)
|
|
112
|
-
return best;
|
|
113
|
-
const fallback = addDays(today, lead + carrierDeliveryDays);
|
|
114
|
-
return { deliveryISO: toISODate(fallback), pickupISO: toISODate(fallback), signupDeadlineISO: null, signupTime: null, deliveryTime: null };
|
|
115
|
-
}
|
|
116
|
-
/** "Nu" in Europe/Amsterdam als lokale Date — voor servercode die in UTC draait. */
|
|
117
|
-
export function nowInAmsterdam(base = new Date()) {
|
|
118
|
-
const parts = new Intl.DateTimeFormat("en-US", {
|
|
119
|
-
timeZone: "Europe/Amsterdam",
|
|
120
|
-
year: "numeric", month: "2-digit", day: "2-digit",
|
|
121
|
-
hour: "2-digit", minute: "2-digit", second: "2-digit", hour12: false,
|
|
122
|
-
}).formatToParts(base);
|
|
123
|
-
const get = (t) => Number(parts.find((p) => p.type === t)?.value ?? 0);
|
|
124
|
-
return new Date(get("year"), get("month") - 1, get("day"), get("hour") % 24, get("minute"), get("second"), 0);
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Aanlevertijd die hoort bij een (al vastgelegde) leverdatum van een order.
|
|
128
|
-
* Kiest het aanmeldmoment dat op die datum uitkomt; bij meerdere momenten het
|
|
129
|
-
* moment dat het laatst nog haalbaar was op het referentiemoment (besteltijd).
|
|
130
|
-
*/
|
|
131
|
-
export function resolveDeliveryTimeForDate(carrier, deliveryISO, reference = new Date()) {
|
|
132
|
-
if (!carrier || !deliveryISO)
|
|
133
|
-
return null;
|
|
134
|
-
const moments = momentsOf(carrier);
|
|
135
|
-
const candidates = [];
|
|
136
|
-
for (const m of moments) {
|
|
137
|
-
const time = normalizeTime(m.delivery_time);
|
|
138
|
-
if (!time)
|
|
139
|
-
continue;
|
|
140
|
-
candidates.push({ time, signup: normalizeTime(m.signup_time) });
|
|
141
|
-
}
|
|
142
|
-
if (candidates.length === 0)
|
|
143
|
-
return null;
|
|
144
|
-
if (candidates.length === 1)
|
|
145
|
-
return candidates[0].time;
|
|
146
|
-
const refTime = `${String(reference.getHours()).padStart(2, "0")}:${String(reference.getMinutes()).padStart(2, "0")}`;
|
|
147
|
-
const sorted = [...candidates].sort((a, b) => a.time.localeCompare(b.time));
|
|
148
|
-
// Eerste moment waarvan het aanmeldmoment op de besteltijd nog niet verstreken is.
|
|
149
|
-
const still = sorted.find((c) => !c.signup || c.signup > refTime);
|
|
150
|
-
return (still ?? sorted[sorted.length - 1]).time;
|
|
151
|
-
}
|
|
@@ -79,6 +79,11 @@ export declare const getOrderPlanCoverage: import("@tanstack/start-client-core")
|
|
|
79
79
|
}, Promise<{
|
|
80
80
|
orderId: string;
|
|
81
81
|
coverage: import("./plan-coverage.js").PlanCoverage;
|
|
82
|
+
externalEvent: {
|
|
83
|
+
status: string | null;
|
|
84
|
+
error: string | null;
|
|
85
|
+
sendError: string | null;
|
|
86
|
+
} | null;
|
|
82
87
|
}>>;
|
|
83
88
|
export declare const replanBufferForOrder: import("@tanstack/start-client-core").OptionalFetcher<readonly [import("@tanstack/start-client-core").FunctionMiddlewareAfterServer<{}, unknown, undefined, {
|
|
84
89
|
supabase: import("../integrations/supabase/auth-middleware.js").AuthedSupabaseClient;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cart-replan.functions.d.ts","sourceRoot":"","sources":["../../src/lib/cart-replan.functions.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,eAAe,GAAG,sBAAsB,CAAC;IACjD,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,MAAM;QAYrD,OAAO;cACD,MAAM,GAAG,IAAI;cACb,MAAM,EAAE;kBACJ,MAAM;yBACC,MAAM;yBACN,OAAO;cAClB,MAAM,EAAE;kBACJ,WAAW,EAAE;cACjB,QAAQ;GAlBnB;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,EAAE;IAC/C,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,GAAG,OAAO,CAAC;IACV,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,OAAO,CAAC,EAAE,QAAQ,CAAC;CACpB,CAAC,CA+YD;AA4BD,wBAAsB,wBAAwB,CAAC,OAAO,EAAE,MAAM;QAzBxD,OAAO;aACF,MAAM;kBACD,MAAM;yBACC,MAAM;yBACN,OAAO;cAClB,MAAM,EAAE;kBACJ,WAAW,EAAE;cACjB,QAAQ;GAoBnB;AAED,eAAO,MAAM,gBAAgB;;;;8CAEH,OAAO;;;QA/B3B,OAAO;aACF,MAAM;kBACD,MAAM;yBACC,MAAM;yBACN,OAAO;cAClB,MAAM,EAAE;kBACJ,WAAW,EAAE;cACjB,QAAQ;GA6BhB,CAAC;AAML,wBAAsB,oBAAoB,CAAC,MAAM,SAAK,GAAG,OAAO,CAAC;IAC/D,EAAE,EAAE,OAAO,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClE,CAAC,CAED;AAMD,eAAO,MAAM,oBAAoB;;;;8CAEP,OAAO
|
|
1
|
+
{"version":3,"file":"cart-replan.functions.d.ts","sourceRoot":"","sources":["../../src/lib/cart-replan.functions.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,eAAe,GAAG,sBAAsB,CAAC;IACjD,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,MAAM;QAYrD,OAAO;cACD,MAAM,GAAG,IAAI;cACb,MAAM,EAAE;kBACJ,MAAM;yBACC,MAAM;yBACN,OAAO;cAClB,MAAM,EAAE;kBACJ,WAAW,EAAE;cACjB,QAAQ;GAlBnB;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,EAAE;IAC/C,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,GAAG,OAAO,CAAC;IACV,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,OAAO,CAAC,EAAE,QAAQ,CAAC;CACpB,CAAC,CA+YD;AA4BD,wBAAsB,wBAAwB,CAAC,OAAO,EAAE,MAAM;QAzBxD,OAAO;aACF,MAAM;kBACD,MAAM;yBACC,MAAM;yBACN,OAAO;cAClB,MAAM,EAAE;kBACJ,WAAW,EAAE;cACjB,QAAQ;GAoBnB;AAED,eAAO,MAAM,gBAAgB;;;;8CAEH,OAAO;;;QA/B3B,OAAO;aACF,MAAM;kBACD,MAAM;yBACC,MAAM;yBACN,OAAO;cAClB,MAAM,EAAE;kBACJ,WAAW,EAAE;cACjB,QAAQ;GA6BhB,CAAC;AAML,wBAAsB,oBAAoB,CAAC,MAAM,SAAK,GAAG,OAAO,CAAC;IAC/D,EAAE,EAAE,OAAO,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClE,CAAC,CAED;AAMD,eAAO,MAAM,oBAAoB;;;;8CAEP,OAAO;;;;;;gBAUA,MAAM,GAAG,IAAI;eAAS,MAAM,GAAG,IAAI;mBAAa,MAAM,GAAG,IAAI;;GAsB1F,CAAC;AAEL,eAAO,MAAM,oBAAoB;;;;8CAEP,OAAO;;;QAxf3B,OAAO;cACD,MAAM,GAAG,IAAI;cACb,MAAM,EAAE;kBACJ,MAAM;yBACC,MAAM;yBACN,OAAO;cAClB,MAAM,EAAE;kBACJ,WAAW,EAAE;cACjB,QAAQ;GAsfhB,CAAC"}
|
|
@@ -393,7 +393,31 @@ export const getOrderPlanCoverage = createServerFn({ method: "GET" })
|
|
|
393
393
|
const { unknownCoverage } = await import("./plan-coverage.js");
|
|
394
394
|
const cov = (await loadPlanCoverage(context.supabase, [dbOrderId])).get(dbOrderId) ??
|
|
395
395
|
unknownCoverage("Geen antwoord van de Engine");
|
|
396
|
-
|
|
396
|
+
// Uitkomst van de melding "Afgehandeld in Floriday" (alleen lezen).
|
|
397
|
+
let externalEvent = null;
|
|
398
|
+
try {
|
|
399
|
+
const { data: o } = await context.supabase.from("orders")
|
|
400
|
+
.select("custom_fields")
|
|
401
|
+
.eq("id", dbOrderId)
|
|
402
|
+
.maybeSingle();
|
|
403
|
+
const cf = (o?.custom_fields ?? {});
|
|
404
|
+
const evId = typeof cf.floriday_external_engine_event_id === "string" ? cf.floriday_external_engine_event_id : null;
|
|
405
|
+
const sendError = typeof cf.floriday_external_engine_error === "string" ? cf.floriday_external_engine_error : null;
|
|
406
|
+
if (evId) {
|
|
407
|
+
const { data: ev } = await context.supabase.from("logistics_events")
|
|
408
|
+
.select("status, error")
|
|
409
|
+
.eq("id", evId)
|
|
410
|
+
.maybeSingle();
|
|
411
|
+
externalEvent = { status: ev?.status ?? null, error: ev?.error ?? null, sendError };
|
|
412
|
+
}
|
|
413
|
+
else if (sendError) {
|
|
414
|
+
externalEvent = { status: null, error: null, sendError };
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
catch {
|
|
418
|
+
externalEvent = null;
|
|
419
|
+
}
|
|
420
|
+
return { orderId: dbOrderId, coverage: cov, externalEvent };
|
|
397
421
|
});
|
|
398
422
|
export const replanBufferForOrder = createServerFn({ method: "POST" })
|
|
399
423
|
.middleware([requireSupabaseAuth])
|
|
@@ -146,6 +146,13 @@ export declare const createManualOrder: import("@tanstack/start-client-core").Op
|
|
|
146
146
|
isReservation?: boolean | undefined;
|
|
147
147
|
loadCarrierType?: string | null | undefined;
|
|
148
148
|
notes?: string | null | undefined;
|
|
149
|
+
momentKey?: string | null | undefined;
|
|
150
|
+
acceptLateSignup?: boolean | undefined;
|
|
151
|
+
acceptedByName?: string | null | undefined;
|
|
152
|
+
source?: "manual" | "mailbox" | undefined;
|
|
153
|
+
customerReference?: string | null | undefined;
|
|
154
|
+
ownTransport?: boolean | undefined;
|
|
155
|
+
ownTransportPickupAt?: string | null | undefined;
|
|
149
156
|
}, Promise<{
|
|
150
157
|
ok: true;
|
|
151
158
|
orderId: string;
|
|
@@ -219,6 +226,7 @@ export declare const updateLocalOrder: import("@tanstack/start-client-core").Opt
|
|
|
219
226
|
}, undefined, undefined, undefined>], (input: unknown) => {
|
|
220
227
|
orderId: string;
|
|
221
228
|
deliveryDate?: string | undefined;
|
|
229
|
+
acceptLateSignup?: boolean | undefined;
|
|
222
230
|
items?: {
|
|
223
231
|
itemId: string;
|
|
224
232
|
quantity: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-order.functions.d.ts","sourceRoot":"","sources":["../../src/lib/create-order.functions.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,2BAA2B;;;;;;GA+CpC,CAAC;AAIL,eAAO,MAAM,2BAA2B;;;;0CAElB,OAAO;;;;GAoDzB,CAAC;AAWL,eAAO,MAAM,0BAA0B;;;;;;YA+D7B,MAAM;iBACD,MAAM;sBACD,MAAM,GAAG,IAAI;cACrB,MAAM;oBACA,MAAM,GAAG,IAAI;0BACP,MAAM;0BACN,MAAM;yBACP,MAAM;wBACP,MAAM;wBACN,MAAM;yBACL,MAAM;kBACb,OAAO;gBACT,UAAU,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS;;GA6RpD,CAAC;AAGL,eAAO,MAAM,kCAAkC;;;;0CAEzB,OAAO;;;;;;;;;;;;;;;;;;;;;;GAkDzB,CAAC;AAKL,eAAO,MAAM,qBAAqB;;;;;;YAoBI,MAAM;;;GAIxC,CAAC;AAGL,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;GAWnC,CAAC;AASL,eAAO,MAAM,8BAA8B;;;;8CAEjB,OAAO;;;;GAU7B,CAAC;AASL,eAAO,MAAM,mBAAmB;;;;;;;;0BAgBuB,MAAM;0BAAoB,MAAM;yBAAmB,MAAM;;;GA8C5G,CAAC;AAGL,eAAO,MAAM,kBAAkB;;;;;;GAU3B,CAAC;
|
|
1
|
+
{"version":3,"file":"create-order.functions.d.ts","sourceRoot":"","sources":["../../src/lib/create-order.functions.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,2BAA2B;;;;;;GA+CpC,CAAC;AAIL,eAAO,MAAM,2BAA2B;;;;0CAElB,OAAO;;;;GAoDzB,CAAC;AAWL,eAAO,MAAM,0BAA0B;;;;;;YA+D7B,MAAM;iBACD,MAAM;sBACD,MAAM,GAAG,IAAI;cACrB,MAAM;oBACA,MAAM,GAAG,IAAI;0BACP,MAAM;0BACN,MAAM;yBACP,MAAM;wBACP,MAAM;wBACN,MAAM;yBACL,MAAM;kBACb,OAAO;gBACT,UAAU,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS;;GA6RpD,CAAC;AAGL,eAAO,MAAM,kCAAkC;;;;0CAEzB,OAAO;;;;;;;;;;;;;;;;;;;;;;GAkDzB,CAAC;AAKL,eAAO,MAAM,qBAAqB;;;;;;YAoBI,MAAM;;;GAIxC,CAAC;AAGL,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;GAWnC,CAAC;AASL,eAAO,MAAM,8BAA8B;;;;8CAEjB,OAAO;;;;GAU7B,CAAC;AASL,eAAO,MAAM,mBAAmB;;;;;;;;0BAgBuB,MAAM;0BAAoB,MAAM;yBAAmB,MAAM;;;GA8C5G,CAAC;AAGL,eAAO,MAAM,kBAAkB;;;;;;GAU3B,CAAC;AA+CL,eAAO,MAAM,iBAAiB;;;;8CAEJ,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aA4PY,MAAM;GAE/C,CAAC;AAKL,eAAO,MAAM,gBAAgB;;;;8CAEH,OAAO;;;;;;;GAY7B,CAAC;AAQL,eAAO,MAAM,gBAAgB;;;;8CAEH,OAAO;;;;;;GAoG7B,CAAC;AAEL;;;GAGG;AACH,eAAO,MAAM,qBAAqB;;;;8CAER,OAAO;;;;GAyB7B,CAAC;AA0CL,eAAO,MAAM,oBAAoB;;;;8CAEP,OAAO;;;aA0JG,MAAM;iBACQ,MAAM,GAAG,IAAI;kBACX,MAAM;;YAEnB,MAAM,GAAG,IAAI;;;;YAkB7B,MAAM;mBACS,MAAM,GAAG,IAAI;qBACT,MAAM;;cAErB,MAAM,GAAG,IAAI;;;;;;GAQpC,CAAC;AAIL,eAAO,MAAM,gBAAgB;;;;8CAEH,OAAO;;;;;;;;;;;;;;;;;;;;;GAuO7B,CAAC;AAKL,eAAO,MAAM,kBAAkB;;;;8CAEL,OAAO;;;;;;;;WAUM,MAAM;YAAU,MAAM,GAAG,IAAI;WAahE,CAAC"}
|
|
@@ -658,15 +658,19 @@ const CreateManualOrderInput = z.object({
|
|
|
658
658
|
loadCarrierType: z.string().max(50).nullable().optional(),
|
|
659
659
|
notes: z.string().max(2000).nullable().optional(),
|
|
660
660
|
lines: z.array(LineInput).min(1),
|
|
661
|
+
// Gekozen ophaalmoment (momentKey uit de Engine-voorbeeldversie).
|
|
662
|
+
momentKey: z.string().max(64).nullable().optional(),
|
|
663
|
+
// Bewust aanmaken na de aanmeldtijd (spoedorder). Zonder dit wordt een
|
|
664
|
+
// niet-haalbare leverdatum geweigerd.
|
|
665
|
+
acceptLateSignup: z.boolean().optional(),
|
|
666
|
+
acceptedByName: z.string().max(255).nullable().optional(),
|
|
667
|
+
source: z.enum(["manual", "mailbox"]).optional(),
|
|
668
|
+
// Referentie van de klant (custom_fields.customer_reference).
|
|
669
|
+
customerReference: z.string().trim().max(100).nullable().optional(),
|
|
670
|
+
// Eigen vervoer / zelf afleveren: geen vervoerder, bewuste keuze.
|
|
671
|
+
ownTransport: z.boolean().optional(),
|
|
672
|
+
ownTransportPickupAt: z.string().regex(/(Z|[+-]\d{2}:\d{2})$/, "Tijd zonder tijdzone").nullable().optional(),
|
|
661
673
|
});
|
|
662
|
-
function addCalendarDays(base, n) {
|
|
663
|
-
const x = new Date(base);
|
|
664
|
-
x.setDate(x.getDate() + n);
|
|
665
|
-
return x;
|
|
666
|
-
}
|
|
667
|
-
function toISODate(d) {
|
|
668
|
-
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
669
|
-
}
|
|
670
674
|
export const createManualOrder = createServerFn({ method: "POST" })
|
|
671
675
|
.middleware([requireSupabaseAuth])
|
|
672
676
|
.inputValidator((input) => CreateManualOrderInput.parse(input))
|
|
@@ -677,45 +681,70 @@ export const createManualOrder = createServerFn({ method: "POST" })
|
|
|
677
681
|
const { assertOrderAllowed } = await import("./logistics-stock.server.js");
|
|
678
682
|
await assertOrderAllowed(context.supabase, data.lines.map((l) => ({ productId: l.product_id, quantity: Number(l.quantity) })));
|
|
679
683
|
}
|
|
680
|
-
// Validatie eerst mogelijke leverdatum — o.b.v. de aanmeldmomenten van de
|
|
681
|
-
// vervoerder (pickup_moments), niet enkel kalenderdagen. Een reservering
|
|
682
|
-
// heeft nog geen vervoerder en dus geen leverdatumvalidatie.
|
|
683
|
-
if (!data.isReservation && !data.carrierId) {
|
|
684
|
-
throw new Error("Selecteer een vervoerder");
|
|
685
|
-
}
|
|
686
684
|
// Ladingdrager: zonder keuze de standaard van de Engine; geen eigen controle.
|
|
687
685
|
const { resolveLoadCarrierType } = await import("./load-carriers.server.js");
|
|
688
686
|
const loadCarrierType = await resolveLoadCarrierType(context.supabase, data.loadCarrierType);
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
const { data: settings } = await context.supabase
|
|
698
|
-
.from("afhandeling_settings")
|
|
699
|
-
.select("pick_days_before_transport")
|
|
700
|
-
.order("updated_at", { ascending: false })
|
|
701
|
-
.limit(1).maybeSingle();
|
|
702
|
-
const pickDays = Math.max(0, Number(settings?.pick_days_before_transport ?? 0));
|
|
703
|
-
const { computeEarliestDelivery, nowInAmsterdam, resolveDeliveryTimeForDate } = await import("./carrier-availability.js");
|
|
704
|
-
const nowLocal = nowInAmsterdam();
|
|
705
|
-
const earliest = computeEarliestDelivery(c, pickDays, nowLocal);
|
|
706
|
-
// Aanlevertijd van het aanmeldmoment dat bij deze leverdatum hoort (bv. 20:00).
|
|
707
|
-
const deliveryTime = data.isReservation
|
|
708
|
-
? null
|
|
709
|
-
: (data.deliveryDate === earliest.deliveryISO
|
|
710
|
-
? earliest.deliveryTime
|
|
711
|
-
: resolveDeliveryTimeForDate(c, data.deliveryDate ?? "", nowLocal));
|
|
712
|
-
const earliestISO = earliest.deliveryISO;
|
|
687
|
+
// Ophaalmoment en haalbaarheid komen alleen van de Logistiek Engine
|
|
688
|
+
// (logistics_departure_preview). Geen eigen berekening of terugval.
|
|
689
|
+
const ownTransport = !data.isReservation && data.ownTransport === true;
|
|
690
|
+
let carrierId = data.isReservation || ownTransport ? null : (data.carrierId ?? null);
|
|
691
|
+
let ownTransportInfo = null;
|
|
692
|
+
let momentKey = null;
|
|
693
|
+
let deliveryTime = null;
|
|
694
|
+
let lateSignup = null;
|
|
713
695
|
if (!data.isReservation) {
|
|
714
696
|
if (!data.deliveryDate)
|
|
715
697
|
throw new Error("Leverdatum ontbreekt.");
|
|
716
|
-
|
|
717
|
-
|
|
698
|
+
const { loadDeparturePreview, deliveryTimeForMoment } = await import("./departure-preview.server.js");
|
|
699
|
+
const { decidePreview } = await import("./departure-preview.js");
|
|
700
|
+
const preview = await loadDeparturePreview(context.supabase, {
|
|
701
|
+
carrierId,
|
|
702
|
+
deliveryLocation: data.deliveryLocationId,
|
|
703
|
+
deliveryDate: data.deliveryDate.slice(0, 10),
|
|
704
|
+
momentKey: ownTransport ? null : (data.momentKey ?? null),
|
|
705
|
+
ownTransport,
|
|
706
|
+
});
|
|
707
|
+
const d = decidePreview(preview);
|
|
708
|
+
if (d.kind === "blocked")
|
|
709
|
+
throw new Error(d.reason);
|
|
710
|
+
// Vervoerder al vertrokken: nooit aanmaken, ook niet met "toch aanmaken".
|
|
711
|
+
if (d.kind === "departed") {
|
|
712
|
+
throw new Error(d.firstDate ? `${d.reason} De eerstvolgende leverdatum is ${d.firstDate}.` : d.reason);
|
|
713
|
+
}
|
|
714
|
+
if (ownTransport) {
|
|
715
|
+
const by = context.claims?.email ?? null;
|
|
716
|
+
ownTransportInfo = {
|
|
717
|
+
by: data.acceptedByName ?? by ?? context.userId ?? null,
|
|
718
|
+
by_user_id: context.userId ?? null,
|
|
719
|
+
at: new Date().toISOString(),
|
|
720
|
+
...(data.ownTransportPickupAt ? { pickup_at: data.ownTransportPickupAt } : {}),
|
|
721
|
+
};
|
|
718
722
|
}
|
|
723
|
+
if (d.kind === "late") {
|
|
724
|
+
if (!data.acceptLateSignup) {
|
|
725
|
+
throw new Error(d.firstDate
|
|
726
|
+
? `${d.reason} De eerste haalbare leverdatum is ${d.firstDate}.`
|
|
727
|
+
: d.reason);
|
|
728
|
+
}
|
|
729
|
+
const by = context.claims?.email ?? null;
|
|
730
|
+
lateSignup = {
|
|
731
|
+
by_user_id: context.userId ?? null,
|
|
732
|
+
by_email: by,
|
|
733
|
+
by_name: data.acceptedByName ?? by,
|
|
734
|
+
at: new Date().toISOString(),
|
|
735
|
+
delivery_date: data.deliveryDate.slice(0, 10),
|
|
736
|
+
signup_deadline: preview?.chosen?.signupDeadline ?? null,
|
|
737
|
+
reason: d.reason,
|
|
738
|
+
source: data.source ?? "manual",
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
if (!ownTransport)
|
|
742
|
+
carrierId = preview?.carrierId ?? carrierId;
|
|
743
|
+
if (!ownTransport && !carrierId)
|
|
744
|
+
throw new Error("Er is geen vervoerder bekend voor deze afleverlocatie. Kies een vervoerder.");
|
|
745
|
+
momentKey = d.momentKey;
|
|
746
|
+
if (!ownTransport)
|
|
747
|
+
deliveryTime = await deliveryTimeForMoment(context.supabase, carrierId, momentKey);
|
|
719
748
|
}
|
|
720
749
|
const { supabaseAdmin } = await import("../integrations/supabase/client.server.js");
|
|
721
750
|
// Zorg dat elk product_id (= identiteit uit de voorraadmodule) een rij
|
|
@@ -829,8 +858,12 @@ export const createManualOrder = createServerFn({ method: "POST" })
|
|
|
829
858
|
source: "manual",
|
|
830
859
|
delivery_location: data.deliveryLocationId,
|
|
831
860
|
pickup_location: data.pickupLocationId,
|
|
832
|
-
carrier:
|
|
861
|
+
carrier: carrierId,
|
|
833
862
|
delivery_time: deliveryTime,
|
|
863
|
+
pickup_moment: momentKey,
|
|
864
|
+
...(lateSignup ? { late_signup_override: lateSignup } : {}),
|
|
865
|
+
...(ownTransportInfo ? { own_transport: ownTransportInfo } : {}),
|
|
866
|
+
...(data.customerReference ? { customer_reference: data.customerReference } : {}),
|
|
834
867
|
is_reservation: !!data.isReservation,
|
|
835
868
|
load_carrier_type: loadCarrierType,
|
|
836
869
|
},
|
|
@@ -1036,6 +1069,7 @@ export const deleteMailboxProposal = createServerFn({ method: "POST" })
|
|
|
1036
1069
|
const UpdateLocalOrderInput = z.object({
|
|
1037
1070
|
orderId: z.string().uuid(),
|
|
1038
1071
|
deliveryDate: z.string().min(1).max(50).optional(),
|
|
1072
|
+
acceptLateSignup: z.boolean().optional(),
|
|
1039
1073
|
items: z
|
|
1040
1074
|
.array(z.object({
|
|
1041
1075
|
itemId: z.string().uuid(),
|
|
@@ -1255,7 +1289,7 @@ export const updateLocalOrder = createServerFn({ method: "POST" })
|
|
|
1255
1289
|
const { supabaseAdmin } = await import("../integrations/supabase/client.server.js");
|
|
1256
1290
|
const { data: order, error: oErr } = await supabaseAdmin
|
|
1257
1291
|
.from("orders")
|
|
1258
|
-
.select("id, custom_fields, order_source, is_reservation, plan_locked_at")
|
|
1292
|
+
.select("id, custom_fields, order_source, is_reservation, plan_locked_at, delivery_date")
|
|
1259
1293
|
.eq("id", data.orderId)
|
|
1260
1294
|
.maybeSingle();
|
|
1261
1295
|
if (oErr)
|
|
@@ -1378,23 +1412,45 @@ export const updateLocalOrder = createServerFn({ method: "POST" })
|
|
|
1378
1412
|
}
|
|
1379
1413
|
// Leverdatum bijwerken (alleen als niet-reservering).
|
|
1380
1414
|
if (data.deliveryDate && !order.is_reservation) {
|
|
1381
|
-
//
|
|
1415
|
+
// Haalbaarheid en moment alleen via de Engine; geen eigen berekening.
|
|
1382
1416
|
let newDeliveryTime = cf?.delivery_time ?? null;
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
const
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1417
|
+
let newMoment = cf?.pickup_moment ?? null;
|
|
1418
|
+
let lateOverride = cf?.late_signup_override ?? null;
|
|
1419
|
+
const newDate = String(data.deliveryDate).slice(0, 10);
|
|
1420
|
+
if (newDate !== String(order.delivery_date ?? "").slice(0, 10) && cf?.delivery_location) {
|
|
1421
|
+
const { loadDeparturePreview, deliveryTimeForMoment } = await import("./departure-preview.server.js");
|
|
1422
|
+
const { decidePreview } = await import("./departure-preview.js");
|
|
1423
|
+
const preview = await loadDeparturePreview(context.supabase, {
|
|
1424
|
+
carrierId: cf?.carrier ?? null,
|
|
1425
|
+
deliveryLocation: String(cf.delivery_location),
|
|
1426
|
+
deliveryDate: newDate,
|
|
1427
|
+
momentKey: null,
|
|
1428
|
+
});
|
|
1429
|
+
const d = decidePreview(preview);
|
|
1430
|
+
if (d.kind === "blocked")
|
|
1431
|
+
throw new Error(d.reason);
|
|
1432
|
+
// Vervoerder al vertrokken: ook bij wijzigen nooit doorlaten.
|
|
1433
|
+
if (d.kind === "departed") {
|
|
1434
|
+
throw new Error(d.firstDate ? `${d.reason} De eerstvolgende leverdatum is ${d.firstDate}.` : d.reason);
|
|
1435
|
+
}
|
|
1436
|
+
if (d.kind === "late") {
|
|
1437
|
+
if (!data.acceptLateSignup) {
|
|
1438
|
+
throw new Error(d.firstDate ? `${d.reason} De eerste haalbare leverdatum is ${d.firstDate}.` : d.reason);
|
|
1439
|
+
}
|
|
1440
|
+
const by = context.claims?.email ?? null;
|
|
1441
|
+
lateOverride = {
|
|
1442
|
+
by_user_id: context.userId ?? null, by_email: by, by_name: by,
|
|
1443
|
+
at: new Date().toISOString(), delivery_date: newDate,
|
|
1444
|
+
signup_deadline: preview?.chosen?.signupDeadline ?? null, reason: d.reason, source: "manual",
|
|
1445
|
+
};
|
|
1446
|
+
}
|
|
1447
|
+
newMoment = d.momentKey;
|
|
1448
|
+
newDeliveryTime = await deliveryTimeForMoment(context.supabase, cf?.carrier ?? null, newMoment);
|
|
1393
1449
|
}
|
|
1394
1450
|
const { error: uErr } = await supabaseAdmin.from("orders")
|
|
1395
1451
|
.update({
|
|
1396
1452
|
delivery_date: data.deliveryDate,
|
|
1397
|
-
custom_fields: { ...(cf ?? {}), delivery_time: newDeliveryTime },
|
|
1453
|
+
custom_fields: { ...(cf ?? {}), delivery_time: newDeliveryTime, pickup_moment: newMoment, ...(lateOverride ? { late_signup_override: lateOverride } : {}) },
|
|
1398
1454
|
updated_at: new Date().toISOString(),
|
|
1399
1455
|
})
|
|
1400
1456
|
.eq("id", data.orderId);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"departure-preview.check.d.ts","sourceRoot":"","sources":["../../src/lib/departure-preview.check.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// Controle voorbeeld-ophaalmoment. Draai: bun src/lib/departure-preview.check.ts
|
|
2
|
+
import { decidePreview, normalizePreview, firstDateText } from "./departure-preview.js";
|
|
3
|
+
// Vaste "nu" zodat de controles niet verouderen.
|
|
4
|
+
Date.now = () => Date.parse("2026-10-19T12:00:00Z");
|
|
5
|
+
import { LIST_CHUNK } from "./order-departure.server.js";
|
|
6
|
+
let failed = 0;
|
|
7
|
+
function check(name, got, want) {
|
|
8
|
+
const ok = got === want;
|
|
9
|
+
if (!ok)
|
|
10
|
+
failed++;
|
|
11
|
+
console.log(`${ok ? "OK " : "FOUT"} ${name}: ${got}${ok ? "" : ` (verwacht ${want})`}`);
|
|
12
|
+
}
|
|
13
|
+
const good = decidePreview(normalizePreview({
|
|
14
|
+
ok: true, carrierId: "c", deliveryDateFeasible: true,
|
|
15
|
+
moments: [{ momentKey: "1@15:00|1@13:00", departureAt: "2026-10-20T13:00:00Z", signupDeadline: "2026-10-20T11:00:00Z", feasible: true },
|
|
16
|
+
{ momentKey: "1@09:00|1@07:00", departureAt: "2026-10-20T07:00:00Z", signupDeadline: "2026-10-20T05:00:00Z", feasible: false }],
|
|
17
|
+
chosen: { momentKey: "1@15:00|1@13:00", departureAt: "2026-10-20T13:00:00Z", signupDeadline: "2026-10-20T11:00:00Z" },
|
|
18
|
+
}));
|
|
19
|
+
check("haalbaar: soort", good.kind, "ok");
|
|
20
|
+
check("haalbaar: tekst", good.kind === "ok" ? good.text : null, "ophalen di 20 okt 15:00 · aanmelden di 20 okt 13:00");
|
|
21
|
+
check("niet-haalbaar moment blijft zichtbaar", normalizePreview({ ok: true, moments: [{ momentKey: "x", feasible: false }] })?.moments[0].feasible, false);
|
|
22
|
+
const late = decidePreview(normalizePreview({
|
|
23
|
+
ok: true, deliveryDateFeasible: false, reason: "Aanmelden kan tot di 20-10 13:00.",
|
|
24
|
+
firstFeasibleDeliveryDate: "2026-10-22", firstFeasibleReason: "Eerstvolgende aanmelding do 13:00",
|
|
25
|
+
chosen: { momentKey: "k", departureAt: "2026-10-20T13:00:00Z" },
|
|
26
|
+
}));
|
|
27
|
+
check("te laat: soort (toch aanmaken mogelijk)", late.kind, "late");
|
|
28
|
+
check("te laat: reden", late.kind === "late" ? late.reason : null, "Aanmelden kan tot di 20-10 13:00.");
|
|
29
|
+
check("te laat: eerste datum", late.kind === "late" ? late.firstDate : null, "2026-10-22");
|
|
30
|
+
const bad = decidePreview(normalizePreview({ ok: false, reason: "Geen vervoerder bekend", chosen: { departureAt: "2026-10-20T13:00:00Z" } }));
|
|
31
|
+
check("ok=false: geblokkeerd", bad.kind, "blocked");
|
|
32
|
+
check("ok=false: alleen reden", bad.kind === "blocked" ? bad.reason : null, "Geen vervoerder bekend");
|
|
33
|
+
check("geen antwoord: geblokkeerd", decidePreview(null).kind, "blocked");
|
|
34
|
+
check("lijst in delen van 1000", LIST_CHUNK, 1000);
|
|
35
|
+
// Vervoerder al vertrokken (HO-2601443): aanmeldtijd én ophaalmoment voorbij → niet "toch aanmaken".
|
|
36
|
+
const gone = decidePreview(normalizePreview({
|
|
37
|
+
ok: true, deliveryDateFeasible: false, reason: "Aanmelden kon tot ma 19-10 13:00",
|
|
38
|
+
chosen: { momentKey: "k", departureAt: "2026-10-19T13:00:00Z" },
|
|
39
|
+
firstFeasibleDeliveryDate: "2026-10-21",
|
|
40
|
+
}), Date.parse("2026-10-19T20:58:00Z"));
|
|
41
|
+
check("vertrokken (afgeleid uit vertrekmoment)", gone.kind, "departed");
|
|
42
|
+
check("vertrokken: eerste datum", gone.kind === "departed" ? gone.firstDate : null, "2026-10-21");
|
|
43
|
+
const lateNotGone = decidePreview(normalizePreview({
|
|
44
|
+
ok: true, deliveryDateFeasible: false, chosen: { momentKey: "k", departureAt: "2026-10-19T13:00:00Z" },
|
|
45
|
+
}), Date.parse("2026-10-19T11:30:00Z"));
|
|
46
|
+
check("aanmeldtijd voorbij, ophalen nog niet: te laat", lateNotGone.kind, "late");
|
|
47
|
+
const engineSays = decidePreview(normalizePreview({
|
|
48
|
+
ok: true, deliveryDateFeasible: true,
|
|
49
|
+
chosen: { momentKey: "k", departureAt: "2026-10-30T13:00:00Z", departed: true },
|
|
50
|
+
nextFeasibleMoment: { momentKey: "n", departureAt: "x", signupDeadline: null, deliveryDate: "2026-10-31" },
|
|
51
|
+
}));
|
|
52
|
+
check("Engine-veld departed gaat voor", engineSays.kind, "departed");
|
|
53
|
+
check("volgende moment uit Engine", engineSays.kind === "departed" ? engineSays.firstDate : null, "2026-10-31");
|
|
54
|
+
check("eigen vervoer: nooit vertrokken", decidePreview(normalizePreview({ ok: true, ownTransport: true, deliveryDateFeasible: true, chosen: { departureAt: "2026-10-01T10:00:00Z" } })).kind, "ok");
|
|
55
|
+
check("tekst eerste leverdatum", firstDateText("2026-10-21", "2026-10-20T11:00:00Z"), "Eerst mogelijke leverdatum: woensdag 21 oktober (aanmelden vóór dinsdag 13:00).");
|
|
56
|
+
if (failed) {
|
|
57
|
+
console.error(`${failed} controle(s) mislukt`);
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
console.log("Alle controles geslaagd");
|