@final-commerce/common 2.4.0-staging.2 → 2.4.1-staging2.1
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/index.d.mts +19 -201
- package/dist/index.d.ts +19 -201
- package/dist/index.js +53 -472
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +41 -452
- package/dist/index.mjs.map +1 -1
- package/dist/pos-types/index.d.mts +18 -147
- package/dist/pos-types/index.d.ts +18 -147
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -422,7 +422,6 @@ var StripeCurrencyCode = /* @__PURE__ */ ((StripeCurrencyCode2) => {
|
|
|
422
422
|
var ProductType = /* @__PURE__ */ ((ProductType2) => {
|
|
423
423
|
ProductType2["SIMPLE"] = "simple";
|
|
424
424
|
ProductType2["VARIABLE"] = "variable";
|
|
425
|
-
ProductType2["BOOKING"] = "booking";
|
|
426
425
|
return ProductType2;
|
|
427
426
|
})(ProductType || {});
|
|
428
427
|
var ProductStatus = /* @__PURE__ */ ((ProductStatus2) => {
|
|
@@ -440,50 +439,6 @@ var PaymentProcessor = /* @__PURE__ */ ((PaymentProcessor2) => {
|
|
|
440
439
|
return PaymentProcessor2;
|
|
441
440
|
})(PaymentProcessor || {});
|
|
442
441
|
|
|
443
|
-
// enums/booking.enum.ts
|
|
444
|
-
var BookingType = /* @__PURE__ */ ((BookingType3) => {
|
|
445
|
-
BookingType3["RENTAL"] = "rental";
|
|
446
|
-
BookingType3["APPOINTMENT"] = "appointment";
|
|
447
|
-
BookingType3["OVERNIGHT"] = "overnight";
|
|
448
|
-
BookingType3["GROUP"] = "group";
|
|
449
|
-
return BookingType3;
|
|
450
|
-
})(BookingType || {});
|
|
451
|
-
var BookingRatePeriod = /* @__PURE__ */ ((BookingRatePeriod2) => {
|
|
452
|
-
BookingRatePeriod2["SLOT"] = "slot";
|
|
453
|
-
BookingRatePeriod2["DAY"] = "day";
|
|
454
|
-
BookingRatePeriod2["NIGHT"] = "night";
|
|
455
|
-
BookingRatePeriod2["WEEK"] = "week";
|
|
456
|
-
BookingRatePeriod2["MONTH"] = "month";
|
|
457
|
-
return BookingRatePeriod2;
|
|
458
|
-
})(BookingRatePeriod || {});
|
|
459
|
-
var BookingResourceKind = /* @__PURE__ */ ((BookingResourceKind2) => {
|
|
460
|
-
BookingResourceKind2["ASSET"] = "asset";
|
|
461
|
-
BookingResourceKind2["ROOM"] = "room";
|
|
462
|
-
BookingResourceKind2["PROPERTY"] = "property";
|
|
463
|
-
BookingResourceKind2["SPACE"] = "space";
|
|
464
|
-
BookingResourceKind2["STAFF"] = "staff";
|
|
465
|
-
BookingResourceKind2["TABLE"] = "table";
|
|
466
|
-
return BookingResourceKind2;
|
|
467
|
-
})(BookingResourceKind || {});
|
|
468
|
-
var ReservationStatus = /* @__PURE__ */ ((ReservationStatus2) => {
|
|
469
|
-
ReservationStatus2["HELD"] = "held";
|
|
470
|
-
ReservationStatus2["CONFIRMED"] = "confirmed";
|
|
471
|
-
ReservationStatus2["CANCELLED"] = "cancelled";
|
|
472
|
-
ReservationStatus2["EXPIRED"] = "expired";
|
|
473
|
-
return ReservationStatus2;
|
|
474
|
-
})(ReservationStatus || {});
|
|
475
|
-
var BookingResourceStatus = /* @__PURE__ */ ((BookingResourceStatus2) => {
|
|
476
|
-
BookingResourceStatus2["ACTIVE"] = "active";
|
|
477
|
-
BookingResourceStatus2["INACTIVE"] = "inactive";
|
|
478
|
-
return BookingResourceStatus2;
|
|
479
|
-
})(BookingResourceStatus || {});
|
|
480
|
-
var ResourceAvailabilityState = /* @__PURE__ */ ((ResourceAvailabilityState2) => {
|
|
481
|
-
ResourceAvailabilityState2["AVAILABLE"] = "available";
|
|
482
|
-
ResourceAvailabilityState2["FULLY_BOOKED"] = "fullyBooked";
|
|
483
|
-
ResourceAvailabilityState2["NO_HOURS_IN_RANGE"] = "noHoursInRange";
|
|
484
|
-
return ResourceAvailabilityState2;
|
|
485
|
-
})(ResourceAvailabilityState || {});
|
|
486
|
-
|
|
487
442
|
// utils/currency.util.ts
|
|
488
443
|
var CURRENCY_CONFIG = {
|
|
489
444
|
// Major currencies with 2 decimal places
|
|
@@ -1695,15 +1650,6 @@ function sumRefundQuantities(refunds) {
|
|
|
1695
1650
|
}
|
|
1696
1651
|
return t;
|
|
1697
1652
|
}
|
|
1698
|
-
var asCount = (value) => typeof value === "number" && Number.isFinite(value) ? Math.max(0, value) : 0;
|
|
1699
|
-
function countsOf(row) {
|
|
1700
|
-
const quantity = asCount(row.quantity);
|
|
1701
|
-
return {
|
|
1702
|
-
quantity,
|
|
1703
|
-
fulfilled: Math.min(asCount(row.fulfilledQuantity), quantity),
|
|
1704
|
-
returned: Math.min(asCount(row.returnedQuantity), quantity)
|
|
1705
|
-
};
|
|
1706
|
-
}
|
|
1707
1653
|
function buildOrderContext(order, extras) {
|
|
1708
1654
|
const o = order ?? {};
|
|
1709
1655
|
const total = typeof o.total === "number" && Number.isFinite(o.total) ? o.total : 0;
|
|
@@ -1711,7 +1657,6 @@ function buildOrderContext(order, extras) {
|
|
|
1711
1657
|
const paymentMethods = o.paymentMethods ?? [];
|
|
1712
1658
|
const refunds = o.refunds ?? o.refund ?? [];
|
|
1713
1659
|
const lineItems = o.lineItems ?? [];
|
|
1714
|
-
const reservations = o.reservations ?? [];
|
|
1715
1660
|
const totalPaid = sumNumbers(paymentMethods);
|
|
1716
1661
|
const totalRefunded = sumRefundQuantities(refunds);
|
|
1717
1662
|
const isFullyPaid = total > 0 ? balance <= 0 : totalPaid > 0 && balance <= 0;
|
|
@@ -1719,11 +1664,13 @@ function buildOrderContext(order, extras) {
|
|
|
1719
1664
|
let itemCount = 0;
|
|
1720
1665
|
let fulfilledItemCount = 0;
|
|
1721
1666
|
let returnedItemCount = 0;
|
|
1722
|
-
for (const
|
|
1723
|
-
const
|
|
1724
|
-
itemCount +=
|
|
1725
|
-
|
|
1726
|
-
|
|
1667
|
+
for (const li of lineItems) {
|
|
1668
|
+
const q = typeof li.quantity === "number" && Number.isFinite(li.quantity) ? Math.max(0, li.quantity) : 0;
|
|
1669
|
+
itemCount += q;
|
|
1670
|
+
const fq = typeof li.fulfilledQuantity === "number" && Number.isFinite(li.fulfilledQuantity) ? Math.max(0, li.fulfilledQuantity) : 0;
|
|
1671
|
+
fulfilledItemCount += Math.min(fq, q);
|
|
1672
|
+
const rq = typeof li.returnedQuantity === "number" && Number.isFinite(li.returnedQuantity) ? Math.max(0, li.returnedQuantity) : 0;
|
|
1673
|
+
returnedItemCount += Math.min(rq, q);
|
|
1727
1674
|
}
|
|
1728
1675
|
const isFullyReturned = itemCount > 0 ? returnedItemCount >= itemCount : returnedItemCount > 0;
|
|
1729
1676
|
const hasPartialReturns = returnedItemCount > 0 && !isFullyReturned;
|
|
@@ -1733,8 +1680,7 @@ function buildOrderContext(order, extras) {
|
|
|
1733
1680
|
balance,
|
|
1734
1681
|
paymentMethods,
|
|
1735
1682
|
refunds,
|
|
1736
|
-
lineItems
|
|
1737
|
-
reservations
|
|
1683
|
+
lineItems
|
|
1738
1684
|
},
|
|
1739
1685
|
computed: {
|
|
1740
1686
|
balance,
|
|
@@ -2814,391 +2760,43 @@ var ORDER_STATE_EVENTS = {
|
|
|
2814
2760
|
configUpdated: "config-updated"
|
|
2815
2761
|
};
|
|
2816
2762
|
|
|
2817
|
-
//
|
|
2818
|
-
var
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
this.name = "BookingRulesError";
|
|
2822
|
-
}
|
|
2823
|
-
};
|
|
2824
|
-
|
|
2825
|
-
// booking/zoned-time.ts
|
|
2826
|
-
var MINUTE = 6e4;
|
|
2827
|
-
var formatters = /* @__PURE__ */ new Map();
|
|
2828
|
-
var formatterFor = (timeZone) => {
|
|
2829
|
-
const existing = formatters.get(timeZone);
|
|
2830
|
-
if (existing) return existing;
|
|
2831
|
-
let created;
|
|
2832
|
-
try {
|
|
2833
|
-
created = new Intl.DateTimeFormat("en-US", {
|
|
2834
|
-
timeZone,
|
|
2835
|
-
hour12: false,
|
|
2836
|
-
year: "numeric",
|
|
2837
|
-
month: "2-digit",
|
|
2838
|
-
day: "2-digit",
|
|
2839
|
-
hour: "2-digit",
|
|
2840
|
-
minute: "2-digit",
|
|
2841
|
-
second: "2-digit",
|
|
2842
|
-
weekday: "short"
|
|
2843
|
-
});
|
|
2844
|
-
} catch {
|
|
2845
|
-
throw new BookingRulesError(`Booking rules: "${timeZone}" is not a known time zone`);
|
|
2846
|
-
}
|
|
2847
|
-
formatters.set(timeZone, created);
|
|
2848
|
-
return created;
|
|
2849
|
-
};
|
|
2850
|
-
var WEEKDAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
2851
|
-
function zonedParts(instant, timeZone) {
|
|
2852
|
-
const parts = {};
|
|
2853
|
-
for (const { type, value } of formatterFor(timeZone).formatToParts(instant)) parts[type] = value;
|
|
2854
|
-
const hour = Number(parts.hour) % 24;
|
|
2855
|
-
return {
|
|
2856
|
-
year: Number(parts.year),
|
|
2857
|
-
month: Number(parts.month),
|
|
2858
|
-
day: Number(parts.day),
|
|
2859
|
-
hour,
|
|
2860
|
-
minute: Number(parts.minute),
|
|
2861
|
-
second: Number(parts.second),
|
|
2862
|
-
weekday: WEEKDAYS.indexOf(parts.weekday)
|
|
2863
|
-
};
|
|
2864
|
-
}
|
|
2865
|
-
function offsetAt(instant, timeZone) {
|
|
2866
|
-
const { year, month, day, hour, minute, second } = zonedParts(instant, timeZone);
|
|
2867
|
-
return Date.UTC(year, month - 1, day, hour, minute, second) - Math.floor(instant.getTime() / 1e3) * 1e3;
|
|
2868
|
-
}
|
|
2869
|
-
function instantFromLocal(year, month, day, minutes, timeZone) {
|
|
2870
|
-
const naive = Date.UTC(year, month - 1, day) + minutes * MINUTE;
|
|
2871
|
-
const firstGuess = naive - offsetAt(new Date(naive), timeZone);
|
|
2872
|
-
return new Date(naive - offsetAt(new Date(firstGuess), timeZone));
|
|
2873
|
-
}
|
|
2874
|
-
function startOfZonedDay(instant, timeZone) {
|
|
2875
|
-
const { year, month, day } = zonedParts(instant, timeZone);
|
|
2876
|
-
return instantFromLocal(year, month, day, 0, timeZone);
|
|
2877
|
-
}
|
|
2878
|
-
function nextZonedDay(dayStart, timeZone) {
|
|
2879
|
-
const { year, month, day } = zonedParts(dayStart, timeZone);
|
|
2880
|
-
return instantFromLocal(year, month, day + 1, 0, timeZone);
|
|
2881
|
-
}
|
|
2882
|
-
function atZonedMinute(dayStart, minutes, timeZone) {
|
|
2883
|
-
const { year, month, day } = zonedParts(dayStart, timeZone);
|
|
2884
|
-
return instantFromLocal(year, month, day, minutes, timeZone);
|
|
2763
|
+
// constants/adyen.constants.ts
|
|
2764
|
+
var ADYEN_ROLLOUT_COUNTRY_CODES = /* @__PURE__ */ new Set(["CA"]);
|
|
2765
|
+
function isAdyenRolloutCountry(alpha2) {
|
|
2766
|
+
return ADYEN_ROLLOUT_COUNTRY_CODES.has(alpha2);
|
|
2885
2767
|
}
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
var MAX_RANGE_DAYS = 366;
|
|
2890
|
-
var asTime = (value, field) => {
|
|
2891
|
-
if (value == null) return void 0;
|
|
2892
|
-
const time = new Date(value).getTime();
|
|
2893
|
-
if (Number.isNaN(time)) throw new BookingRulesError(`Booking rules: ${field} is not a date, got "${String(value)}"`);
|
|
2894
|
-
return time;
|
|
2895
|
-
};
|
|
2896
|
-
function parseHhMm(value, field) {
|
|
2897
|
-
const [hours, minutes] = value.split(":").map(Number);
|
|
2898
|
-
if (!Number.isInteger(hours) || !Number.isInteger(minutes)) {
|
|
2899
|
-
throw new BookingRulesError(`Booking rules: ${field} must be "HH:mm", got "${value}"`);
|
|
2900
|
-
}
|
|
2901
|
-
return hours * 60 + minutes;
|
|
2902
|
-
}
|
|
2903
|
-
function windowEndsAt(rule, now) {
|
|
2904
|
-
const { maxAdvanceDays, bookableTo } = rule.window;
|
|
2905
|
-
const ends = Math.min(
|
|
2906
|
-
maxAdvanceDays ? now.getTime() + maxAdvanceDays * 1440 * MINUTE2 : Number.POSITIVE_INFINITY,
|
|
2907
|
-
asTime(bookableTo, "window.bookableTo") ?? Number.POSITIVE_INFINITY
|
|
2908
|
-
);
|
|
2909
|
-
return Number.isFinite(ends) ? new Date(ends) : null;
|
|
2910
|
-
}
|
|
2911
|
-
function periodSlot(dayStart, timeZone, rule, openMinute, closeMinute) {
|
|
2912
|
-
const { ratePeriod, slot, checkInTime, checkOutTime } = rule;
|
|
2913
|
-
const at = (minutes) => atZonedMinute(dayStart, minutes, timeZone);
|
|
2914
|
-
if (ratePeriod === "night" /* NIGHT */) {
|
|
2915
|
-
if (!checkInTime || !checkOutTime) {
|
|
2916
|
-
throw new BookingRulesError("Overnight booking rules need both checkInTime and checkOutTime");
|
|
2917
|
-
}
|
|
2918
|
-
const checkIn = parseHhMm(checkInTime, "checkInTime");
|
|
2919
|
-
const checkOut = parseHhMm(checkOutTime, "checkOutTime");
|
|
2920
|
-
return {
|
|
2921
|
-
startAt: at(checkIn),
|
|
2922
|
-
endAt: at(1440 + checkOut),
|
|
2923
|
-
// Housekeeping sits between check-out and the next check-in: it costs no night.
|
|
2924
|
-
bufferEndAt: at(1440 + checkIn),
|
|
2925
|
-
canStart: true
|
|
2926
|
-
};
|
|
2927
|
-
}
|
|
2928
|
-
const from = ratePeriod === "day" /* DAY */ ? openMinute ?? 0 : 0;
|
|
2929
|
-
const to = ratePeriod === "day" /* DAY */ ? closeMinute ?? 1440 : 1440;
|
|
2930
|
-
return {
|
|
2931
|
-
startAt: at(from),
|
|
2932
|
-
endAt: at(to),
|
|
2933
|
-
bufferEndAt: at(to + (slot.bufferMinutes ?? 0)),
|
|
2934
|
-
canStart: true
|
|
2935
|
-
};
|
|
2768
|
+
var ADYEN_STORE_STATE_PROVINCE_COUNTRIES = /* @__PURE__ */ new Set(["AU", "BR", "CA", "IN", "MX", "NZ", "US"]);
|
|
2769
|
+
function adyenStoreRequiresStateOrProvince(alpha2) {
|
|
2770
|
+
return !!alpha2 && ADYEN_STORE_STATE_PROVINCE_COUNTRIES.has(alpha2);
|
|
2936
2771
|
}
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
let cursor = openAt;
|
|
2941
|
-
for (const { from, to } of inside) {
|
|
2942
|
-
if (from > cursor) gaps.push({ from: cursor, to: from, endsAtBooking: true });
|
|
2943
|
-
cursor = Math.max(cursor, to);
|
|
2944
|
-
if (cursor >= closeAt) break;
|
|
2945
|
-
}
|
|
2946
|
-
if (cursor < closeAt) gaps.push({ from: cursor, to: closeAt, endsAtBooking: false });
|
|
2947
|
-
return gaps;
|
|
2948
|
-
}
|
|
2949
|
-
function buildGrid(rule, timeZone, from, to, now, busy = []) {
|
|
2950
|
-
if (to.getTime() - from.getTime() > MAX_RANGE_DAYS * 1440 * MINUTE2) {
|
|
2951
|
-
throw new BookingRulesError(`A booking range may span at most ${MAX_RANGE_DAYS} days`);
|
|
2952
|
-
}
|
|
2953
|
-
const { availability, slot, window, ratePeriod } = rule;
|
|
2954
|
-
const periodMode = ratePeriod !== "slot" /* SLOT */;
|
|
2955
|
-
const weeklyHours = availability.weeklyHours ?? [];
|
|
2956
|
-
const notBefore = Math.max(
|
|
2957
|
-
now.getTime() + (window.minNoticeMinutes ?? 0) * MINUTE2,
|
|
2958
|
-
asTime(window.bookableFrom, "window.bookableFrom") ?? 0,
|
|
2959
|
-
asTime(availability.availableFrom, "availability.availableFrom") ?? 0
|
|
2960
|
-
);
|
|
2961
|
-
const notAfter = windowEndsAt(rule, now)?.getTime() ?? Number.POSITIVE_INFINITY;
|
|
2962
|
-
const blocked = (availability.offMarket ?? []).map(({ from: blockFrom, to: blockTo }) => ({
|
|
2963
|
-
from: asTime(blockFrom, "availability.offMarket.from"),
|
|
2964
|
-
to: asTime(blockTo, "availability.offMarket.to")
|
|
2965
|
-
}));
|
|
2966
|
-
const arrivalDays = availability.arrivalDays;
|
|
2967
|
-
const step = slot.lengthMinutes + (slot.bufferMinutes ?? 0);
|
|
2968
|
-
const slots = [];
|
|
2969
|
-
const lastDay = startOfZonedDay(to, timeZone).getTime();
|
|
2970
|
-
let dayStart = startOfZonedDay(from, timeZone);
|
|
2971
|
-
while (dayStart.getTime() <= lastDay) {
|
|
2972
|
-
const weekday = zonedParts(dayStart, timeZone).weekday;
|
|
2973
|
-
const rows = weeklyHours.filter((entry) => entry.weekday === weekday);
|
|
2974
|
-
if (periodMode) {
|
|
2975
|
-
const openToday = weeklyHours.length === 0 || rows.length > 0;
|
|
2976
|
-
if (openToday) {
|
|
2977
|
-
const built = periodSlot(dayStart, timeZone, rule, rows[0]?.openMinute, rows[0]?.closeMinute);
|
|
2978
|
-
slots.push({ ...built, canStart: !arrivalDays?.length || arrivalDays.includes(weekday) });
|
|
2979
|
-
}
|
|
2980
|
-
} else {
|
|
2981
|
-
for (const row of rows) {
|
|
2982
|
-
const openAt = +atZonedMinute(dayStart, row.openMinute, timeZone);
|
|
2983
|
-
const closeAt = +atZonedMinute(dayStart, row.closeMinute, timeZone);
|
|
2984
|
-
for (const gap of freeGaps(openAt, closeAt, busy)) {
|
|
2985
|
-
const mustFit = (gap.endsAtBooking ? step : slot.lengthMinutes) * MINUTE2;
|
|
2986
|
-
for (let start = gap.from; start + mustFit <= gap.to; start += step * MINUTE2) {
|
|
2987
|
-
slots.push({
|
|
2988
|
-
startAt: new Date(start),
|
|
2989
|
-
endAt: new Date(start + slot.lengthMinutes * MINUTE2),
|
|
2990
|
-
bufferEndAt: new Date(start + step * MINUTE2),
|
|
2991
|
-
canStart: true
|
|
2992
|
-
});
|
|
2993
|
-
}
|
|
2994
|
-
}
|
|
2995
|
-
}
|
|
2996
|
-
}
|
|
2997
|
-
dayStart = nextZonedDay(dayStart, timeZone);
|
|
2998
|
-
}
|
|
2999
|
-
const askedFrom = from.getTime();
|
|
3000
|
-
const askedTo = to.getTime();
|
|
3001
|
-
return slots.filter(({ startAt, bufferEndAt }) => {
|
|
3002
|
-
const start = startAt.getTime();
|
|
3003
|
-
if (start < askedFrom || start >= askedTo) return false;
|
|
3004
|
-
if (start < notBefore || start > notAfter) return false;
|
|
3005
|
-
return !blocked.some(({ from: blockFrom, to: blockTo }) => start < blockTo && bufferEndAt.getTime() > blockFrom);
|
|
3006
|
-
}).sort((first, second) => +first.startAt - +second.startAt);
|
|
3007
|
-
}
|
|
3008
|
-
function slotsForWindow(grid, startAt, endAt) {
|
|
3009
|
-
const startIndex = grid.findIndex((entry) => entry.startAt.getTime() === startAt.getTime());
|
|
3010
|
-
if (startIndex < 0) {
|
|
3011
|
-
throw new BookingRulesError(`${startAt.toISOString()} is not a bookable slot start for these rules`);
|
|
3012
|
-
}
|
|
3013
|
-
if (!grid[startIndex].canStart) {
|
|
3014
|
-
throw new BookingRulesError(`${startAt.toISOString()} is not an arrival day for these rules`);
|
|
3015
|
-
}
|
|
3016
|
-
const covered = [];
|
|
3017
|
-
for (let index = startIndex; index < grid.length; index++) {
|
|
3018
|
-
const entry = grid[index];
|
|
3019
|
-
const previous = covered[covered.length - 1];
|
|
3020
|
-
if (previous && entry.startAt.getTime() !== previous.bufferEndAt.getTime()) break;
|
|
3021
|
-
covered.push(entry);
|
|
3022
|
-
if (entry.endAt.getTime() === endAt.getTime()) return covered;
|
|
3023
|
-
if (entry.endAt.getTime() > endAt.getTime()) break;
|
|
3024
|
-
}
|
|
3025
|
-
throw new BookingRulesError(
|
|
3026
|
-
`${startAt.toISOString()} \u2192 ${endAt.toISOString()} does not line up with the bookable grid`
|
|
3027
|
-
);
|
|
2772
|
+
var ADYEN_LEGAL_ENTITY_STATE_PROVINCE_COUNTRIES = /* @__PURE__ */ new Set(["AU", "BR", "CA", "IN", "MX", "NZ", "US"]);
|
|
2773
|
+
function adyenLegalEntityRequiresStateOrProvince(alpha2) {
|
|
2774
|
+
return !!alpha2 && ADYEN_LEGAL_ENTITY_STATE_PROVINCE_COUNTRIES.has(alpha2);
|
|
3028
2775
|
}
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
if (!presence?.length) return true;
|
|
3033
|
-
const dayStart = startOfZonedDay(slot.startAt, timeZone);
|
|
3034
|
-
const weekday = zonedParts(dayStart, timeZone).weekday;
|
|
3035
|
-
return presence.some(
|
|
3036
|
-
(shift) => shift.weekday === weekday && slot.startAt.getTime() >= atZonedMinute(dayStart, shift.openMinute, timeZone).getTime() && slot.endAt.getTime() <= atZonedMinute(dayStart, shift.closeMinute, timeZone).getTime()
|
|
3037
|
-
);
|
|
3038
|
-
};
|
|
3039
|
-
var overlaps = (entry, startAt, bufferEndAt) => entry.startAt.getTime() < bufferEndAt.getTime() && entry.bufferEndAt.getTime() > startAt.getTime();
|
|
3040
|
-
function occupancyIn(occupied, productId, startAt, bufferEndAt, shared) {
|
|
3041
|
-
const clashing = occupied.filter((entry) => overlaps(entry, startAt, bufferEndAt));
|
|
3042
|
-
const foreign = shared ? void 0 : clashing.find((entry) => entry.productId !== productId);
|
|
3043
|
-
return {
|
|
3044
|
-
taken: clashing.filter((entry) => shared || entry.productId === productId).reduce((sum, entry) => sum + entry.qty, 0),
|
|
3045
|
-
foreignProductId: foreign?.productId
|
|
3046
|
-
};
|
|
2776
|
+
var ADYEN_NO_TAX_NUMBER_ABSENT_COUNTRIES = /* @__PURE__ */ new Set(["CA"]);
|
|
2777
|
+
function adyenSupportsTaxNumberAbsent(alpha2) {
|
|
2778
|
+
return !!alpha2 && !ADYEN_NO_TAX_NUMBER_ABSENT_COUNTRIES.has(alpha2);
|
|
3047
2779
|
}
|
|
3048
|
-
var
|
|
3049
|
-
|
|
3050
|
-
return hasShift() ? "fullyBooked" /* FULLY_BOOKED */ : "noHoursInRange" /* NO_HOURS_IN_RANGE */;
|
|
3051
|
-
}
|
|
3052
|
-
return free === 0 ? "fullyBooked" /* FULLY_BOOKED */ : "available" /* AVAILABLE */;
|
|
2780
|
+
var ADYEN_TAX_NUMBER_FORMATS = {
|
|
2781
|
+
CA: { pattern: /^\d{9}$/, length: 9 }
|
|
3053
2782
|
};
|
|
3054
|
-
function
|
|
3055
|
-
|
|
3056
|
-
const pad = (value) => String(value).padStart(2, "0");
|
|
3057
|
-
return `${year}-${pad(month)}-${pad(day)}`;
|
|
3058
|
-
}
|
|
3059
|
-
function shopDayRange(fromDayKey, count, timeZone) {
|
|
3060
|
-
const [year, month, day] = fromDayKey.split("-").map(Number);
|
|
3061
|
-
return {
|
|
3062
|
-
from: instantFromLocal(year, month, day, 0, timeZone),
|
|
3063
|
-
to: instantFromLocal(year, month, day + Math.max(1, count), 0, timeZone)
|
|
3064
|
-
};
|
|
3065
|
-
}
|
|
3066
|
-
function buildAvailability({
|
|
3067
|
-
productId,
|
|
3068
|
-
bookingRulesId,
|
|
3069
|
-
bookingType,
|
|
3070
|
-
rule,
|
|
3071
|
-
resources,
|
|
3072
|
-
occupied,
|
|
3073
|
-
from,
|
|
3074
|
-
to,
|
|
3075
|
-
now
|
|
3076
|
-
}) {
|
|
3077
|
-
const shared = rule.slot.sharedAcrossProducts ?? false;
|
|
3078
|
-
const bookableUntil = windowEndsAt(rule, now);
|
|
3079
|
-
const header = {
|
|
3080
|
-
productId,
|
|
3081
|
-
bookingRulesId,
|
|
3082
|
-
bookingType,
|
|
3083
|
-
ratePeriod: rule.ratePeriod,
|
|
3084
|
-
// Passed through for the UI to label: a group slot under minimumToRun may not run.
|
|
3085
|
-
minimumToRun: rule.slot.minimumToRun,
|
|
3086
|
-
minStay: rule.slot.minStay,
|
|
3087
|
-
maxStay: rule.slot.maxStay,
|
|
3088
|
-
// Why a day can come back empty. Past this instant the rule refuses everything, so the UI
|
|
3089
|
-
// can say "beyond the booking window" where it would otherwise claim "nothing free".
|
|
3090
|
-
bookableUntil,
|
|
3091
|
-
// The comparison itself, not just the boundary: deciding whether a day lies past the
|
|
3092
|
-
// window is a rule, and a UI that re-derives it owns a copy of that rule — which is how
|
|
3093
|
-
// the same empty grid ends up explained one way on the till and another in a flow.
|
|
3094
|
-
beyondWindow: !!bookableUntil && from.getTime() > bookableUntil.getTime()
|
|
3095
|
-
};
|
|
3096
|
-
const byResource = /* @__PURE__ */ new Map();
|
|
3097
|
-
for (const entry of occupied) {
|
|
3098
|
-
byResource.set(entry.resourceId, [...byResource.get(entry.resourceId) ?? [], entry]);
|
|
3099
|
-
}
|
|
3100
|
-
const grids = resources.map((resource) => {
|
|
3101
|
-
const mine = byResource.get(resource.id) ?? [];
|
|
3102
|
-
const busy = (resource.seats ?? 1) === 1 ? mine : [];
|
|
3103
|
-
const slots2 = buildGrid(rule, resource.timeZone, from, to, now, busy).filter(
|
|
3104
|
-
(slot) => withinPresence(slot, resource.timeZone, resource.presence)
|
|
3105
|
-
);
|
|
3106
|
-
return { resource, slots: slots2 };
|
|
3107
|
-
});
|
|
3108
|
-
const byInstant = /* @__PURE__ */ new Map();
|
|
3109
|
-
const freeSlotsPerResource = /* @__PURE__ */ new Map();
|
|
3110
|
-
for (const { resource, slots: slots2 } of grids) {
|
|
3111
|
-
const capacity = resource.seats ?? 1;
|
|
3112
|
-
const mine = byResource.get(resource.id) ?? [];
|
|
3113
|
-
for (const slot of slots2) {
|
|
3114
|
-
const { taken, foreignProductId } = occupancyIn(mine, productId, slot.startAt, slot.bufferEndAt, shared);
|
|
3115
|
-
const free = foreignProductId ? 0 : Math.max(capacity - taken, 0);
|
|
3116
|
-
const entry = byInstant.get(+slot.startAt) ?? { ...slot, capacity: 0, booked: 0, free: 0, resources: [], dayKey: shopDayKey(slot.startAt, resource.timeZone) };
|
|
3117
|
-
entry.capacity += capacity;
|
|
3118
|
-
entry.booked += foreignProductId ? capacity : taken;
|
|
3119
|
-
entry.free += free;
|
|
3120
|
-
entry.canStart = entry.canStart || slot.canStart;
|
|
3121
|
-
entry.resources.push({ resourceId: resource.id, name: resource.name, capacity, booked: taken, free });
|
|
3122
|
-
if (free > 0) freeSlotsPerResource.set(resource.id, (freeSlotsPerResource.get(resource.id) ?? 0) + 1);
|
|
3123
|
-
byInstant.set(+slot.startAt, entry);
|
|
3124
|
-
}
|
|
3125
|
-
}
|
|
3126
|
-
const inWindow = grids.map(({ resource, slots: slots2 }) => {
|
|
3127
|
-
const free = freeSlotsPerResource.get(resource.id) ?? 0;
|
|
3128
|
-
return {
|
|
3129
|
-
resourceId: resource.id,
|
|
3130
|
-
name: resource.name,
|
|
3131
|
-
slots: slots2.length,
|
|
3132
|
-
free,
|
|
3133
|
-
// Lazily: the shift grid is a second walk, and only an empty answer needs it.
|
|
3134
|
-
state: stateFor(
|
|
3135
|
-
() => buildGrid(rule, resource.timeZone, from, to, now).filter(
|
|
3136
|
-
(slot) => withinPresence(slot, resource.timeZone, resource.presence)
|
|
3137
|
-
).length > 0,
|
|
3138
|
-
slots2.length,
|
|
3139
|
-
free
|
|
3140
|
-
)
|
|
3141
|
-
};
|
|
3142
|
-
});
|
|
3143
|
-
const slots = [...byInstant.values()].sort((first, second) => +first.startAt - +second.startAt);
|
|
3144
|
-
return {
|
|
3145
|
-
...header,
|
|
3146
|
-
resources: inWindow,
|
|
3147
|
-
slots,
|
|
3148
|
-
/**
|
|
3149
|
-
* The clock every instant above reads on. Returned rather than assumed: without it a caller
|
|
3150
|
-
* has to fetch the zone from somewhere else and hope it is the same one the grid used.
|
|
3151
|
-
*/
|
|
3152
|
-
timeZone: resources[0]?.timeZone ?? null,
|
|
3153
|
-
/** The shop days this answer covers, in order — what a day picker lists. */
|
|
3154
|
-
days: [...new Set(slots.map((slot) => slot.dayKey))]
|
|
3155
|
-
};
|
|
3156
|
-
}
|
|
3157
|
-
function presentAt(resources, rows, outletId) {
|
|
3158
|
-
const byResource = /* @__PURE__ */ new Map();
|
|
3159
|
-
for (const row of rows) {
|
|
3160
|
-
byResource.set(row.resourceId, [...byResource.get(row.resourceId) ?? [], row]);
|
|
3161
|
-
}
|
|
3162
|
-
return resources.flatMap((resource) => {
|
|
3163
|
-
const own = byResource.get(resource.id) ?? [];
|
|
3164
|
-
if (own.length === 0 || !outletId) return [{ resource }];
|
|
3165
|
-
const here = own.find((row) => row.outletId === outletId);
|
|
3166
|
-
return here ? [{ resource, presence: here.weeklyHours }] : [];
|
|
3167
|
-
});
|
|
3168
|
-
}
|
|
3169
|
-
|
|
3170
|
-
// booking/plan.ts
|
|
3171
|
-
var DEFAULT_HOLD_MINUTES = 10;
|
|
3172
|
-
function planWindow({ rule, timeZone, presence, startAt, endAt, now, busy = [] }) {
|
|
3173
|
-
const grid = buildGrid(rule, timeZone, startAt, endAt, now, busy).filter(
|
|
3174
|
-
(slot) => withinPresence(slot, timeZone, presence)
|
|
3175
|
-
);
|
|
3176
|
-
const slots = slotsForWindow(grid, startAt, endAt);
|
|
3177
|
-
const { minStay, maxStay } = rule.slot;
|
|
3178
|
-
if (minStay && slots.length < minStay) {
|
|
3179
|
-
throw new BookingRulesError(`These rules ask for at least ${minStay} period(s), got ${slots.length}`);
|
|
3180
|
-
}
|
|
3181
|
-
if (maxStay && slots.length > maxStay) {
|
|
3182
|
-
throw new BookingRulesError(`These rules allow at most ${maxStay} period(s), got ${slots.length}`);
|
|
3183
|
-
}
|
|
3184
|
-
const last = slots[slots.length - 1];
|
|
3185
|
-
return { slots, endAt: last.endAt, bufferEndAt: last.bufferEndAt };
|
|
2783
|
+
function adyenTaxNumberFormat(alpha2) {
|
|
2784
|
+
return alpha2 ? ADYEN_TAX_NUMBER_FORMATS[alpha2] : void 0;
|
|
3186
2785
|
}
|
|
3187
|
-
var
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
function isAdyenRolloutCountry(alpha2) {
|
|
3192
|
-
return ADYEN_ROLLOUT_COUNTRY_CODES.has(alpha2);
|
|
2786
|
+
var ADYEN_TAX_NUMBER_MIN_LENGTH = 5;
|
|
2787
|
+
var ADYEN_JOB_TITLE_ASSOCIATION_TYPES = ["signatory", "uboThroughControl"];
|
|
2788
|
+
function adyenRequiresJobTitle(associationType) {
|
|
2789
|
+
return ADYEN_JOB_TITLE_ASSOCIATION_TYPES.includes(associationType);
|
|
3193
2790
|
}
|
|
3194
2791
|
export {
|
|
2792
|
+
ADYEN_JOB_TITLE_ASSOCIATION_TYPES,
|
|
2793
|
+
ADYEN_LEGAL_ENTITY_STATE_PROVINCE_COUNTRIES,
|
|
2794
|
+
ADYEN_NO_TAX_NUMBER_ABSENT_COUNTRIES,
|
|
3195
2795
|
ADYEN_ROLLOUT_COUNTRY_CODES,
|
|
2796
|
+
ADYEN_STORE_STATE_PROVINCE_COUNTRIES,
|
|
2797
|
+
ADYEN_TAX_NUMBER_FORMATS,
|
|
2798
|
+
ADYEN_TAX_NUMBER_MIN_LENGTH,
|
|
3196
2799
|
AttributeType,
|
|
3197
|
-
BookingRatePeriod,
|
|
3198
|
-
BookingResourceKind,
|
|
3199
|
-
BookingResourceStatus,
|
|
3200
|
-
BookingRulesError,
|
|
3201
|
-
BookingType,
|
|
3202
2800
|
CONDITION_OPERATORS,
|
|
3203
2801
|
COUNTRY_CURRENCIES,
|
|
3204
2802
|
CURRENCY_CONFIG,
|
|
@@ -3209,7 +2807,6 @@ export {
|
|
|
3209
2807
|
DEFAULT_CONFIG,
|
|
3210
2808
|
DEFAULT_CROSS_AXIS_RULES,
|
|
3211
2809
|
DEFAULT_DISPLAY_STATE_MAP,
|
|
3212
|
-
DEFAULT_HOLD_MINUTES,
|
|
3213
2810
|
DEFAULT_RESOLVED_CONFIG,
|
|
3214
2811
|
DEFAULT_UNIT_ID,
|
|
3215
2812
|
DualWriteStrategy,
|
|
@@ -3253,10 +2850,8 @@ export {
|
|
|
3253
2850
|
REPORT_NEGATE_PATHS,
|
|
3254
2851
|
ReceiptSendChannel,
|
|
3255
2852
|
ReceiptType,
|
|
3256
|
-
ReservationStatus,
|
|
3257
2853
|
ResidualPaymentMethod,
|
|
3258
2854
|
ResidualStatus,
|
|
3259
|
-
ResourceAvailabilityState,
|
|
3260
2855
|
STATE_SCHEMA,
|
|
3261
2856
|
STRIPE_SUPPORTED_COUNTRIES,
|
|
3262
2857
|
SYSTEM_FAMILIES,
|
|
@@ -3270,6 +2865,11 @@ export {
|
|
|
3270
2865
|
TopMetericsSort,
|
|
3271
2866
|
UserTypes,
|
|
3272
2867
|
addAmounts,
|
|
2868
|
+
adyenLegalEntityRequiresStateOrProvince,
|
|
2869
|
+
adyenRequiresJobTitle,
|
|
2870
|
+
adyenStoreRequiresStateOrProvince,
|
|
2871
|
+
adyenSupportsTaxNumberAbsent,
|
|
2872
|
+
adyenTaxNumberFormat,
|
|
3273
2873
|
amountToString,
|
|
3274
2874
|
assertUnitSane,
|
|
3275
2875
|
availableIn,
|
|
@@ -3277,8 +2877,6 @@ export {
|
|
|
3277
2877
|
baseFulfillmentDefinitions,
|
|
3278
2878
|
baseOf,
|
|
3279
2879
|
basePaymentDefinitions,
|
|
3280
|
-
buildAvailability,
|
|
3281
|
-
buildGrid,
|
|
3282
2880
|
buildOrderContext,
|
|
3283
2881
|
buildPosPresetConfig,
|
|
3284
2882
|
buildResolvedConfig,
|
|
@@ -3318,7 +2916,6 @@ export {
|
|
|
3318
2916
|
getPricingRegionFromCountry,
|
|
3319
2917
|
getSettlementTotal,
|
|
3320
2918
|
getTotalCollected,
|
|
3321
|
-
holdExpiresAt,
|
|
3322
2919
|
inferStatesFromLegacyStatus,
|
|
3323
2920
|
isAdyenRolloutCountry,
|
|
3324
2921
|
isConditionOperator,
|
|
@@ -3333,12 +2930,9 @@ export {
|
|
|
3333
2930
|
mergeFragment,
|
|
3334
2931
|
multiplyAmount,
|
|
3335
2932
|
normalizeMongoIdString,
|
|
3336
|
-
occupancyIn,
|
|
3337
2933
|
parseAmountToMinorUnits,
|
|
3338
2934
|
parseCurrencyCode,
|
|
3339
2935
|
parseStripeCurrencyCode,
|
|
3340
|
-
planWindow,
|
|
3341
|
-
presentAt,
|
|
3342
2936
|
removeFragment,
|
|
3343
2937
|
resolveFamily,
|
|
3344
2938
|
resolveTemplate,
|
|
@@ -3346,18 +2940,13 @@ export {
|
|
|
3346
2940
|
roundToPrecision,
|
|
3347
2941
|
sameFamily,
|
|
3348
2942
|
setOrderState,
|
|
3349
|
-
shopDayKey,
|
|
3350
|
-
shopDayRange,
|
|
3351
2943
|
signReportForDisplay,
|
|
3352
|
-
slotsForWindow,
|
|
3353
2944
|
stringifyMinorUnits,
|
|
3354
2945
|
subtractAmounts,
|
|
3355
2946
|
toBase,
|
|
3356
2947
|
toMinorUnits,
|
|
3357
2948
|
validateConfig,
|
|
3358
2949
|
validateFragmentCompatibility,
|
|
3359
|
-
violatesFinancialInvariant
|
|
3360
|
-
windowEndsAt,
|
|
3361
|
-
withinPresence
|
|
2950
|
+
violatesFinancialInvariant
|
|
3362
2951
|
};
|
|
3363
2952
|
//# sourceMappingURL=index.mjs.map
|